├── .babelrc
├── .dockerignore
├── .env.sample
├── .gitignore
├── .vscode
└── sftp.json
├── @types
├── global.d.ts
├── less.d.ts
├── node.d.ts
├── redux.d.ts
├── videojs.d.ts
└── window.d.ts
├── README.md
├── env.example
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── 403.tsx
├── 404.tsx
├── _app.tsx
├── _document.tsx
├── _error.tsx
├── about-us
│ ├── index.less
│ └── index.tsx
├── account
│ ├── performer
│ │ ├── account-settings
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ ├── earning
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ ├── galleries
│ │ │ ├── add.tsx
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── update.tsx
│ │ ├── geo-block
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ ├── orders
│ │ │ ├── detail.tsx
│ │ │ └── index.tsx
│ │ ├── payout-requests
│ │ │ ├── create.tsx
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── update.tsx
│ │ ├── photos
│ │ │ ├── add.tsx
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── update.tsx
│ │ ├── products
│ │ │ ├── add.tsx
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── update.tsx
│ │ ├── profile
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ ├── schedules
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ └── videos
│ │ │ ├── add.tsx
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── update.tsx
│ └── user
│ │ ├── account-settings
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── favorites
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── funds-tokens
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── orders
│ │ ├── detail.tsx
│ │ └── index.tsx
│ │ ├── payment-token-history
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── purchased-gallery
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── purchased-product
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── purchased-video
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── refund-request
│ │ ├── index.tsx
│ │ └── request.tsx
│ │ └── transaction-history
│ │ ├── index.less
│ │ └── index.tsx
├── auth
│ ├── forgot-password
│ │ └── index.tsx
│ ├── index.less
│ ├── login
│ │ ├── performer.tsx
│ │ └── user.tsx
│ ├── register
│ │ ├── model.tsx
│ │ └── user.tsx
│ └── resend-verification-email
│ │ └── index.tsx
├── contact-us
│ ├── index.less
│ └── index.tsx
├── faq
│ ├── Faqs.js
│ └── index.tsx
├── galleries
│ └── index.tsx
├── how-it-works
│ ├── index.less
│ └── index.tsx
├── index.tsx
├── live
│ ├── groupchat.tsx
│ ├── index.less
│ ├── index.tsx
│ ├── privatechat.tsx
│ └── webrtc
│ │ ├── groupchat.tsx
│ │ └── privatechat.tsx
├── livecam
│ └── index.tsx
├── mental-health-conditions
│ ├── index.less
│ └── index.tsx
├── messages
│ └── index.tsx
├── our-therapists
│ ├── index.less
│ └── index.tsx
├── page
│ └── index.tsx
├── photos
│ ├── index.less
│ └── index.tsx
├── privacy-policy
│ ├── index.less
│ └── index.tsx
├── products
│ └── index.tsx
├── stream
│ ├── groupchat.tsx
│ ├── index.less
│ ├── index.tsx
│ ├── privatechat.tsx
│ └── webrtc
│ │ ├── groupchat.tsx
│ │ └── privatechat.tsx
├── studio
│ ├── account-settings.tsx
│ ├── commissions
│ │ ├── index.less
│ │ └── index.tsx
│ ├── earning
│ │ ├── index.less
│ │ └── index.tsx
│ ├── index.tsx
│ ├── login.tsx
│ ├── models
│ │ ├── add.tsx
│ │ ├── index.less
│ │ ├── index.tsx
│ │ └── stats.tsx
│ ├── payout-requests
│ │ ├── create.tsx
│ │ ├── index.less
│ │ ├── index.tsx
│ │ ├── performer-requests.tsx
│ │ └── update.tsx
│ └── register.tsx
├── tag
│ ├── index.less
│ └── index.tsx
├── terms-conditions
│ ├── index.less
│ └── index.tsx
├── type-of-therapy
│ ├── index.less
│ └── index.tsx
├── videos
│ ├── detail.tsx
│ ├── index.less
│ └── index.tsx
└── work-with-us
│ ├── index.less
│ └── index.tsx
├── public
├── 1.png
├── background-login.jpg
├── background-responsive.svg
├── banner-bottom.png
├── crown - Copy.png
├── css
│ ├── antd.min.css
│ └── dark-theme.js
├── default-user-icon.png
├── emotion-ico.png
├── favicon.ico
├── feature-1.png
├── feature-2.png
├── feature-4.png
├── fonts
│ ├── Flaticon.eot
│ ├── Flaticon.svg
│ ├── Flaticon.ttf
│ ├── Flaticon.woff
│ ├── Flaticon.woff2
│ ├── Roboto
│ │ ├── LICENSE.txt
│ │ ├── Roboto-Black.ttf
│ │ ├── Roboto-BlackItalic.ttf
│ │ ├── Roboto-Bold.ttf
│ │ ├── Roboto-BoldItalic.ttf
│ │ ├── Roboto-Italic.ttf
│ │ ├── Roboto-Light.ttf
│ │ ├── Roboto-LightItalic.ttf
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-MediumItalic.ttf
│ │ ├── Roboto-Regular.ttf
│ │ ├── Roboto-Thin.ttf
│ │ └── Roboto-ThinItalic.ttf
│ ├── boxicons.eot
│ ├── boxicons.svg
│ ├── boxicons.ttf
│ ├── boxicons.woff
│ └── boxicons.woff2
├── gallery.png
├── group.png
├── icons
│ ├── Group 532.svg
│ ├── Payment Tokens history.svg
│ ├── Performer payout.svg
│ ├── Transaction history.svg
│ ├── add-circle.svg
│ ├── chat-settings.svg
│ ├── checkbox.svg
│ ├── coinbase-logo.svg
│ ├── commission.svg
│ ├── delete.svg
│ ├── down filled.svg
│ ├── earnings.svg
│ ├── expand-outlined.svg
│ ├── eye.svg
│ ├── facebook.svg
│ ├── favourite.svg
│ ├── female-sign.svg
│ ├── filter.svg
│ ├── geo-blocking.svg
│ ├── gift.svg
│ ├── group.svg
│ ├── images.svg
│ ├── instagram.svg
│ ├── jam_transgender.svg
│ ├── left-directional.svg
│ ├── male-sign.svg
│ ├── message.svg
│ ├── models.svg
│ ├── mute.svg
│ ├── my-products.svg
│ ├── payout request.svg
│ ├── payout requests.svg
│ ├── performer sats.svg
│ ├── product.svg
│ ├── profile.svg
│ ├── purchased-image.svg
│ ├── purchased-items.svg
│ ├── purchased-videos.svg
│ ├── right-directional.svg
│ ├── schedules.svg
│ ├── search.svg
│ ├── send.svg
│ ├── settings.svg
│ ├── smily.svg
│ ├── star-outlined.svg
│ ├── stop broadcasrting.svg
│ ├── tokens.svg
│ ├── twitter.svg
│ ├── upload file.svg
│ ├── video.svg
│ ├── video1.svg
│ └── volume-full.svg
├── img
│ ├── 123.mp4
│ ├── about
│ │ ├── about-shape-1.png
│ │ ├── about-shape-2.png
│ │ ├── about-shape-3.png
│ │ └── about1.jpg
│ ├── appointment-bg-2.png
│ ├── appointment-bg.jpg
│ ├── appointment-bg3.jpg
│ ├── client
│ │ ├── client-bg.jpg
│ │ ├── client1.jpg
│ │ ├── client2.jpg
│ │ ├── client3.jpg
│ │ ├── client4.jpg
│ │ ├── client5.jpg
│ │ └── client6.jpg
│ ├── doctors
│ │ ├── doctor1.png
│ │ ├── doctor10.png
│ │ ├── doctor11.png
│ │ ├── doctor12.png
│ │ ├── doctor13.jpg
│ │ ├── doctor14.jpg
│ │ ├── doctor15.jpg
│ │ ├── doctor2.png
│ │ ├── doctor3.png
│ │ ├── doctor4.jpg
│ │ ├── doctor5.jpg
│ │ ├── doctor6.jpg
│ │ ├── doctor7.jpg
│ │ ├── doctor8.jpg
│ │ └── doctor9.jpg
│ ├── facility-img
│ │ ├── New folder
│ │ │ ├── facility-icon1.png
│ │ │ ├── facility-icon2.png
│ │ │ ├── facility-icon3.png
│ │ │ └── facility-icon4.png
│ │ ├── facility-icon1.png
│ │ ├── facility-icon2.png
│ │ ├── facility-icon3.png
│ │ ├── facility-icon4.png
│ │ ├── facility-icon5.png
│ │ ├── facility-icon6.png
│ │ └── facility-shape-img.png
│ ├── facility-shape.png
│ ├── footer-bg.jpg
│ ├── home-seven
│ │ ├── home-seven-banner1.jpg
│ │ ├── home-seven-banner2.jpg
│ │ └── home-seven-banner3.jpg
│ ├── log-in-img.jpg
│ ├── logo.png
│ ├── page-banner-bg1.jpg
│ ├── page-banner-bg2.jpg
│ ├── page-banner-bg3.jpg
│ ├── page-banner-bg4.jpg
│ ├── prevention-shape-2.png
│ ├── professional-register
│ │ ├── doctor-image-two.png
│ │ ├── img-doctor.png
│ │ ├── money.svg
│ │ ├── reliable.svg
│ │ └── time.svg
│ ├── services-bg.jpg
│ ├── services-card-shape.png
│ ├── shape
│ │ ├── appointment-shape.png
│ │ ├── counter-shape.png
│ │ ├── emergency-shape.png
│ │ ├── shape1.png
│ │ └── work-shape.png
│ ├── sign-in-img.jpg
│ └── work-bg.jpg
├── index.html
├── lib
│ ├── adapter-latest.js
│ └── webrtc_adaptor.js
├── loading-ico.gif
├── logo.png
├── logo1.png
├── logo3.png
├── logo5.png
├── no-avatar.png
├── no-image.jpg
├── offline.png
├── online.png
├── paperclip-ico.png
├── private.png
├── robots.txt
├── sounds
│ └── default-audio.mp3
├── under-construction.jpg
├── user.png
├── xcam-logo-black.png
└── xcam-logo-primary-color.png
├── server
├── index.ts
└── routes.ts
├── src
├── antmedia
│ ├── LocalStream.tsx
│ ├── constants.ts
│ ├── index.tsx
│ ├── interfaces
│ │ ├── Device.ts
│ │ ├── IceServer.ts
│ │ ├── WebRTCAdaptor.ts
│ │ ├── WebRTCAdaptorConfigs.ts
│ │ └── index.ts
│ └── utils.ts
├── components
│ ├── auth
│ │ ├── login
│ │ │ ├── footer-login-form.tsx
│ │ │ ├── performer-login-form.tsx
│ │ │ └── user-login-form.tsx
│ │ ├── password-change.tsx
│ │ └── register
│ │ │ ├── ProfessionalRegister.tsx
│ │ │ ├── hooks
│ │ │ └── useWorkWithUs.tsx
│ │ │ ├── model-register-form.tsx
│ │ │ ├── studio-register-form.tsx
│ │ │ ├── user-register-form.tsx
│ │ │ └── work-with-us-steps.tsx
│ ├── coinbase
│ │ ├── CoinbasePayment.tsx
│ │ └── index.less
│ ├── commission
│ │ ├── commission-card.less
│ │ └── commission-card.tsx
│ ├── common
│ │ ├── base
│ │ │ ├── drop-option.tsx
│ │ │ ├── icons.tsx
│ │ │ ├── input-item-list.tsx
│ │ │ ├── list-item.tsx
│ │ │ ├── loader.less
│ │ │ ├── loader.tsx
│ │ │ ├── nav.tsx
│ │ │ ├── popup-commission.tsx
│ │ │ ├── popup.less
│ │ │ ├── popup.tsx
│ │ │ ├── scroll-bar.less
│ │ │ ├── scroll-bar.tsx
│ │ │ ├── select
│ │ │ │ ├── countries.tsx
│ │ │ │ ├── galleries.tsx
│ │ │ │ ├── profile.tsx
│ │ │ │ └── timezones.tsx
│ │ │ ├── tabs.tsx
│ │ │ ├── token-card.less
│ │ │ ├── token-card.tsx
│ │ │ └── trash.tsx
│ │ ├── index.tsx
│ │ ├── layout
│ │ │ ├── NFooter.js
│ │ │ ├── banner.less
│ │ │ ├── banner.tsx
│ │ │ ├── footer.less
│ │ │ ├── footer.tsx
│ │ │ ├── form-register-placeholder.tsx
│ │ │ ├── header.less
│ │ │ ├── header.tsx
│ │ │ ├── index.ts
│ │ │ ├── left-header-content.less
│ │ │ ├── left-header-content.tsx
│ │ │ ├── menu.tsx
│ │ │ ├── numberformat.tsx
│ │ │ ├── page-header.tsx
│ │ │ ├── page.less
│ │ │ ├── page.tsx
│ │ │ ├── popup-18plus-content.less
│ │ │ ├── popup-18plus-content.tsx
│ │ │ ├── sider.less
│ │ │ └── sider.tsx
│ │ ├── recaptcha.less
│ │ └── recaptcha.tsx
│ ├── file
│ │ └── image-upload.tsx
│ ├── galleries
│ │ ├── gallery-card.tsx
│ │ ├── gallery-dashboard-grid.tsx
│ │ ├── index.less
│ │ └── purchased-gallery-card.tsx
│ ├── homepage
│ │ ├── AboutUs.js
│ │ ├── DoctorsStyleOne.js
│ │ ├── EmergencyArea.js
│ │ ├── Facility.js
│ │ ├── FunFactStyleOne.js
│ │ ├── MainBanner.js
│ │ ├── PageBanner.js
│ │ ├── Services.js
│ │ ├── Subscribe.js
│ │ └── TestimonialStyleOne.js
│ ├── messages
│ │ ├── Compose.tsx
│ │ ├── ConversationList.less
│ │ ├── ConversationList.tsx
│ │ ├── ConversationListItem.less
│ │ ├── ConversationListItem.tsx
│ │ ├── ConversationSearch.less
│ │ ├── ConversationSearch.tsx
│ │ ├── Message.tsx
│ │ ├── MessageList.tsx
│ │ ├── Messenger.tsx
│ │ ├── emotions.tsx
│ │ └── uploadPhoto.tsx
│ ├── order
│ │ ├── detail.less
│ │ ├── form-order.tsx
│ │ ├── index.ts
│ │ ├── order-status.tsx
│ │ ├── search-filter.tsx
│ │ └── table-list.tsx
│ ├── payment
│ │ ├── bitpay-form.tsx
│ │ ├── direct-deposit-form.tsx
│ │ ├── index.ts
│ │ ├── issue-check-us-setting-form.tsx
│ │ ├── paxum-form.tsx
│ │ ├── paypal-setting-form.tsx
│ │ └── wire-transfer-setting-form.tsx
│ ├── payout-request
│ │ ├── form.tsx
│ │ ├── index.less
│ │ ├── studio-performer-request-table.tsx
│ │ └── table.tsx
│ ├── paypal
│ │ └── PaypalPayment.tsx
│ ├── performer-assets
│ │ ├── common
│ │ │ ├── modal-buy-assets.less
│ │ │ └── modal-buy-assets.tsx
│ │ ├── gallery-carousel
│ │ │ ├── index.less
│ │ │ └── index.tsx
│ │ ├── product-carousel
│ │ │ ├── index.tsx
│ │ │ ├── product-carousel.less
│ │ │ └── product-item.tsx
│ │ └── video-carousel
│ │ │ ├── index.less
│ │ │ ├── index.tsx
│ │ │ └── video-item.tsx
│ ├── performer
│ │ ├── broadcast-setting-form.tsx
│ │ ├── contact-setting-form.tsx
│ │ ├── documents-setting-form.tsx
│ │ ├── earning-history-table.tsx
│ │ ├── earning-independent-table.tsx
│ │ ├── earning-studio-operated-table.tsx
│ │ ├── index.less
│ │ ├── index.tsx
│ │ ├── performer-carousel.less
│ │ ├── performer-carousel.tsx
│ │ ├── performer-grid.tsx
│ │ ├── performer-username.tsx
│ │ ├── profile-card.tsx
│ │ ├── profile-detail.less
│ │ ├── profile-detail.tsx
│ │ ├── profile-edit-form.tsx
│ │ ├── settings
│ │ │ ├── default-price-form.tsx
│ │ │ └── disable-account-form.tsx
│ │ └── streaming-status-update-form.tsx
│ ├── photos
│ │ ├── gallery-form.tsx
│ │ ├── index.less
│ │ ├── photo-dashboard-grid.tsx
│ │ └── photo-form.tsx
│ ├── products
│ │ ├── index.less
│ │ ├── product-card.tsx
│ │ ├── products-form.tsx
│ │ └── products-table.tsx
│ ├── refund-request
│ │ ├── form.tsx
│ │ └── table-list.tsx
│ ├── schedules
│ │ └── form.tsx
│ ├── stream-chat
│ │ ├── Compose.less
│ │ ├── Compose.tsx
│ │ ├── Message.less
│ │ ├── Message.tsx
│ │ ├── MessageList.less
│ │ ├── MessageList.tsx
│ │ ├── Messenger.less
│ │ ├── Messenger.tsx
│ │ ├── UserList.tsx
│ │ ├── chat-box.less
│ │ ├── chat-box.tsx
│ │ └── emotions.tsx
│ ├── streaming
│ │ ├── ant-media-player.tsx
│ │ ├── contants.ts
│ │ ├── description.tsx
│ │ ├── footer.less
│ │ ├── footer.tsx
│ │ ├── group-streaming-container.less
│ │ ├── group-streaming-container.tsx
│ │ ├── header.less
│ │ ├── header.tsx
│ │ ├── index.less
│ │ ├── index.tsx
│ │ ├── private-streaming-container.less
│ │ ├── private-streaming-container.tsx
│ │ ├── publisher.tsx
│ │ ├── subscriber.tsx
│ │ ├── tip
│ │ │ ├── content.less
│ │ │ └── content.tsx
│ │ └── webrtc
│ │ │ ├── groupchat
│ │ │ ├── publisher.tsx
│ │ │ └── subscriber.tsx
│ │ │ └── privatechat
│ │ │ ├── index.less
│ │ │ ├── publisher.tsx
│ │ │ └── subscriber.tsx
│ ├── studio
│ │ ├── account-information.tsx
│ │ ├── index.less
│ │ ├── models-manager
│ │ │ ├── search-online-status.tsx
│ │ │ ├── studio-add-model-form.tsx
│ │ │ ├── studio-commissions-table.tsx
│ │ │ ├── studio-models-stats-table.tsx
│ │ │ └── studio-models-table.tsx
│ │ ├── payout-request
│ │ │ └── studio-payout-request-table.tsx
│ │ ├── studio-commission-table.tsx
│ │ ├── studio-earning-table.tsx
│ │ └── studio-login-form.tsx
│ ├── transaction
│ │ └── table-list.tsx
│ ├── user
│ │ ├── avatar-upload.tsx
│ │ ├── favourite-performer-grid.less
│ │ ├── favourite-performer-grid.tsx
│ │ ├── payment-token-history-table.tsx
│ │ ├── performer-filter.less
│ │ ├── performer-filter.tsx
│ │ ├── profile.less
│ │ ├── profile.tsx
│ │ └── update-password-form.tsx
│ └── videos
│ │ ├── index.less
│ │ ├── popup-video.tsx
│ │ ├── purchased-video-card.tsx
│ │ ├── video-form.tsx
│ │ ├── video-grid.tsx
│ │ └── video-single-card.tsx
├── constants.tsx
├── interfaces
│ ├── auth.ts
│ ├── banner.ts
│ ├── earning.ts
│ ├── favourite.ts
│ ├── index.ts
│ ├── order.ts
│ ├── payout-request.ts
│ ├── peformer-assets.ts
│ ├── performer-categories.ts
│ ├── performer.ts
│ ├── photo.ts
│ ├── post.ts
│ ├── redux.ts
│ ├── refund-request.ts
│ ├── setting.ts
│ ├── stream.ts
│ ├── studio.ts
│ ├── token-package.ts
│ ├── transaction.ts
│ ├── ui-config.ts
│ ├── user.ts
│ └── utils.ts
├── layouts
│ ├── auth-layout.less
│ ├── auth-layout.tsx
│ ├── base-layout.tsx
│ ├── default-layout.less
│ ├── default-layout.tsx
│ ├── maintenance-layout.tsx
│ ├── primary-layout.less
│ ├── primary-layout.tsx
│ ├── public-layout.less
│ └── public-layout.tsx
├── lib
│ ├── date.ts
│ ├── file.ts
│ ├── index.ts
│ ├── internet.ts
│ ├── layout.ts
│ ├── message.ts
│ ├── redux.ts
│ ├── rules.ts
│ ├── storeHolder.ts
│ ├── stream.ts
│ ├── string.ts
│ └── utils.ts
├── redux
│ ├── actions.ts
│ ├── auth
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── banner
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── galleries
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── message
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── performer
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── photos
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── products
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── rootReducer.ts
│ ├── rootSaga.ts
│ ├── selectors.ts
│ ├── settings
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── store.ts
│ ├── stream-chat
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── streaming
│ │ ├── actions.ts
│ │ └── reducers.ts
│ ├── studio
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── ui
│ │ ├── actions.ts
│ │ └── reducers.ts
│ ├── user
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ ├── videos
│ │ ├── actions.ts
│ │ ├── reducers.ts
│ │ └── sagas.ts
│ └── withReduxSaga.ts
├── services
│ ├── api-request.ts
│ ├── auth.service.ts
│ ├── banner.service.ts
│ ├── coinbase.service.ts
│ ├── config.ts
│ ├── earning.service.ts
│ ├── favourite.service.ts
│ ├── gallery.service.ts
│ ├── index.ts
│ ├── message.service.ts
│ ├── order.service.ts
│ ├── payment-information.service.ts
│ ├── payout-request.ts
│ ├── paypal.service.ts
│ ├── perfomer-categories.service.ts
│ ├── perfomer.service.ts
│ ├── photo.service.ts
│ ├── post.service.ts
│ ├── product.service.ts
│ ├── purchase-item.service.ts
│ ├── refund-request.service.ts
│ ├── setting.service.ts
│ ├── stream.service.tsx
│ ├── studio.service.ts
│ ├── token-package.service.ts
│ ├── transaction.service.ts
│ ├── user.service.ts
│ ├── utils.service.ts
│ └── video.service.ts
├── socket
│ ├── Event.tsx
│ ├── Socket.tsx
│ ├── SocketContext.tsx
│ ├── index.ts
│ └── utils.ts
└── videojs
│ ├── contants.ts
│ └── mic-controls
│ ├── audio-mute-toggle-button.ts
│ └── plugin.ts
├── style
├── animate.css
├── bootstrap.min.css
├── boxicons.min.css
├── default.less
├── flaticon.css
├── index.less
├── meanmenu.css
├── mixin.less
├── responsive.css
├── responsive.css.map
├── responsive.scss
├── style.css
├── style.css.map
├── style.scss
├── vars.less
└── videojs.less
├── tsconfig.json
├── tsconfig.server.json
└── utils
├── ActiveLink.js
└── baseUrl.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["next/babel"],
3 | "plugins": [
4 | [
5 | "import",
6 | {
7 | "libraryName": "antd",
8 | "libraryDirectory": "lib",
9 | "style": true
10 | }
11 | ]
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
3 | .git
4 | .gitignore
5 |
--------------------------------------------------------------------------------
/.env.sample:
--------------------------------------------------------------------------------
1 | # http port
2 | PORT=8081
3 |
4 | NEXT_PUBLIC_DEBUG=false
5 |
6 | NODE_ENV=development
7 | # api endpoint we can call in the server side, if single server it can run to api:port without proxy
8 | API_ENDPOINT=http://localhost:8080
9 | NEXT_PUBLIC_API_ENDPOINT=http://localhost:8080
10 | NEXT_PUBLIC_SOCKET_ENDPOINT=http://localhost:8080
11 |
12 | # upload file
13 | NEXT_PUBLIC_MAX_VIDEO_BITRATE_KBPS=900
14 | NEXT_PUBLIC_IMAGE_ACCPET=.jpeg, .jpg, .png
15 | NEXT_PUBLIC_MAXIMUM_SIZE_UPLOAD_AVATAR=2
16 |
17 | #paypal client id
18 | NEXT_PUBLIC_PAYPAL_CLIENT_ID="paypal-client-id"
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 |
15 | .env
16 | dist/
17 | .dockerenv
18 | Dockerfile
19 |
--------------------------------------------------------------------------------
/.vscode/sftp.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "My Server",
3 | "host": "149.102.147.191",
4 | "protocol": "sftp",
5 | "port": 22,
6 | "username": "root",
7 | "remotePath": "/",
8 | "uploadOnSave": false,
9 | "useTempFile": false,
10 | "openSsh": false
11 | }
12 |
--------------------------------------------------------------------------------
/@types/global.d.ts:
--------------------------------------------------------------------------------
1 | declare global {
2 | interface File {
3 | ReactSocketIO: any;
4 | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any;
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/@types/less.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.less' {
2 | const resource: {[key: string]: string};
3 | export = resource;
4 | }
--------------------------------------------------------------------------------
/@types/node.d.ts:
--------------------------------------------------------------------------------
1 | declare module NodeJS {
2 | interface Process extends NodeJS.Process {
3 | browser?: string;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/@types/redux.d.ts:
--------------------------------------------------------------------------------
1 | import * as Redux from "redux"
2 | import { Task } from "redux-saga";
3 |
4 | declare module "redux" {
5 | export interface Store {
6 | sagaTask: Task
7 | }
8 | }
--------------------------------------------------------------------------------
/@types/videojs.d.ts:
--------------------------------------------------------------------------------
1 | import 'video.js';
2 |
3 | declare module 'video.js' {
4 | export interface VideoJsPlayer {
5 | webRTCMicControlsPlugin: (options?: any) => void;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/@types/window.d.ts:
--------------------------------------------------------------------------------
1 | import ReCAPTCHA from 'react-google-recaptcha';
2 |
3 | declare global {
4 | interface Window {
5 | ReactSocketIO: any;
6 | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any;
7 | grecaptcha: ReCAPTCHA;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/env.example:
--------------------------------------------------------------------------------
1 | # http port
2 | PORT=8081
3 |
4 | NEXT_PUBLIC_DEBUG=false
5 |
6 | # api endpoint we can call in the server side, if single server it can run to api:port without proxy
7 | API_ENDPOINT=http://localhost:8080
8 | NEXT_PUBLIC_API_ENDPOINT=https://api.example.com
9 | NEXT_PUBLIC_SOCKET_ENDPOINT=https://api.example.com
10 |
11 | # upload file
12 | NEXT_PUBLIC_MAX_VIDEO_BITRATE_KBPS=900
13 | NEXT_PUBLIC_IMAGE_ACCPET=.jpeg, .jpg, .png
14 | NEXT_PUBLIC_MAXIMUM_SIZE_UPLOAD_AVATAR=2
15 |
16 | #paypal client id
17 | NEXT_PUBLIC_PAYPAL_CLIENT_ID="paypal-client-id"
18 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/pages/403.tsx:
--------------------------------------------------------------------------------
1 | import Error from 'next/error';
2 |
3 | interface P {
4 | title?: string;
5 | }
6 | function ErrorForbidden({ title }: P) {
7 | return ;
8 | }
9 | ErrorForbidden.defaultProps = {
10 | title: 'Forbidden Access'
11 | };
12 | ErrorForbidden.layout = 'default';
13 | export default ErrorForbidden;
14 |
--------------------------------------------------------------------------------
/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import Error from 'next/error';
2 |
3 | interface P {
4 | title?: string;
5 | }
6 | function ErrorForbidden({ title }: P) {
7 | return ;
8 | }
9 | ErrorForbidden.defaultProps = {
10 | title: 'Page not found'
11 | };
12 | ErrorForbidden.layout = 'default';
13 | export default ErrorForbidden;
14 |
--------------------------------------------------------------------------------
/pages/_error.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-nested-ternary */
2 | import React from 'react';
3 |
4 | function Error({ statusCode, message = '' }: any) {
5 | return (
6 |
7 | {message
8 | ? `${statusCode} - ${message}`
9 | : statusCode
10 | ? `${statusCode} - An error ${statusCode} occurred on server`
11 | : 'An error occurred on client'}
12 |
13 | );
14 | }
15 |
16 | Error.getInitialProps = ({ res, err }) => {
17 | const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
18 | return { statusCode };
19 | };
20 |
21 | export default Error;
22 |
--------------------------------------------------------------------------------
/pages/about-us/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
--------------------------------------------------------------------------------
/pages/account/performer/account-settings/index.less:
--------------------------------------------------------------------------------
1 | .account-setting-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/performer/earning/index.less:
--------------------------------------------------------------------------------
1 | .earning-history-page {
2 | background-color: white;
3 | height: 100%;
4 | .table {
5 | .admin-to-studio-transaction,
6 | .studio-to-model-transaction {
7 | background: #99ff99;
8 | }
9 |
10 | .ant-table-tbody {
11 |
12 | // Fix css when table has no data
13 | .ant-table-expanded-row-fixed {
14 | width: auto !important;
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/pages/account/performer/galleries/index.less:
--------------------------------------------------------------------------------
1 | .performer-gallries-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/performer/geo-block/index.less:
--------------------------------------------------------------------------------
1 | .geo-blocking-page {
2 | background-color: white;
3 | height: 100%;
4 | padding: 15px;
5 | }
6 |
--------------------------------------------------------------------------------
/pages/account/performer/payout-requests/index.less:
--------------------------------------------------------------------------------
1 | .payout-request-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/performer/photos/index.less:
--------------------------------------------------------------------------------
1 | .performer-photos-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/performer/products/index.less:
--------------------------------------------------------------------------------
1 | .performer-products-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/performer/profile/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/vars.less';
2 |
3 | .performer-profile-page {
4 | background-color: white;
5 | min-height: 100%;
6 |
7 | .performer-profile-list {
8 | color: @regular-text;
9 | .light-text {
10 | color: @light-text;
11 | }
12 |
13 | .ant-card-head, .ant-card-body {
14 | padding: 0 !important;
15 | border-bottom: none !important;
16 | }
17 |
18 | .social-media {
19 | display: flex;
20 | align-items: center;
21 | margin-bottom: 15px;
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/pages/account/performer/schedules/index.less:
--------------------------------------------------------------------------------
1 | .performer-schedule-page {
2 | background-color: white;
3 | }
--------------------------------------------------------------------------------
/pages/account/performer/videos/index.less:
--------------------------------------------------------------------------------
1 | .performer-videos-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/account/user/account-settings/index.less:
--------------------------------------------------------------------------------
1 | .account-setting-page {
2 | background-color: white;
3 | }
--------------------------------------------------------------------------------
/pages/account/user/favorites/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 | .favorite-page {
3 | background-color: @background-container;
4 | min-height: 100%;
5 | }
--------------------------------------------------------------------------------
/pages/account/user/funds-tokens/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 | .funds-tokens-box {
3 | background-color: @background-container;
4 | min-height: 100%;
5 | width: 100%;
6 | }
--------------------------------------------------------------------------------
/pages/account/user/payment-token-history/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 |
3 | .payment-token-history {
4 | background-color: @body-background-color;
5 | }
--------------------------------------------------------------------------------
/pages/account/user/purchased-gallery/index.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/pages/account/user/purchased-gallery/index.less
--------------------------------------------------------------------------------
/pages/account/user/purchased-product/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 |
3 | .purchased-product {
4 | background-color: @body-background-color;
5 | }
--------------------------------------------------------------------------------
/pages/account/user/purchased-video/index.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/pages/account/user/purchased-video/index.less
--------------------------------------------------------------------------------
/pages/account/user/transaction-history/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 | .transaction-history-page {
3 | background-color: @background-container;
4 | min-height: 100%;
5 | width: 100%;
6 | }
--------------------------------------------------------------------------------
/pages/how-it-works/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
4 |
5 | .single-privacy h2{
6 | background: -webkit-linear-gradient(#286be7, #345d9d);
7 | background-clip: border-box;
8 | -webkit-background-clip: text;
9 | -webkit-text-fill-color: transparent
10 | }
11 |
12 | .single-privacy h3{
13 | color: #345d9d;
14 | }
15 |
16 | .single-privacy li{
17 | margin-bottom: 0.5em;
18 | }
--------------------------------------------------------------------------------
/pages/live/index.less:
--------------------------------------------------------------------------------
1 | .conversation {
2 | width: 100%;
3 | height: 100%;
4 | min-height: 320px;
5 | border: solid 1px @primary-color;
6 | border-radius: 15px;
7 | .tablist {
8 | margin: 0;
9 | }
10 | .ant-tabs-nav-list {
11 | width: 100%;
12 | border-top-left-radius: 12px;
13 | border-top-right-radius: 12px;
14 | overflow: hidden;
15 | .ant-tabs-tab {
16 | width: 50%;
17 | justify-content: center;
18 | margin: 0;
19 | }
20 | .ant-tabs-tab-active {
21 | background-color: @primary-color;
22 | .ant-tabs-tab-btn {
23 | color: #fff;
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/pages/mental-health-conditions/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
4 |
5 | .single-privacy h2{
6 | background: -webkit-linear-gradient(#286be7, #345d9d);
7 | background-clip: border-box;
8 | -webkit-background-clip: text;
9 | -webkit-text-fill-color: transparent
10 | }
11 |
12 | .single-privacy h3{
13 | color: #345d9d;
14 | }
15 |
16 | .single-privacy li{
17 | margin-bottom: 0.5em;
18 | }
--------------------------------------------------------------------------------
/pages/messages/index.tsx:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import { connect } from 'react-redux';
3 | import Head from 'next/head';
4 | import { IUIConfig } from 'src/interfaces/';
5 | import Messenger from '@components/messages/Messenger';
6 | import { resetMessageState } from '@redux/message/actions';
7 |
8 | interface IProps {
9 | ui: IUIConfig;
10 | getList: Function;
11 | query: Record;
12 | resetMessageState: Function;
13 | }
14 |
15 | class Messages extends PureComponent {
16 | static authenticate = true;
17 |
18 | static layout = 'primary';
19 |
20 | static getInitialProps({ ctx }) {
21 | return {
22 | query: ctx.query
23 | };
24 | }
25 |
26 | componentWillUnmount() {
27 | const { resetMessageState: resetStateHandler } = this.props;
28 | resetStateHandler();
29 | }
30 |
31 | render() {
32 | const { query = {} } = this.props;
33 | return (
34 | <>
35 |
36 |
37 | Messages
38 |
39 |
40 |
41 | >
42 | );
43 | }
44 | }
45 |
46 | const mapStates = (state: any) => ({
47 | ui: { ...state.ui }
48 | });
49 |
50 | const mapDispatch = { resetMessageState };
51 | export default connect(mapStates, mapDispatch)(Messages);
52 |
--------------------------------------------------------------------------------
/pages/our-therapists/index.less:
--------------------------------------------------------------------------------
1 | .ant-divider-horizontal{
2 | margin: 10px 0;
3 | }
4 |
5 | .ant-page-header{
6 | padding: 20px 29px !important;
7 | }
8 |
9 | .performer-grid{
10 | padding: 0px 19px !important;
11 | }
12 |
--------------------------------------------------------------------------------
/pages/photos/index.less:
--------------------------------------------------------------------------------
1 | @import '../../style/default.less';
2 |
3 | .photo-carousel-content {
4 | padding-right: @content-padding;
5 | padding-left: @content-padding;
6 |
7 | @media (max-width: @mobile-query) {
8 | padding-right: 0;
9 | padding-left: 0;
10 | }
11 | }
12 | .carousel .slide img {
13 | max-height: 500px;
14 | }
--------------------------------------------------------------------------------
/pages/privacy-policy/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
--------------------------------------------------------------------------------
/pages/stream/index.less:
--------------------------------------------------------------------------------
1 | .title {
2 | position: absolute;
3 | bottom: 0;
4 |
5 | @media (max-width: 567px) {
6 | position: relative;
7 | }
8 | }
9 |
10 | .streaming-container {
11 | margin-top: 20px;
12 | margin-bottom: 20px;
13 | min-height: 520px;
14 |
15 | .subscriber {
16 | height: calc(100% - 50px);
17 | width: 100%;
18 | background: #ffffff;
19 | video {
20 | width: 100%;
21 | height: 100%;
22 | }
23 | @media (max-width: 567px) {
24 | height: 480px;
25 | }
26 | }
27 | }
28 |
29 | .profile-page .performer-grid{
30 | min-height: 0 !important;
31 | .ant-card-head {
32 | padding: 0 20px !important;
33 | }
34 | }
--------------------------------------------------------------------------------
/pages/studio/commissions/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/vars';
2 |
3 | .studio-commisson-background {
4 | background-color: white;
5 | height: 100%;
6 | .studio-commisson-box {
7 | padding: 0 24px;
8 | }
9 | }
10 |
11 | .performerEditForm {
12 | @media (max-width: 567px) {
13 | padding-left: 24px;
14 | padding-right: 24px;
15 | }
16 |
17 | .edit-icon {
18 | position: absolute;
19 | font-size: 16px;
20 | bottom: 0px;
21 | right: 0px;
22 | border-radius: 8px;
23 | background: white;
24 | height: 20px;
25 | width: 20px;
26 | display: flex;
27 | align-items: center;
28 | justify-content: center;
29 | }
30 |
31 | label {
32 | font-weight: bold !important;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/pages/studio/earning/index.less:
--------------------------------------------------------------------------------
1 | .earning-history-page {
2 | background-color: white;
3 | height: 100%;
4 | .table {
5 | .ant-table-thead {
6 | .admin-to-studio-transaction,
7 | .studio-to-model-transaction {
8 | background: #99ff99;
9 | }
10 | }
11 |
12 | .ant-table-tbody {
13 |
14 | // Fix css when table has no data
15 | .ant-table-expanded-row-fixed {
16 | width: auto !important;
17 | }
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/pages/studio/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 |
3 | class StudioIndexPage extends PureComponent {
4 | static layout = 'primary';
5 |
6 | static authenticate = 'studio';
7 |
8 | render() {
9 | return <>>;
10 | }
11 | }
12 |
13 | export default StudioIndexPage;
14 |
--------------------------------------------------------------------------------
/pages/studio/models/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/vars';
2 |
3 | .studio-models-background {
4 | background-color: white;
5 | height: 100%;
6 | .studio-models-box {
7 | padding: 0 24px;
8 | }
9 | }
10 |
11 | .performerEditForm {
12 | @media (max-width: 567px) {
13 | padding-left: 24px;
14 | padding-right: 24px;
15 | }
16 |
17 | .edit-icon {
18 | position: absolute;
19 | font-size: 16px;
20 | bottom: 0px;
21 | right: 0px;
22 | border-radius: 8px;
23 | background: white;
24 | height: 20px;
25 | width: 20px;
26 | display: flex;
27 | align-items: center;
28 | justify-content: center;
29 | }
30 |
31 | label {
32 | font-weight: bold !important;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/pages/studio/payout-requests/index.less:
--------------------------------------------------------------------------------
1 | .payout-request-page {
2 | background-color: white;
3 | height: 100%;
4 | }
--------------------------------------------------------------------------------
/pages/tag/index.less:
--------------------------------------------------------------------------------
1 | .filter {
2 | flex-direction: column !important;
3 |
4 | button {
5 | margin: 0 20px;
6 | }
7 | }
--------------------------------------------------------------------------------
/pages/terms-conditions/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
--------------------------------------------------------------------------------
/pages/type-of-therapy/index.less:
--------------------------------------------------------------------------------
1 | .color-blue{
2 | color:darkblue
3 | }
4 |
5 | .single-privacy h2{
6 | background: -webkit-linear-gradient(#286be7, #345d9d);
7 | background-clip: border-box;
8 | -webkit-background-clip: text;
9 | -webkit-text-fill-color: transparent
10 | }
11 |
12 | .single-privacy h3{
13 | color: #345d9d;
14 | }
15 |
16 | .single-privacy li{
17 | margin-bottom: 0.5em;
18 | }
--------------------------------------------------------------------------------
/public/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/1.png
--------------------------------------------------------------------------------
/public/background-login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/background-login.jpg
--------------------------------------------------------------------------------
/public/banner-bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/banner-bottom.png
--------------------------------------------------------------------------------
/public/crown - Copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/crown - Copy.png
--------------------------------------------------------------------------------
/public/default-user-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/default-user-icon.png
--------------------------------------------------------------------------------
/public/emotion-ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/emotion-ico.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/favicon.ico
--------------------------------------------------------------------------------
/public/feature-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/feature-1.png
--------------------------------------------------------------------------------
/public/feature-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/feature-2.png
--------------------------------------------------------------------------------
/public/feature-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/feature-4.png
--------------------------------------------------------------------------------
/public/fonts/Flaticon.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Flaticon.eot
--------------------------------------------------------------------------------
/public/fonts/Flaticon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Flaticon.ttf
--------------------------------------------------------------------------------
/public/fonts/Flaticon.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Flaticon.woff
--------------------------------------------------------------------------------
/public/fonts/Flaticon.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Flaticon.woff2
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/public/fonts/Roboto/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/Roboto/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/boxicons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/boxicons.eot
--------------------------------------------------------------------------------
/public/fonts/boxicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/boxicons.ttf
--------------------------------------------------------------------------------
/public/fonts/boxicons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/boxicons.woff
--------------------------------------------------------------------------------
/public/fonts/boxicons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/fonts/boxicons.woff2
--------------------------------------------------------------------------------
/public/gallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/gallery.png
--------------------------------------------------------------------------------
/public/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/group.png
--------------------------------------------------------------------------------
/public/icons/Group 532.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/add-circle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/chat-settings.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/icons/checkbox.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/public/icons/coinbase-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/public/icons/commission.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/delete.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/down filled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/earnings.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/icons/expand-outlined.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/eye.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/facebook.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/favourite.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/female-sign.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/filter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/gift.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/group.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/icons/images.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/left-directional.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/male-sign.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/message.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/models.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/payout request.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/payout requests.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/performer sats.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/icons/product.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/purchased-items.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/purchased-videos.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/icons/right-directional.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/schedules.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/public/icons/search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/send.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/star-outlined.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/stop broadcasrting.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/upload file.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/video.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/icons/video1.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/icons/volume-full.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/img/123.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/123.mp4
--------------------------------------------------------------------------------
/public/img/about/about-shape-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/about/about-shape-1.png
--------------------------------------------------------------------------------
/public/img/about/about-shape-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/about/about-shape-2.png
--------------------------------------------------------------------------------
/public/img/about/about-shape-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/about/about-shape-3.png
--------------------------------------------------------------------------------
/public/img/about/about1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/about/about1.jpg
--------------------------------------------------------------------------------
/public/img/appointment-bg-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/appointment-bg-2.png
--------------------------------------------------------------------------------
/public/img/appointment-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/appointment-bg.jpg
--------------------------------------------------------------------------------
/public/img/appointment-bg3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/appointment-bg3.jpg
--------------------------------------------------------------------------------
/public/img/client/client-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client-bg.jpg
--------------------------------------------------------------------------------
/public/img/client/client1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client1.jpg
--------------------------------------------------------------------------------
/public/img/client/client2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client2.jpg
--------------------------------------------------------------------------------
/public/img/client/client3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client3.jpg
--------------------------------------------------------------------------------
/public/img/client/client4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client4.jpg
--------------------------------------------------------------------------------
/public/img/client/client5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client5.jpg
--------------------------------------------------------------------------------
/public/img/client/client6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/client/client6.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor1.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor10.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor11.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor12.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor13.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor14.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor15.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor2.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor3.png
--------------------------------------------------------------------------------
/public/img/doctors/doctor4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor4.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor5.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor6.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor7.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor8.jpg
--------------------------------------------------------------------------------
/public/img/doctors/doctor9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/doctors/doctor9.jpg
--------------------------------------------------------------------------------
/public/img/facility-img/New folder/facility-icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/New folder/facility-icon1.png
--------------------------------------------------------------------------------
/public/img/facility-img/New folder/facility-icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/New folder/facility-icon2.png
--------------------------------------------------------------------------------
/public/img/facility-img/New folder/facility-icon3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/New folder/facility-icon3.png
--------------------------------------------------------------------------------
/public/img/facility-img/New folder/facility-icon4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/New folder/facility-icon4.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon1.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon2.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon3.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon4.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon5.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-icon6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-icon6.png
--------------------------------------------------------------------------------
/public/img/facility-img/facility-shape-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-img/facility-shape-img.png
--------------------------------------------------------------------------------
/public/img/facility-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/facility-shape.png
--------------------------------------------------------------------------------
/public/img/footer-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/footer-bg.jpg
--------------------------------------------------------------------------------
/public/img/home-seven/home-seven-banner1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/home-seven/home-seven-banner1.jpg
--------------------------------------------------------------------------------
/public/img/home-seven/home-seven-banner2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/home-seven/home-seven-banner2.jpg
--------------------------------------------------------------------------------
/public/img/home-seven/home-seven-banner3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/home-seven/home-seven-banner3.jpg
--------------------------------------------------------------------------------
/public/img/log-in-img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/log-in-img.jpg
--------------------------------------------------------------------------------
/public/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/logo.png
--------------------------------------------------------------------------------
/public/img/page-banner-bg1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/page-banner-bg1.jpg
--------------------------------------------------------------------------------
/public/img/page-banner-bg2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/page-banner-bg2.jpg
--------------------------------------------------------------------------------
/public/img/page-banner-bg3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/page-banner-bg3.jpg
--------------------------------------------------------------------------------
/public/img/page-banner-bg4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/page-banner-bg4.jpg
--------------------------------------------------------------------------------
/public/img/prevention-shape-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/prevention-shape-2.png
--------------------------------------------------------------------------------
/public/img/professional-register/doctor-image-two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/professional-register/doctor-image-two.png
--------------------------------------------------------------------------------
/public/img/professional-register/img-doctor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/professional-register/img-doctor.png
--------------------------------------------------------------------------------
/public/img/professional-register/reliable.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/public/img/professional-register/time.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/img/services-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/services-bg.jpg
--------------------------------------------------------------------------------
/public/img/services-card-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/services-card-shape.png
--------------------------------------------------------------------------------
/public/img/shape/appointment-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/shape/appointment-shape.png
--------------------------------------------------------------------------------
/public/img/shape/counter-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/shape/counter-shape.png
--------------------------------------------------------------------------------
/public/img/shape/emergency-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/shape/emergency-shape.png
--------------------------------------------------------------------------------
/public/img/shape/shape1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/shape/shape1.png
--------------------------------------------------------------------------------
/public/img/shape/work-shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/shape/work-shape.png
--------------------------------------------------------------------------------
/public/img/sign-in-img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/sign-in-img.jpg
--------------------------------------------------------------------------------
/public/img/work-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/img/work-bg.jpg
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/index.html
--------------------------------------------------------------------------------
/public/loading-ico.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/loading-ico.gif
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/logo.png
--------------------------------------------------------------------------------
/public/logo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/logo1.png
--------------------------------------------------------------------------------
/public/logo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/logo3.png
--------------------------------------------------------------------------------
/public/logo5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/logo5.png
--------------------------------------------------------------------------------
/public/no-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/no-avatar.png
--------------------------------------------------------------------------------
/public/no-image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/no-image.jpg
--------------------------------------------------------------------------------
/public/offline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/offline.png
--------------------------------------------------------------------------------
/public/online.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/online.png
--------------------------------------------------------------------------------
/public/paperclip-ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/paperclip-ico.png
--------------------------------------------------------------------------------
/public/private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/private.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
--------------------------------------------------------------------------------
/public/sounds/default-audio.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/sounds/default-audio.mp3
--------------------------------------------------------------------------------
/public/under-construction.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/under-construction.jpg
--------------------------------------------------------------------------------
/public/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/user.png
--------------------------------------------------------------------------------
/public/xcam-logo-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/xcam-logo-black.png
--------------------------------------------------------------------------------
/public/xcam-logo-primary-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/public/xcam-logo-primary-color.png
--------------------------------------------------------------------------------
/server/index.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import next from 'next';
3 | import express from 'express';
4 | import { resolve } from 'path';
5 | import routes from './routes';
6 |
7 | require('dotenv').config({ path: resolve(process.cwd(), '.env') });
8 |
9 | const port = parseInt(process.env.PORT || '8081', 10);
10 | const dev = process.env.NODE_ENV !== 'production';
11 | const app = next({ dev: process.env.NODE_ENV !== 'production' });
12 | const handler = routes.getRequestHandler(app);
13 |
14 | app.prepare().then(() => {
15 | const expressApp = express();
16 | expressApp.disable('x-powered-by');
17 | expressApp.use(handler).listen(port);
18 |
19 | console.log(`> Server listening at http://localhost:${port} as ${dev ? 'development' : process.env.NODE_ENV}`);
20 | })
21 | .catch((e) => {
22 | console.log('Something went wrong: ', e);
23 | process.exit();
24 | });
25 |
--------------------------------------------------------------------------------
/src/antmedia/LocalStream.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import classnames from 'classnames';
3 |
4 | export interface HTMLMediaProps
5 | extends React.AudioHTMLAttributes,
6 | React.VideoHTMLAttributes {
7 | id: string;
8 | classNames?: string;
9 | }
10 |
11 | const defaultProps = {
12 | muted: true,
13 | controls: true,
14 | playsInline: true,
15 | autoPlay: true,
16 | preload: 'auto'
17 | };
18 |
19 | export const LocalStream = ({ classNames, ...props }: HTMLMediaProps) => {
20 | const ref = React.useRef();
21 |
22 | React.useEffect(() => {
23 | const videoEl = ref.current;
24 | if (videoEl) {
25 | videoEl.addEventListener('play', () => {
26 | // eslint-disable-next-line no-console
27 | console.log('Pulisher is playing');
28 | });
29 | }
30 | }, []);
31 |
32 | const className = React.useMemo(() => classnames('video-js broadcaster'), [classNames]);
33 |
34 | return React.createElement('video', {
35 | ...defaultProps,
36 | ...props,
37 | ref,
38 | className
39 | });
40 | };
41 |
--------------------------------------------------------------------------------
/src/antmedia/interfaces/Device.ts:
--------------------------------------------------------------------------------
1 | export interface Device {
2 | kind: string;
3 | lable: string;
4 | deviceId: string;
5 | }
6 |
--------------------------------------------------------------------------------
/src/antmedia/interfaces/IceServer.ts:
--------------------------------------------------------------------------------
1 | export interface IceServer {
2 | urls: string;
3 | username: string;
4 | credential: string;
5 | }
6 |
7 | export type IceConnectionState =
8 | | 'disconnected'
9 | | 'connected'
10 | | 'checking'
11 | | 'failed';
12 |
--------------------------------------------------------------------------------
/src/antmedia/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export * from './IceServer';
2 | export * from './WebRTCAdaptor';
3 | export * from './WebRTCAdaptorConfigs';
4 | export * from './Device';
5 |
--------------------------------------------------------------------------------
/src/antmedia/utils.ts:
--------------------------------------------------------------------------------
1 | import classnames from 'classnames';
2 |
3 | export function initializePlayer(id: string, cls?: string): HTMLVideoElement {
4 | const video = document.createElement('video');
5 | video.id = id;
6 | video.className = classnames('video-js broadcaster', cls);
7 | video.autoplay = true;
8 | video.muted = true;
9 | video.controls = true;
10 | video.playsInline = true;
11 | return video;
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/coinbase/CoinbasePayment.tsx:
--------------------------------------------------------------------------------
1 | import Loader from "@components/common/base/loader";
2 | import { getGlobalConfig } from "@services/config";
3 |
4 | import { coinbaseRequestService } from "@services/coinbase.service";
5 | import { useEffect, useState } from "react";
6 | import { Button, Image } from "antd";
7 |
8 | import "./index.less";
9 |
10 | interface ICoinbasePaymentProps {
11 | tokenPackage: string;
12 | }
13 |
14 | export default function CoinbasePayment({
15 | tokenPackage,
16 | ...otherProps
17 | }: ICoinbasePaymentProps) {
18 | const config = getGlobalConfig();
19 | const controller = new AbortController();
20 |
21 | const createCharge = () =>
22 | coinbaseRequestService
23 | .createCharge({ tokenPackage }, controller.signal)
24 | .then((charge) => {
25 | window.open(
26 | charge.hosted_url,
27 | "Coinbase Payment",
28 | "width=400,height=300"
29 | );
30 | })
31 | .catch(console.error);
32 |
33 | return (
34 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/src/components/coinbase/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/default.less';
2 | .coinbase-payment-button {
3 | width: 100%;
4 | height: 2rem;
5 | padding: 1rem;
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | background-color: @primary-color;
10 | gap: 1rem;
11 | font-size: 1rem;
12 | }
13 |
14 | .coinbase-payment-button-logo {
15 | width: 2rem;
16 | height: 2rem;
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/commission/commission-card.less:
--------------------------------------------------------------------------------
1 | .card-studio-commission .ant-card-body {
2 | padding: initial;
3 | }
--------------------------------------------------------------------------------
/src/components/common/base/drop-option.tsx:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import { BarsOutlined, DownOutlined } from '@ant-design/icons';
3 | import { Dropdown, Button, Menu } from 'antd';
4 |
5 | interface IProps {
6 | onMenuClick: any,
7 | menuOptions?: any[],
8 | buttonStyle?: any,
9 | dropdownProps?: any
10 | }
11 |
12 | export class DropOption extends PureComponent {
13 | render() {
14 | const {
15 | onMenuClick, menuOptions = [], buttonStyle, dropdownProps
16 | } = this.props;
17 | const menu = menuOptions.map((item) => (
18 | {item.name}
19 | ));
20 | return (
21 | {menu}}
23 | {...dropdownProps}
24 | >
25 |
29 |
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/common/base/input-item-list.tsx:
--------------------------------------------------------------------------------
1 | import { Form } from 'antd';
2 | import { FormItemProps } from 'antd/lib/form/FormItem';
3 | import React from 'react';
4 |
5 | interface IFormInputItem {
6 | fields: FormItemProps[];
7 | }
8 |
9 | export default ({ fields }: IFormInputItem) => (
10 | <>
11 | {fields.map((field) => (
12 |
13 | {field.children}
14 |
15 | ))}
16 | >
17 | );
18 |
--------------------------------------------------------------------------------
/src/components/common/base/list-item.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Row, Col, List } from 'antd';
3 |
4 | interface IProps {
5 | title: string;
6 | description: string;
7 | titleLayout: any;
8 | descriptionLayout: any;
9 | }
10 |
11 | const ListItem = ({
12 | title, description, titleLayout, descriptionLayout
13 | }: IProps) => (
14 |
15 |
16 |
17 | {title}
18 |
19 |
20 | {description}
21 |
22 |
23 |
24 | );
25 |
26 | export default ListItem;
27 |
--------------------------------------------------------------------------------
/src/components/common/base/loader.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import classNames from 'classnames';
3 | import './loader.less';
4 |
5 | const Loader = ({ spinning = false, fullScreen = false }: any) => (
6 |
12 |
13 | {/*
*/}
14 | {/*
*/}
15 |
16 |
17 | );
18 |
19 | export default Loader;
20 |
--------------------------------------------------------------------------------
/src/components/common/base/nav.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { MenuProps, MenuItemProps } from 'antd';
3 | import MenuItem from 'antd/lib/menu/MenuItem';
4 | import dynamic from 'next/dynamic';
5 |
6 | const Menu = dynamic(() => import('antd/lib/menu'), { ssr: false });
7 |
8 | export const NavItem = ({ ...props }: MenuItemProps) => ;
9 |
10 | export const NavBar = ({
11 | children,
12 | ...props
13 | }: React.PropsWithChildren) => (
14 |
22 | );
23 |
--------------------------------------------------------------------------------
/src/components/common/base/popup.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 |
3 | .popup {
4 | width: 40%;
5 | .ant-radio-wrapper {
6 | width: 100%;
7 | }
8 | span.ant-radio + * {
9 | width: 100%;
10 | }
11 | .ant-modal-close {
12 | color: #ffffff;
13 | }
14 | .ant-modal-header {
15 | background-color: @primary-color;
16 |
17 | .ant-modal-title {
18 | color: #ffffff;
19 | }
20 | }
21 | .ant-modal-body {
22 | color: @regular-text;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/components/common/base/scroll-bar.less:
--------------------------------------------------------------------------------
1 | @import (inline) '../../../node_modules/react-perfect-scrollbar/dist/css/styles.css';
2 |
3 | :global {
4 | .ps--active-x > .ps__rail-x,
5 | .ps--active-y > .ps__rail-y {
6 | background-color: transparent;
7 | }
8 |
9 | .ps__rail-x:hover > .ps__thumb-x,
10 | .ps__rail-x:focus > .ps__thumb-x {
11 | height: 8px;
12 | }
13 |
14 | .ps__rail-y:hover > .ps__thumb-y,
15 | .ps__rail-y:focus > .ps__thumb-y {
16 | width: 8px;
17 | }
18 |
19 | .ps__rail-y,
20 | .ps__rail-x {
21 | z-index: 9;
22 | }
23 |
24 | .ps__thumb-y {
25 | width: 4px;
26 | right: 4px;
27 | }
28 |
29 | .ps__thumb-x {
30 | height: 4px;
31 | bottom: 4px;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/components/common/base/scroll-bar.tsx:
--------------------------------------------------------------------------------
1 | import ScrollBar from 'react-perfect-scrollbar';
2 | import './scroll-bar.less';
3 |
4 | export default ScrollBar;
5 |
--------------------------------------------------------------------------------
/src/components/common/base/select/countries.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Select } from 'antd';
3 | import { ICountries } from 'src/interfaces';
4 |
5 | interface IProps {
6 | autoFocus?: boolean;
7 | disabled?: boolean;
8 | mode?: 'multiple' | 'tags';
9 | onChange?: Function;
10 | defaultValue: string;
11 | countries: ICountries[];
12 | }
13 |
14 | const { Option } = Select;
15 |
16 | const filter = (value, option): boolean => option.children.toLowerCase().indexOf(value.toLowerCase()) > -1;
17 |
18 | const CountriesSelect = ({
19 | defaultValue, onChange, countries, ...props
20 | }: IProps) => {
21 | const [value, setValue] = React.useState(defaultValue);
22 | const handleSelectChange = (v) => {
23 | setValue(v);
24 | onChange && onChange(v);
25 | };
26 |
27 | return (
28 |
42 | );
43 | };
44 |
45 | CountriesSelect.defaultProps = {
46 | autoFocus: false,
47 | disabled: false,
48 | mode: '',
49 | onChange: null
50 | };
51 |
52 | export default CountriesSelect;
53 |
--------------------------------------------------------------------------------
/src/components/common/base/select/profile.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/react-in-jsx-scope */
2 | import { PureComponent } from 'react';
3 | import { Select, Form } from 'antd';
4 |
5 | interface Props {
6 | label: string;
7 | name: string;
8 | dataSource: {label: string, value: any}[]
9 | }
10 |
11 | export class OptionProfile extends PureComponent {
12 | render() {
13 | const { label, dataSource, name } = this.props;
14 | return (
15 |
16 |
19 |
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/common/base/tabs.tsx:
--------------------------------------------------------------------------------
1 | import React, { PropsWithChildren } from "react";
2 | import { SizeType } from "antd/lib/config-provider/SizeContext";
3 | import RcTabs, { TabsProps as RcTabsProps } from "rc-tabs";
4 | import classnames from "classnames";
5 |
6 | export interface TabsProps extends RcTabsProps {
7 | animated?: any;
8 | size?: SizeType;
9 | }
10 |
11 | // @ts-ignore
12 | export const { TabPane } = RcTabs;
13 |
14 | export const Tabs = ({
15 | prefixCls = "ant-tabs",
16 | size = "large",
17 | animated = {
18 | inkBar: true,
19 | tabPane: true,
20 | },
21 | defaultActiveKey,
22 | className,
23 | ...props
24 | }: PropsWithChildren) => {
25 | const [activeKey, setActiveKey] = React.useState(defaultActiveKey);
26 | const onTabClick = (key) => {
27 | setActiveKey(key);
28 | };
29 | return (
30 | (
36 |
41 | )}
42 | animated={animated}
43 | {...props}
44 | />
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/src/components/common/base/trash.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button, Popconfirm } from 'antd';
3 | import { DeleteOutlined } from '@ant-design/icons';
4 |
5 | interface P {
6 | confirm: (e?: React.MouseEvent) => void;
7 | }
8 |
9 | const PopupConfirm = ({ confirm }: P) => (
10 |
17 |
20 |
21 | );
22 | PopupConfirm.defaultProps = {};
23 |
24 | export default PopupConfirm;
25 |
--------------------------------------------------------------------------------
/src/components/common/index.tsx:
--------------------------------------------------------------------------------
1 | import GoogleReCaptcha from './recaptcha';
2 |
3 | export {
4 | GoogleReCaptcha
5 | };
6 |
--------------------------------------------------------------------------------
/src/components/common/layout/banner.less:
--------------------------------------------------------------------------------
1 | .banner {
2 | // margin: 20px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/components/common/layout/banner.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | // import Link from 'next/link';
3 | import { Carousel } from 'antd';
4 |
5 | import './banner.less';
6 | import { IBanner } from 'src/interfaces';
7 |
8 | interface IProps {
9 | banners: IBanner[];
10 | styleImage: { [key: string]: any };
11 | classnames?: string;
12 | }
13 | const renderBanner = (banner: IBanner, styleImage: { [key: string]: any }) => {
14 | const {
15 | type, href, _id, photo, contentHTML
16 | } = banner;
17 | if (type === 'html' && contentHTML) {
18 | // eslint-disable-next-line react/no-danger
19 | return ;
20 | }
21 |
22 | return (
23 |
24 |
29 |
30 | );
31 | };
32 | const Banner = ({ banners, styleImage, classnames }: IProps) => (
33 |
34 | {banners && banners.length > 0 && (
35 |
36 | {banners.map((item) => (renderBanner(item, styleImage)
37 | ))}
38 |
39 | )}
40 |
41 | );
42 |
43 | Banner.defaultProps = {
44 | classnames: ''
45 | };
46 | export default Banner;
47 |
--------------------------------------------------------------------------------
/src/components/common/layout/footer.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/default.less';
2 | .ant-layout-footer {
3 | background: @background-footer !important;
4 | }
5 | .footer-custom {
6 | text-align: center;
7 | }
8 |
9 | .footer-logo{
10 | width: 217px !important;
11 | }
12 |
13 | .single-widget img{
14 | margin-bottom: 0 !important;
15 | }
16 |
17 | .footer-container{
18 | width: 95%;
19 | margin: 0 auto;
20 | }
--------------------------------------------------------------------------------
/src/components/common/layout/form-register-placeholder.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { IUIConfig } from 'src/interfaces';
3 |
4 | interface P {
5 | ui: IUIConfig;
6 | }
7 |
8 | export const FormRegisterPlaceHolder = ({ ui }: P) => (
9 |
17 | );
18 |
--------------------------------------------------------------------------------
/src/components/common/layout/index.ts:
--------------------------------------------------------------------------------
1 | export * from './form-register-placeholder';
2 | export * from './popup-18plus-content';
3 |
--------------------------------------------------------------------------------
/src/components/common/layout/left-header-content.less:
--------------------------------------------------------------------------------
1 | @media (max-width: @mobile-small-query) {
2 | .ant-menu-item.hidden-sm {
3 | display: none !important;
4 | }
5 | }
6 |
7 | @media (min-width: @mobile-small-query) {
8 | .ant-menu-item.visible-sm {
9 | display: none !important;
10 | }
11 | }
12 |
13 | @media (max-width: @mobile-small-query) {
14 | .ant-menu-item.visible-sm {
15 | display: inline-block !important;
16 | }
17 | }
18 |
19 | .cate-sub-menu-overlay {
20 | width: 450px;
21 | ul li {
22 | width: 25%;
23 | .ant-dropdown-menu-title-content {
24 | overflow: hidden;
25 | text-overflow: ellipsis;
26 | text-align: center;
27 | }
28 | &:hover {
29 | color: @white-color;
30 | background-color: @primary-color;
31 | }
32 | }
33 |
34 | @media (max-width: @mobile-query) {
35 | width: 100%;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/components/common/layout/numberformat.tsx:
--------------------------------------------------------------------------------
1 | import { NumberFormatProps } from 'react-number-format';
2 | import dynamic from 'next/dynamic';
3 |
4 | const NumberFormatNoSSR = dynamic(() => import('react-number-format'), {
5 | ssr: false
6 | });
7 | type P = NumberFormatProps
8 | export default function NumberFormat({ decimalScale, ...props }: P) {
9 | return (
10 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/common/layout/page-header.tsx:
--------------------------------------------------------------------------------
1 | import { PageHeader, Divider } from 'antd';
2 |
3 | interface P {
4 | title: any;
5 | // eslint-disable-next-line react/require-default-props
6 | extra?: any;
7 | }
8 |
9 | export default ({ title, extra } : P) => (
10 | <>
11 |
12 |
13 | >
14 | );
15 |
--------------------------------------------------------------------------------
/src/components/common/layout/page.less:
--------------------------------------------------------------------------------
1 | @import '../../../../style/vars.less';
2 |
3 | .contentInner {
4 | background: #fff;
5 | padding: 24px;
6 | box-shadow: @shadow-1;
7 | min-height: ~'calc(100vh - 230px)';
8 | position: relative;
9 | }
10 |
11 | @media (max-width: 767px) {
12 | .contentInner {
13 | padding: 12px;
14 | min-height: ~'calc(100vh - 160px)';
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/common/layout/page.tsx:
--------------------------------------------------------------------------------
1 | import React, { PropsWithChildren, PureComponent } from "react";
2 | import classnames from "classnames";
3 | import Loader from "../base/loader";
4 | import "./page.less";
5 |
6 | interface IProps {
7 | loading?: boolean;
8 | className?: string;
9 | inner?: boolean;
10 | }
11 |
12 | export default class Page extends PureComponent> {
13 | render() {
14 | const { className, children, loading = false, inner = true } = this.props;
15 | const loadingStyle = {
16 | height: "calc(100vh - 184px)",
17 | overflow: "hidden",
18 | };
19 | return (
20 |
26 | {loading ? : ""}
27 | {children}
28 |
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/components/common/layout/popup-18plus-content.less:
--------------------------------------------------------------------------------
1 | .confirmage__header {
2 | font-weight: bold;
3 | font-size: 20px;
4 | margin-bottom: 10px;
5 | }
6 |
7 | .confirmage__description .scroll {
8 | height: 200px;
9 | overflow: auto;
10 | padding: 0 15px 0 10px;
11 | border: 1px solid #ccc;
12 | margin: 0 auto;
13 | text-align: left;
14 | }
--------------------------------------------------------------------------------
/src/components/common/recaptcha.less:
--------------------------------------------------------------------------------
1 | .recaptcha-box {
2 | .recaptcha-error-message {
3 | color: #dd4b39 !important;
4 | font-size: 13px !important;
5 | line-height: 1.5715 !important;
6 | padding: 4px 0 !important;
7 | margin: 0 !important;
8 | }
9 | }
--------------------------------------------------------------------------------
/src/components/common/recaptcha.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useEffect } from 'react';
2 | import './recaptcha.less';
3 | import ReCAPTCHA from 'react-google-recaptcha';
4 | import Router from 'next/router';
5 |
6 | interface IProps {
7 | googleReCaptchaEnabled: boolean;
8 | googleReCaptchaSiteKey: string;
9 | error: string;
10 | }
11 |
12 | const GoogleReCaptcha = forwardRef((props: IProps, ref) => {
13 | const {
14 | googleReCaptchaEnabled, googleReCaptchaSiteKey, error
15 | } = props;
16 |
17 | const onRouteChangeStart = () => {
18 | if (window.grecaptcha) {
19 | window.grecaptcha.reset();
20 | }
21 | };
22 |
23 | useEffect(() => {
24 | Router.events.on('routeChangeStart', onRouteChangeStart);
25 |
26 | return () => {
27 | Router.events.off('routeChangeStart', onRouteChangeStart);
28 | };
29 | }, []);
30 |
31 | return (
32 |
33 | {googleReCaptchaEnabled && (
34 |
40 | )}
41 | {error && (
42 |
43 | {error || 'Please verify that you are not a robot.'}
44 |
45 | )}
46 |
47 | );
48 | });
49 | export default GoogleReCaptcha;
50 |
--------------------------------------------------------------------------------
/src/components/galleries/purchased-gallery-card.tsx:
--------------------------------------------------------------------------------
1 | import { IPerformerGallery } from 'src/interfaces';
2 | import Link from 'next/link';
3 | import './index.less';
4 | import React from 'react';
5 |
6 | interface IProps {
7 | gallery: IPerformerGallery;
8 | }
9 |
10 | const PurchasedGalleryCard = ({ gallery }: IProps) => {
11 | const { name, coverPhoto, _id } = gallery;
12 | return (
13 |
32 | );
33 | };
34 |
35 | export default PurchasedGalleryCard;
36 |
--------------------------------------------------------------------------------
/src/components/homepage/EmergencyArea.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const EmergencyArea = () => {
4 | return (
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |

16 |
17 |
18 | )
19 | }
20 |
21 | export default EmergencyArea;
--------------------------------------------------------------------------------
/src/components/homepage/PageBanner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Link from 'next/link';
3 |
4 | const PageBanner = ({pageTitle, homePageUrl, homePageText, activePageText, imgClass}) => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
{pageTitle}
12 |
20 |
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default PageBanner;
--------------------------------------------------------------------------------
/src/components/homepage/Subscribe.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Subscribe = () => {
4 | return (
5 |
6 |
7 |
8 |
9 |
Subscribe Now
10 |
Get our latest news & update regularly
11 |
12 |
13 |
14 |
21 |
22 |
23 |
24 |
25 | )
26 | }
27 |
28 | export default Subscribe;
--------------------------------------------------------------------------------
/src/components/messages/ConversationList.less:
--------------------------------------------------------------------------------
1 | .conversation-list {
2 | height: 100%;
3 | width: 100%;
4 | overflow: hidden;
5 | padding: 20px 0;
6 | border-right: 1px #ff0066 solid;
7 | }
--------------------------------------------------------------------------------
/src/components/messages/ConversationListItem.less:
--------------------------------------------------------------------------------
1 | .conversation-list-item {
2 | display: flex;
3 | align-items: center;
4 | padding: 10px;
5 | position: relative;
6 | overflow: hidden;
7 |
8 | .conversation-info {
9 | overflow: hidden;
10 | }
11 | }
12 |
13 | .conversation-left-corner {
14 | display: flex;
15 | flex-direction: column;
16 | margin-right: 10px;
17 | align-items: center;
18 | justify-content: center;
19 | }
20 |
21 | .conversation-left-corner span {
22 | font-size: 10px;
23 | }
24 |
25 | .conversation-list-item:hover {
26 | background: #ffe6eb;
27 | cursor: pointer;
28 | }
29 |
30 | .conversation-list-item.active {
31 | background: #ffe6eb;
32 | pointer-events: none;
33 | }
34 |
35 | .conversation-photo {
36 | width: 50px;
37 | height: 50px;
38 | border-radius: 50%;
39 | object-fit: cover;
40 | }
41 |
42 | .conversation-title {
43 | font-size: 14px;
44 | font-weight: bold;
45 | text-transform: capitalize;
46 | margin: 0;
47 | }
48 |
49 | .conversation-snippet {
50 | font-size: 12px;
51 | color: #888;
52 | margin: 0;
53 | height: 20px;
54 | width: 100%;
55 | overflow: hidden;
56 | text-overflow: ellipsis;
57 | white-space: nowrap;
58 | }
59 |
60 | .conversation-time {
61 | font-size: 10px;
62 | color: #888;
63 | margin: 0;
64 | }
65 |
66 | .notification-badge {
67 | position: absolute;
68 | top: 0;
69 | left: 10px;
70 | }
--------------------------------------------------------------------------------
/src/components/messages/ConversationListItem.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Badge } from 'antd';
3 | import moment from 'moment';
4 |
5 | import './ConversationListItem.less';
6 |
7 | interface Iprops{
8 | data: any;
9 | selected: boolean;
10 | setActive: Function;
11 | }
12 |
13 | export default function ConversationListItem(props : Iprops) {
14 | const { setActive, selected, data } = props;
15 | const {
16 | recipientInfo, lastMessage, _id, updatedAt, lastMessageCreatedAt, totalNotSeenMessages = 0
17 | } = data;
18 | const className = selected
19 | ? 'conversation-list-item active'
20 | : 'conversation-list-item';
21 |
22 | return (
23 | setActive(_id)}
27 | >
28 |
29 |

30 |
31 |
32 |
{recipientInfo?.username || 'N/A'}
33 |
{lastMessage}
34 |
{moment(lastMessageCreatedAt || updatedAt).fromNow()}
35 |
36 |
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/messages/ConversationSearch.less:
--------------------------------------------------------------------------------
1 | .conversation-search {
2 | padding: 10px;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | .conversation-search-input {
8 | background: #f4f4f8;
9 | padding: 8px 10px;
10 | border-radius: 10px;
11 | border: none;
12 | font-size: 14px;
13 | }
14 |
15 | .conversation-search-input::placeholder {
16 | text-align: center;
17 | }
18 |
19 | .conversation-search-input:focus::placeholder {
20 | text-align: left;
21 | }
--------------------------------------------------------------------------------
/src/components/messages/ConversationSearch.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './ConversationSearch.less';
3 |
4 | export default function ConversationSearch({ onSearch } : any) {
5 | return (
6 |
7 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/messages/emotions.tsx:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import dynamic from 'next/dynamic';
3 | import '../stream-chat/Compose.less';
4 |
5 | let Picker;
6 | if (typeof window !== 'undefined') {
7 | Picker = dynamic(() => import('emoji-picker-react'), { ssr: false });
8 | }
9 |
10 | interface IProps {
11 | onEmojiClick: Function;
12 | }
13 |
14 | export default class Emotions extends PureComponent {
15 | uploadRef: any;
16 |
17 | constructor(props) {
18 | super(props);
19 | this.uploadRef = React.createRef();
20 | }
21 |
22 | onEmojiClick(event, emoji) {
23 | const { onEmojiClick } = this.props;
24 | onEmojiClick(emoji);
25 | }
26 |
27 | render() {
28 | return (
29 | <>
30 |
36 | >
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/components/order/detail.less:
--------------------------------------------------------------------------------
1 | #form-update-order {
2 | .ant-form-item-label{
3 | text-align: left;
4 | }
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/order/index.ts:
--------------------------------------------------------------------------------
1 | export * from './search-filter';
2 | export * from './table-list';
3 | export * from './order-status';
4 |
--------------------------------------------------------------------------------
/src/components/order/order-status.tsx:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import { Tag } from 'antd';
3 |
4 | interface IProps {
5 | status: string;
6 | }
7 |
8 | export class OrderStatus extends PureComponent {
9 | renderStatus(status: string) {
10 | switch (status) {
11 | case 'processing':
12 | return Processing;
13 | case 'shipping':
14 | return Shipping;
15 | case 'delivered':
16 | return Delivered;
17 | case 'refunded':
18 | return Refunded;
19 | case 'created':
20 | return Created;
21 | default:
22 | return Pending;
23 | }
24 | }
25 |
26 | render() {
27 | const { status } = this.props;
28 | return this.renderStatus(status);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/payment/index.ts:
--------------------------------------------------------------------------------
1 | export * from './paypal-setting-form';
2 | export * from './issue-check-us-setting-form';
3 | export * from './wire-transfer-setting-form';
4 | export * from './bitpay-form';
5 | export * from './direct-deposit-form';
6 | export * from './paxum-form';
7 |
--------------------------------------------------------------------------------
/src/components/payout-request/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/default.less';
2 | .payout-request-form {
3 | padding: @form-padding
4 | }
--------------------------------------------------------------------------------
/src/components/performer-assets/common/modal-buy-assets.less:
--------------------------------------------------------------------------------
1 | .color {
2 | color: #ff0066;;
3 | }
--------------------------------------------------------------------------------
/src/components/performer/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './performer-username';
2 |
--------------------------------------------------------------------------------
/src/components/performer/performer-username.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Link from 'next/link';
3 | import { IPerformer } from 'src/interfaces';
4 |
5 | interface P {
6 | performer: IPerformer
7 | }
8 |
9 | export const PerformerUsername = ({ performer }: P) => (
10 |
17 | {performer.username}
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/performer/profile-detail.less:
--------------------------------------------------------------------------------
1 | .performer-profile-list {
2 | text-transform: capitalize;
3 | }
--------------------------------------------------------------------------------
/src/components/performer/streaming-status-update-form.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Button, Input, Row, Col
4 | } from 'antd';
5 |
6 | interface IProps {
7 | submit: Function;
8 | status: string;
9 | updating: boolean;
10 | }
11 |
12 | export default ({ status, updating, submit }: IProps) => {
13 | const [value, setValue] = React.useState(status);
14 | const handleClick = () => {
15 | submit(value);
16 | };
17 |
18 | return (
19 |
20 |
21 | setValue(event.target.value)}
25 | />
26 |
27 |
28 |
38 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/components/stream-chat/MessageList.less:
--------------------------------------------------------------------------------
1 | .message-list {
2 | height: 100%;
3 | overflow: hidden;
4 | width: 100%;
5 | margin-bottom: 0px;
6 | &.custom {
7 | height: 50vh;
8 | }
9 | }
10 | .message-list-container {
11 | padding: 10px;
12 | overflow-y: scroll;
13 | // height: calc(100% - 55px);
14 | height: 90%;
15 | }
16 | .sub-text {
17 | color: #ff0064;
18 | position: absolute;
19 | top: 0;
20 | left: 0;
21 | width: 100%;
22 | height: 100%;
23 | display: flex;
24 | align-items: center;
25 | justify-content: center;
26 | font-size: 18px;
27 | background: rgba(1,1,1,.5);
28 | }
29 |
30 | @media all and (max-width: 768px) {
31 | .sub-text {
32 | font-size: 14px;
33 | }
34 | }
35 | .start-conversation {
36 | text-align: center;
37 | margin-top:30%;
38 | font-size: large;
39 | }
--------------------------------------------------------------------------------
/src/components/stream-chat/Messenger.less:
--------------------------------------------------------------------------------
1 | .messenger {
2 | display: flex;
3 | width: 100%;
4 | }
5 | .message-stream {
6 | display: flex;
7 | width: 100%;
8 | height: 480px;
9 | position: relative;
10 | margin-bottom: 5px;
11 | background-color: transparent;
12 |
13 | &.user-logged-in {
14 | .message-list {
15 | margin-bottom: 0px;
16 | }
17 | .message-list-container {
18 | height: calc(100% - 50px) !important;
19 | }
20 | }
21 | }
22 |
23 | .scrollable {
24 | position: relative;
25 | overflow-y: scroll;
26 | -webkit-overflow-scrolling: touch;
27 | }
28 |
29 | .sidebar {
30 | background-color: #fff;
31 | display: flex;
32 | width: 30%;
33 | }
34 |
35 | .chat-content {
36 | background: #fff;
37 | display: flex;
38 | width: 70%;
39 | padding: 20px 0;
40 | position: relative;
41 | }
42 | .chat-content .close-btn {
43 | display: none;
44 | }
45 |
46 | .footer {
47 | background: #fff;
48 | }
49 |
50 | @media all and (max-width: 768px) {
51 | .sidebar {
52 | width: 100%;
53 | }
54 | .sidebar.active {
55 | display: none;
56 | }
57 | .chat-content {
58 | display: none;
59 | }
60 | .chat-content.active {
61 | display: flex;
62 | width: 100%;
63 | }
64 | .chat-content.active .close-btn {
65 | display: flex;
66 | position: absolute;
67 | top: 5px;
68 | left: 5px;
69 | z-index: 1;
70 | }
71 | }
--------------------------------------------------------------------------------
/src/components/stream-chat/Messenger.tsx:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import classnames from 'classnames';
3 | import './Messenger.less';
4 | import { connect } from 'react-redux';
5 | import { getStreamConversation } from '@redux/stream-chat/actions';
6 | import MessageList from './MessageList';
7 |
8 | interface IProps {
9 | streamId?: string;
10 | getStreamConversation: Function;
11 | activeConversation?: any;
12 | loggedIn: boolean;
13 | }
14 | class StreamMessenger extends PureComponent {
15 | componentDidMount() {
16 | const { streamId, activeConversation, getStreamConversation: dispatchGetStreamConversation } = this.props;
17 | if (!activeConversation && streamId) {
18 | dispatchGetStreamConversation({ conversation: activeConversation.data, isPublic: true });
19 | }
20 | }
21 |
22 | render() {
23 | const { activeConversation, loggedIn } = this.props;
24 | return (
25 |
26 | {activeConversation && activeConversation.data && activeConversation.data.streamId ?
:
No conversation found.
}
27 |
28 | );
29 | }
30 | }
31 | const mapStates = (state: any) => ({
32 | activeConversation: state.streamMessage.activeConversation,
33 | loggedIn: state.auth.loggedIn
34 | });
35 | const mapDispatchs = { getStreamConversation };
36 | export default connect(mapStates, mapDispatchs)(StreamMessenger);
37 |
--------------------------------------------------------------------------------
/src/components/stream-chat/chat-box.less:
--------------------------------------------------------------------------------
1 | .conversation-stream {
2 | min-height: 530px;
3 | border: solid 1px @primary-color;
4 | border-radius: 15px;
5 | margin: 0 15px;
6 |
7 | .tablist {
8 | margin: 0;
9 | }
10 | .ant-tabs > .ant-tabs-nav, .ant-tabs > div > .ant-tabs-nav {
11 | margin: 0 !important;
12 | }
13 | .ant-tabs-tab-btn {
14 | transition: all 0.1s;
15 | }
16 | .ant-tabs-nav-list {
17 | width: 100%;
18 | overflow: hidden;
19 | .ant-tabs-tab {
20 | flex: 1;
21 | justify-content: center;
22 | height: 50px;
23 | margin: 0;
24 | &:first-child {
25 | border-top-left-radius: 12px;
26 | }
27 | &:nth-child(2) {
28 | border-top-right-radius: 12px;
29 | }
30 | }
31 | .ant-tabs-tab-active {
32 | background-color: @primary-color;
33 | color: #ffffff;
34 | .ant-tabs-tab-btn {
35 | color: #fff;
36 | }
37 | }
38 | }
39 | }
40 |
41 | @media (max-width: @mobile-query) {
42 | .conversation-stream {
43 | margin: 15px 0;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/components/stream-chat/emotions.tsx:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import dynamic from 'next/dynamic';
3 | import './Compose.less';
4 |
5 | let Picker;
6 | if (typeof window !== 'undefined') {
7 | Picker = dynamic(() => import('emoji-picker-react'), { ssr: false });
8 | }
9 |
10 | interface IProps {
11 | onEmojiClick: Function;
12 | }
13 |
14 | export default class Emotions extends PureComponent {
15 | uploadRef: any;
16 |
17 | constructor(props) {
18 | super(props);
19 | this.uploadRef = React.createRef();
20 | }
21 |
22 | onEmojiClick(event, emoji) {
23 | const { onEmojiClick } = this.props;
24 | onEmojiClick(emoji);
25 | }
26 |
27 | render() {
28 | return (
29 | <>
30 |
36 | >
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/components/streaming/contants.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-shadow
2 | export enum STREAM_TYPE {
3 | PRIVATE = 'private',
4 | PUBLIC = 'public',
5 | GROUP = 'group'
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/streaming/footer.less:
--------------------------------------------------------------------------------
1 | .stream-footer {
2 | .ant-btn:disabled{
3 | color: #fff;
4 | background: #0cb8b6;
5 | border-color: #ff0066;
6 | }
7 | }
--------------------------------------------------------------------------------
/src/components/streaming/group-streaming-container.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/default.less';
2 |
3 | .stream-group {
4 | margin: 5px 0;
5 | #group-video-container {
6 | width: 100%;
7 | display: flex;
8 | flex-wrap: wrap;
9 | }
10 | }
11 |
12 | #main-group-video {
13 | height: 480px !important;
14 | width: 100%;
15 | }
--------------------------------------------------------------------------------
/src/components/streaming/header.less:
--------------------------------------------------------------------------------
1 | .stream-header {
2 | margin-bottom: 10px;
3 |
4 | .left-content {
5 | display: flex;
6 | align-items: center;
7 |
8 | .stream-title {
9 | margin-left: 5px;
10 | font-size: 16px;
11 | font-weight: bold;
12 | color: #0cb8b6;
13 | display: flex;
14 | flex-direction: column;
15 | text-transform: capitalize;
16 | }
17 |
18 | .stream-avatar {
19 | height: 45px;
20 | width: 45px;
21 | border-radius: 50%;
22 | }
23 | }
24 | }
25 |
26 | .button-block {
27 | width: 100%;
28 | display: flex;
29 | justify-content: flex-end;
30 | .ant-btn {
31 | height: 35px;
32 | margin: 5px;
33 | }
34 | @media (max-width: 567px) {
35 | justify-content: flex-start;
36 | margin-top: 10px;
37 | width: 100%;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/components/streaming/index.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/default.less';
2 |
3 | #subscriber {
4 | min-height: 480px;
5 | width: 100%;
6 | object-fit: cover;
7 | @media screen and (max-width: @mobile-small-query) {
8 | min-height: 320px;
9 | height: 320px;
10 | }
11 | }
12 |
13 | #publisher {
14 | min-height: 480px;
15 | width: 100%;
16 | @media screen and (max-width: @mobile-small-query) {
17 | min-height: 230px;
18 | height: 230px;
19 | }
20 | }
21 |
22 | .video-container {
23 | display: flex;
24 | video {
25 | width: 100%;
26 | }
27 | }
28 |
29 | .conversation-users {
30 | .users {
31 | height: 435px;
32 | overflow-y: scroll;
33 | width: 100%;
34 | .user {
35 | margin: 15px;
36 | padding: 10px;
37 | border-radius: 5px;
38 | background-color: #ffffff;
39 | .message-username {
40 | font-weight: 1000;
41 | }
42 | }
43 | }
44 | }
45 |
46 | .publishing {
47 | font-size: 13px;
48 | font-weight: 500;
49 | color: @primary-color;
50 | }
--------------------------------------------------------------------------------
/src/components/streaming/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './description';
2 |
--------------------------------------------------------------------------------
/src/components/streaming/private-streaming-container.less:
--------------------------------------------------------------------------------
1 | .private-streaming-container {
2 | position: relative;
3 | margin: 5px 0;
4 | min-height: 520px;
5 |
6 | #private-publisher {
7 | right: 10px;
8 | top: 25px;
9 | height: 145px;
10 | width: 145px;
11 | position: absolute;
12 | z-index: 2;
13 | }
14 |
15 | #private-subscriber {
16 | width: 100% !important;
17 | height: 480px;
18 | object-fit: cover;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/components/streaming/tip/content.less:
--------------------------------------------------------------------------------
1 | .token-radio {
2 | width: 100%;
3 | justify-content:space-between;
4 | .amount{
5 | width: 150px;
6 | }
7 |
8 | @media (max-width: 567px) {
9 | .tip-description {
10 | display: none;
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/components/streaming/webrtc/privatechat/index.less:
--------------------------------------------------------------------------------
1 | .private-streaming-container {
2 | position: relative;
3 | margin: 5px 0;
4 | min-height: 520px;
5 |
6 | #private-publisher {
7 | right: 10px;
8 | top: 25px;
9 | height: 145px;
10 | width: 145px;
11 | position: absolute;
12 | z-index: 2;
13 | object-fit: cover;
14 |
15 | @media screen and (max-width: @mobile-small-query) {
16 | right: 5px;
17 | top: 5px;
18 | height: 100px;
19 | width: 100px;
20 | }
21 | }
22 |
23 | #private-subscriber {
24 | width: 100% !important;
25 | height: 480px;
26 | object-fit: cover;
27 |
28 | @media screen and (max-width: @mobile-small-query) {
29 | height: 320px;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/components/user/performer-filter.less:
--------------------------------------------------------------------------------
1 | @import '../../../style/default.less';
2 |
3 | .performer-filter {
4 | padding: 0 10px;
5 |
6 | .ant-btn-dashed.active {
7 | color: #0cb8b6 !important;
8 | background: #fff !important;
9 | border-color: #0cb8b6 !important;
10 | }
11 | .ant-btn:focus {
12 | color: #666;
13 | background: #fff;
14 | border-color: #e5e5e5;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/components/user/profile.less:
--------------------------------------------------------------------------------
1 | .performerRegisterForm {
2 | @media (max-width: 567px) {
3 | padding-left: 24px;
4 | padding-right: 24px;
5 | }
6 |
7 | .edit-icon {
8 | position: absolute;
9 | font-size: 16px;
10 | bottom: 0px;
11 | right: 0px;
12 | border-radius: 8px;
13 | background: white;
14 | height: 20px;
15 | width: 20px;
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | }
20 |
21 | label {
22 | font-weight: bold !important;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/components/user/update-password-form.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Button, Input } from 'antd';
3 |
4 | export const UpdatePaswordForm = ({ onFinish, updating = false }: any) => (
5 |
11 |
12 |
13 |
14 |
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/videos/purchased-video-card.tsx:
--------------------------------------------------------------------------------
1 | import { IPerformer, IVideo } from 'src/interfaces';
2 | import Link from 'next/link';
3 | import { PlayCircleOutlined } from '@ant-design/icons';
4 | import './index.less';
5 | import React from 'react';
6 |
7 | interface IProps {
8 | video: IVideo;
9 | performer: IPerformer;
10 | onClick: () => void;
11 | }
12 |
13 | const PurchasedVideoCard = ({ video, performer, onClick }: IProps) => {
14 | const { title, thumbnail, _id } = video;
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |

22 |
23 |
34 |
35 | );
36 | };
37 |
38 | export default PurchasedVideoCard;
39 |
--------------------------------------------------------------------------------
/src/components/videos/video-single-card.tsx:
--------------------------------------------------------------------------------
1 | import { Tag } from 'antd';
2 | import React from 'react';
3 | import { IVideo } from 'src/interfaces';
4 | import { defaultColor } from 'src/lib';
5 | import Link from 'next/link';
6 | import './index.less';
7 | import NumberFormat from '@components/common/layout/numberformat';
8 |
9 | interface IProps {
10 | video: IVideo;
11 | }
12 |
13 | const generateToken = (token: number, isSale: boolean) => token && (
14 | 0 ? defaultColor.primaryColor : '#ccc'}>
15 | {isSale && token > 0 ? : 'FREE'}
16 |
17 | );
18 |
19 | const VideoSingleCard = ({ video }: IProps) => {
20 | const {
21 | token, title, thumbnail, isSaleVideo, _id
22 | } = video;
23 | return (
24 |
25 |
26 |
{generateToken(token, isSaleVideo)}
27 |
34 |
35 |
36 |
37 |
38 |
39 |
{title}
40 |
41 | );
42 | };
43 |
44 | export default VideoSingleCard;
45 |
--------------------------------------------------------------------------------
/src/constants.tsx:
--------------------------------------------------------------------------------
1 | export const SETTING_CHANNEL = 'SETTINGS';
2 |
3 | export const SETTING_KEYS = {
4 | SITE_NAME: 'siteName',
5 | LOGO_URL: 'logoUrl',
6 | PLACEHOLDER_LOGIN_URL: 'placeholderLoginUrl',
7 | PLACEHOLDER_AVATAR_URL: 'placeholderAvatarUrl',
8 | FAVICON: 'favicon',
9 | META_KEYWORDS: 'metaKeywords',
10 | META_DESCRIPTION: 'metaDescription',
11 | HEADER_SCRIPT: 'headerScript',
12 | AFTER_BODY_SCRIPT: 'afterBodyScript',
13 | CURRENCY: 'currency',
14 | GOOGLE_ANALYTICS_CODE: 'gaCode',
15 | MAINTENANCE_MODE: 'maintenanceMode',
16 | TIP_SOUND: 'tipSound',
17 | DEFAULT_OFFLINE_MODEL_IMAGE: 'defaultOfflineModelImage',
18 | DEFAULT_MODEL_PRIVATECALL_WITH_USER_IMAGE: 'defaultPrivateCallImage',
19 | DEFAULT_MODEL_IN_GROUP_CHAT_IMAGE: 'defaultGroupChatImage',
20 | VIEWER_URL: 'viewerURL',
21 | PUBLISHER_URL: 'publisherURL',
22 | SUBSCRIBER_URL: 'subscriberUrl',
23 | OPTION_FOR_BROADCAST: 'optionForBroadcast',
24 | OPTION_FOR_PRIVATE: 'optionForPrivate',
25 | OPTION_FOR_GROUP: 'optionForGroup',
26 | SECURE_OPTION: 'secureOption',
27 | ANT_MEDIA_APPNAME: 'AntMediaAppname'
28 | };
29 |
30 | export const MENU_SECTION = {
31 | MAIN: 'main',
32 | HEADER: 'header',
33 | FOOTER: 'footer'
34 | };
35 |
--------------------------------------------------------------------------------
/src/interfaces/banner.ts:
--------------------------------------------------------------------------------
1 | export interface IBanner {
2 | _id: string;
3 | title: string;
4 | description?: string;
5 | status?: string;
6 | href: string;
7 | position?: string;
8 | photo?: { url: string; thumbnails: string[] };
9 | type: string;
10 | contentHTML: string;
11 | }
12 |
13 | export interface IBannerSearch {
14 | position?: string;
15 | status?: string;
16 | }
17 |
--------------------------------------------------------------------------------
/src/interfaces/earning.ts:
--------------------------------------------------------------------------------
1 | import { IUser } from './user';
2 | import { ITransaction } from './transaction';
3 | import { IPerformer } from './performer';
4 |
5 | export interface IEarning {
6 | _id: string;
7 | createAt: Date;
8 | updateAt: Date;
9 | userId: string;
10 | userInfo: IUser;
11 | transactionTokenId: string;
12 | transactionInfo: ITransaction;
13 | performerId: string;
14 | performerInfo: IPerformer;
15 | sourceType: string;
16 | grossPrice: number;
17 | netPrice: number;
18 | isPaid: boolean;
19 | commission: number;
20 | paidAt: Date;
21 | transactionStatus: string;
22 | conversionRate?: number;
23 | payoutStatus: string;
24 | }
25 |
--------------------------------------------------------------------------------
/src/interfaces/favourite.ts:
--------------------------------------------------------------------------------
1 | import { IPerformer } from 'src/interfaces';
2 |
3 | export interface IFavourite {
4 | _id: string;
5 | favoriteId: string;
6 | ownerId: string;
7 | performer: IPerformer;
8 | status: string;
9 | createdAt: Date;
10 | updatedAt: Date;
11 | }
12 |
--------------------------------------------------------------------------------
/src/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export * from './redux';
2 | export * from './utils';
3 | export * from './ui-config';
4 | export * from './user';
5 | export * from './auth';
6 | export * from './post';
7 | export * from './performer';
8 | export * from './setting';
9 | export * from './performer-categories';
10 | export * from './peformer-assets';
11 | export * from './photo';
12 | export * from './favourite';
13 | export * from './token-package';
14 | export * from './transaction';
15 | export * from './order';
16 | export * from './refund-request';
17 | export * from './payout-request';
18 | export * from './studio';
19 | export * from './banner';
20 | export * from './stream';
21 |
--------------------------------------------------------------------------------
/src/interfaces/order.ts:
--------------------------------------------------------------------------------
1 | export interface IOrder {
2 | _id: string;
3 | buyerSource: string;
4 | buyerId: string;
5 | buyerInfo?: any;
6 | sellerSource: string;
7 | sellerId: string;
8 | sellerInfo?: any;
9 | name: string;
10 | description: string;
11 | orderNumber: string;
12 | shippingCode: string;
13 | payBy: string;
14 | quantity: number;
15 | totalPrice: number;
16 | deliveryAddress?: string;
17 | deliveryStatus: string;
18 | postalCode?: string;
19 | productType?: string;
20 | productId?: string;
21 | createdAt: Date;
22 | updatedAt: Date;
23 | productsInfo:any;
24 | }
25 |
--------------------------------------------------------------------------------
/src/interfaces/performer-categories.ts:
--------------------------------------------------------------------------------
1 | export interface IPerformerCategogies {
2 | _id: string;
3 | name: string;
4 | slug: string;
5 | ordering: number;
6 | description: string;
7 | createdBy: string;
8 | updatedBy: string;
9 | createdAt: Date;
10 | updatedAt: Date;
11 | }
12 |
--------------------------------------------------------------------------------
/src/interfaces/photo.ts:
--------------------------------------------------------------------------------
1 | import { IPerformer, IPerformerGallery } from 'src/interfaces';
2 |
3 | export interface IPhoto {
4 | _id?: string;
5 | performerId?: string;
6 | galleryId?: string;
7 | fileId?: string;
8 | photo?: IPhotoMetaData;
9 | type?: string;
10 | title?: string;
11 | description?: string;
12 | status?: 'draft'| 'active'| 'inactive';
13 | processing?: boolean;
14 | token?: number;
15 | performer?: IPerformer;
16 | gallery?: IPerformerGallery;
17 | createdBy?: string;
18 | updatedBy?: string;
19 | createdAt?: Date;
20 | updatedAt?: Date;
21 | }
22 |
23 | interface IPhotoMetaData {
24 | thumbnails: string[];
25 | url: string;
26 | width: number;
27 | height: number;
28 | mimeType: string;
29 | }
30 |
--------------------------------------------------------------------------------
/src/interfaces/post.ts:
--------------------------------------------------------------------------------
1 | import { ISearch } from './utils';
2 |
3 | export interface IPost {
4 | title: string;
5 | type: string;
6 | slug: string;
7 | content: string;
8 | shortDescription: string;
9 | categoryIds: string[];
10 | status: string;
11 | image: string;
12 | updatedBy: string;
13 | createdBy: string;
14 | createdAt: Date;
15 | updatedAt: Date;
16 | }
17 |
18 | export interface IPostCreate {
19 | title: string;
20 | type: string;
21 | slug: string;
22 | content: string;
23 | shortDescription: string;
24 | categoryIds: string[];
25 | status: string;
26 | }
27 |
28 | export interface IPostUpdate {
29 | title: string;
30 | slug: string;
31 | content: string;
32 | shortDescription: string;
33 | categoryIds: string[];
34 | status: string;
35 | }
36 |
37 | export interface IPostSearch extends ISearch {
38 | status?: string;
39 | }
40 |
--------------------------------------------------------------------------------
/src/interfaces/redux.ts:
--------------------------------------------------------------------------------
1 | export interface IReduxAction {
2 | type: string;
3 | payload: T;
4 | }
5 |
6 | export interface IReducerFieldUpdate {
7 | field: string;
8 | data: T;
9 | }
10 |
--------------------------------------------------------------------------------
/src/interfaces/refund-request.ts:
--------------------------------------------------------------------------------
1 | export interface IRefundRequest {
2 | _id: string;
3 | userId: string;
4 | sourceType?: string;
5 | sourceId: string;
6 | token: number;
7 | performerId: string;
8 | description: string;
9 | status?: string;
10 | createdAt?: Date;
11 | updatedAt?: Date;
12 | }
13 |
--------------------------------------------------------------------------------
/src/interfaces/setting.ts:
--------------------------------------------------------------------------------
1 | export interface ISetting {
2 | _id: string;
3 | key: string;
4 | value: any;
5 | name: string;
6 | description: string;
7 | group: string;
8 | public: boolean;
9 | type: string;
10 | visible: boolean;
11 | meta: { [key: string]: string };
12 | banner: string;
13 | createdAt: Date;
14 | updatedAt: Date;
15 | }
16 |
17 | export interface ICountries {
18 | code: string;
19 | flag: string;
20 | name: any;
21 | }
22 |
--------------------------------------------------------------------------------
/src/interfaces/studio.ts:
--------------------------------------------------------------------------------
1 | import {
2 | IPerformerPaymentInfo,
3 | IPerformerDirectDeposit,
4 | IPerformerPaxum,
5 | IPerformerBitpay
6 | } from '.';
7 | import { IStats } from './utils';
8 |
9 | export interface IStudioLogin {
10 | email: string;
11 | password: string;
12 | }
13 |
14 | export interface IStudio {
15 | _id: string;
16 | avatar: string;
17 | firstName?: string;
18 | lastName?: string;
19 | name?: string;
20 | username?: string;
21 | email?: string;
22 | status?: string;
23 | phone?: string;
24 | country?: string;
25 | city?: string;
26 | state?: string;
27 | zipcode?: string;
28 | address?: string;
29 | languages?: string[];
30 | roles?: string[];
31 | timezone?: string;
32 | bankTransferOption?: IPerformerPaymentInfo;
33 | directDeposit?: IPerformerDirectDeposit;
34 | paxum?: IPerformerPaxum;
35 | bitpay?: IPerformerBitpay;
36 | createdAt?: Date;
37 | updatedAt?: Date;
38 | balance?: number;
39 | emailVerified?: boolean;
40 | minPayment: number;
41 | swiftCode: string;
42 | address1: string;
43 | address2: string;
44 | payoneer: string;
45 | paypal: string;
46 | certificate: string;
47 | stats?: IStats;
48 | documentVerificationId?: string;
49 | documentVerification?: any;
50 | role?: string;
51 | commission?: number;
52 | grossPrice?: number;
53 | netPrice?: number;
54 | payoutStatus?: string;
55 | }
56 |
--------------------------------------------------------------------------------
/src/interfaces/token-package.ts:
--------------------------------------------------------------------------------
1 | export interface ITokenPackage {
2 | _id: string;
3 | name: string;
4 | price: number;
5 | tokens: number;
6 | description: string;
7 | }
8 |
--------------------------------------------------------------------------------
/src/interfaces/ui-config.ts:
--------------------------------------------------------------------------------
1 | export interface IUIConfig {
2 | collapsed: boolean;
3 | theme: string;
4 | siteName: string;
5 | logo: string;
6 | fixedHeader: boolean;
7 | placeholderLoginUrl: string;
8 | placeholderAvatarUrl: string;
9 | menus: IMenu[];
10 | footerContent: string;
11 | maintenanceMode: boolean;
12 | singularTextModel: string;
13 | pluralTextModel: string;
14 | googleReCaptchaSiteKey: string;
15 | googleReCaptchaEnabled: boolean;
16 | }
17 |
18 | export interface IMenu {
19 | _id: string;
20 | section: string;
21 | path: string;
22 | title: string;
23 | isOpenNewTab: boolean;
24 | internal: boolean;
25 | }
26 |
--------------------------------------------------------------------------------
/src/interfaces/user.ts:
--------------------------------------------------------------------------------
1 | import { ISearch, IStats } from './utils';
2 |
3 | export interface IUser {
4 | _id: string;
5 | avatar: string;
6 | username?: string;
7 | name: string;
8 | email: string;
9 | gender?: string;
10 | firstName?: string;
11 | lastName?: string;
12 | country?: string;
13 | roles?: Array;
14 | role?: string;
15 | phone?: string;
16 | city?: string;
17 | state?: string;
18 | timezone?: string;
19 | dateOfBirth?: Date;
20 | balance: number;
21 | isPerformer?: boolean;
22 | stats?: IStats;
23 | }
24 |
25 | export interface IUserSearch extends ISearch {
26 | role?: string;
27 | }
28 |
--------------------------------------------------------------------------------
/src/interfaces/utils.ts:
--------------------------------------------------------------------------------
1 | export interface ISearch {
2 | q?: string;
3 | limit?: number;
4 | offset?: number;
5 | sortBy?: string;
6 | sort?: string;
7 | }
8 |
9 | export interface IResponse {
10 | data: T;
11 | status: number;
12 | }
13 |
14 | export interface IDataResponse {
15 | data: T[];
16 | total: number;
17 | }
18 |
19 | export interface ICountry {
20 | name: string;
21 | code: string;
22 | flag: string;
23 | }
24 |
25 | export interface ILangguges {
26 | name: string;
27 | code: string;
28 | }
29 |
30 | export interface IPhoneCodes {
31 | name: string;
32 | code: string;
33 | dialCode: string;
34 | }
35 |
36 | export interface IStats {
37 | views?: number;
38 | favorites?: number;
39 | totalVideos?: number;
40 | totalPhotos?: number;
41 | totalGalleries?: number;
42 | totalProducts?: number;
43 | totalStreamTime?: number;
44 | totalTokenEarned: number;
45 | totalTokenSpent: number;
46 | totalPerformer?: number;
47 | totalHoursOnline?: number;
48 | totalOnlineToday?: number;
49 | }
50 |
--------------------------------------------------------------------------------
/src/layouts/auth-layout.less:
--------------------------------------------------------------------------------
1 | @import '../../style/vars.less';
2 |
3 | .auth-content {
4 | background: @white-color;
5 | padding: 10px;
6 | border-radius: 10px;
7 | }
8 |
9 |
10 | @media (max-width: @desktop-query) {
11 | .auth-content {
12 | padding: 50px 5px 5px;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/layouts/default-layout.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/24hrtheraphy/3c014624c37ce2476cd9555c7a4ba416a2155915/src/layouts/default-layout.less
--------------------------------------------------------------------------------
/src/layouts/default-layout.tsx:
--------------------------------------------------------------------------------
1 | import './default-layout.less';
2 | import React from 'react';
3 |
4 | export default ({ children }: any) => {children}
;
5 |
--------------------------------------------------------------------------------
/src/layouts/maintenance-layout.tsx:
--------------------------------------------------------------------------------
1 | import { FunctionComponent } from 'react';
2 |
3 | const MaintenanceLayout: FunctionComponent = () => (
4 |
5 |
6 |
7 |
8 |
9 | );
10 |
11 | export default MaintenanceLayout;
12 |
--------------------------------------------------------------------------------
/src/layouts/primary-layout.less:
--------------------------------------------------------------------------------
1 | @import '../../style/default.less';
2 | .tk-studio {
3 | background:@primary-color;
4 | padding: 15px;
5 | color: #fff;
6 | margin-bottom: 15px;
7 | .stat {
8 | width: 100%;
9 | display: flex;
10 | justify-content: space-between;
11 | }
12 | }
13 |
14 | .btn-live {
15 | width: 100%;
16 | height: 45px;
17 | font-size: 18px;
18 | }
19 |
20 | .footer {
21 | background: #fff;
22 | margin-top: 0;
23 | margin-bottom: 0;
24 | padding-top: 24px;
25 | padding-bottom: 24px;
26 | min-height: 72px;
27 | }
28 |
29 | .ant-divider-horizontal{
30 | margin: 0 0 !important;
31 | }
32 |
33 | .primary-content {
34 | padding: 30px 20px;
35 |
36 | }
37 |
38 | .table {
39 | padding: 16px 24px;
40 | height: 100%;
41 | img {
42 | height: 100px;
43 | width: 100px;
44 | }
45 |
46 | }
47 |
48 | // .ant-row{
49 | // padding: 20px 20px;
50 | // }
51 |
52 | .ant-layout-content {
53 | margin-top: 0px !important;
54 | }
55 |
56 | .ant-card-actions {
57 | background-color: @white-color !important;
58 | border-top: none !important;
59 | }
60 |
--------------------------------------------------------------------------------
/src/layouts/public-layout.less:
--------------------------------------------------------------------------------
1 | @import '../../style/vars.less';
2 | .public-content {
3 | min-height: 100vh;
4 | background: @white-color;
5 | padding: 10px;
6 | border-radius: 10px;
7 | }
8 |
9 | .ant-card-head {
10 | border: none;
11 | }
12 | .ant-btn-default {
13 | border-color: @primary-color !important;
14 | color: @primary-color !important;
15 | }
16 | .ant-card-body {
17 | display: flex;
18 | flex-wrap: wrap;
19 | &::before {
20 | display: block !important;
21 | }
22 | .ant-card-grid {
23 | box-shadow: none;
24 | }
25 | }
26 |
27 | .footer {
28 | background: #fff;
29 | margin-top: 0;
30 | margin-bottom: 0;
31 | padding-top: 24px;
32 | padding-bottom: 24px;
33 | min-height: 72px;
34 | }
35 |
36 | @media (max-width: @desktop-query) {
37 | .public-content {
38 | padding: 50px 5px 5px;
39 | }
40 | }
41 |
42 | .ant-space-wrap {
43 | flex-wrap: wrap;
44 | .ant-space-item {
45 | margin-bottom: 10px;
46 | }
47 | }
48 |
49 | .ant-card-actions {
50 | background-color: @white-color !important;
51 | border-top: none !important;
52 | }
--------------------------------------------------------------------------------
/src/lib/date.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | export function formatDate(date: Date, format = 'DD/MM/YYYY HH:mm:ss') {
4 | return moment(date).format(format);
5 | }
6 |
7 | export function converDuration(duration: number, format = 'HH:mm') {
8 | return moment
9 | .utc(moment.duration(duration, 'milliseconds').asMilliseconds())
10 | .format(format);
11 | }
12 |
13 | export function parseAge(date: string, format = 'MMMM DD, YYYY') {
14 | return moment(date).format(format);
15 | }
16 |
17 | export function getAge(date: Date): string {
18 | return moment().diff(moment(date).format('YYYY-MM-DD'), 'years').toString();
19 | }
20 |
21 | export function formatDuration(s: number) {
22 | const hours = Math.floor(s / 3600);
23 | const minutes = Math.floor((s - hours * 3600) / 60);
24 | const seconds = s - hours * 3600 - minutes * 60;
25 | return `${hours < 10 ? '0' : ''}${hours}:${
26 | minutes < 10 ? '0' : ''
27 | }${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
28 | }
29 |
--------------------------------------------------------------------------------
/src/lib/file.ts:
--------------------------------------------------------------------------------
1 | import { getGlobalConfig } from '@services/config';
2 | import { message } from 'antd';
3 | import { RcFile } from 'antd/lib/upload';
4 |
5 | export function beforeAvatarUpload(file: RcFile): boolean {
6 | const ext = file.name.split('.').pop().toLowerCase();
7 | const config = getGlobalConfig();
8 | const isImageAccept = config.NEXT_PUBLIC_IMAGE_ACCPET
9 | .split(',')
10 | .map((item: string) => item.trim())
11 | .indexOf(`.${ext}`);
12 | if (isImageAccept === -1) {
13 | message.error(`You can only upload ${config.NEXT_PUBLIC_IMAGE_ACCPET} file!`);
14 | return false;
15 | }
16 |
17 | const isLt2M = file.size / 1024 / 1024 < (config.NEXT_PUBLIC_MAXIMUM_SIZE_UPLOAD_AVATAR || 2);
18 | if (!isLt2M) {
19 | message.error(
20 | `Image must smaller than ${config.NEXT_PUBLIC_MAXIMUM_SIZE_UPLOAD_AVATAR || 2}MB!`
21 | );
22 | return false;
23 | }
24 |
25 | return true;
26 | }
27 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './internet';
2 | export * from './redux';
3 | export * from './string';
4 | export * from './date';
5 | export * from './message';
6 | export * from './layout';
7 | export * from './utils';
8 | export * from './rules';
9 | export * from './file';
10 | export * from './stream';
11 |
--------------------------------------------------------------------------------
/src/lib/internet.ts:
--------------------------------------------------------------------------------
1 | const INTERNET_CHECK_URL = 'https://google.com';
2 |
3 | export const isHasInternetConnection = async (): Promise => {
4 | try {
5 | const res = await fetch(INTERNET_CHECK_URL, {
6 | headers: {
7 | 'Cache-Control': 'no-cache, no-store, must-revalidate',
8 | Pragma: 'no-cache',
9 | Expires: 0
10 | } as any
11 | });
12 | if (
13 | res.status === 404
14 | || res.status === 401
15 | || res.status === 403
16 | || res.status === 500
17 | || (res.status >= 200 && res.status <= 300)
18 | ) {
19 | return true;
20 | }
21 | } catch (exception) {
22 | // eslint-disable-next-line no-console
23 | console.log(exception);
24 | }
25 | return false;
26 | };
27 |
--------------------------------------------------------------------------------
/src/lib/layout.ts:
--------------------------------------------------------------------------------
1 | export const formItemLayout = {
2 | labelCol: {
3 | xs: {
4 | span: 24
5 | },
6 | sm: {
7 | span: 12
8 | }
9 | },
10 | wrapperCol: {
11 | xs: {
12 | span: 24
13 | },
14 | sm: {
15 | span: 12
16 | }
17 | }
18 | };
19 |
20 | export const tailFormItemLayout = {
21 | wrapperCol: {
22 | xs: {
23 | span: 24,
24 | offset: 0
25 | },
26 | sm: {
27 | span: 16,
28 | offset: 0
29 | }
30 | }
31 | };
32 |
33 | export const defaultColor = {
34 | primaryColor: '#0cb8b6',
35 | successColor: '#2fb52d',
36 | whiteColor: '#ffffff'
37 | };
38 |
39 | export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
40 | export type BreakpointMap = Partial>;
41 |
--------------------------------------------------------------------------------
/src/lib/message.ts:
--------------------------------------------------------------------------------
1 | export const validateMessages = {
2 | required: 'This field is required!',
3 | types: {
4 | email: 'Not a validate email!',
5 | number: 'Not a validate number!'
6 | },
7 | number: {
8 | range: 'Must be between min and max'
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/lib/rules.ts:
--------------------------------------------------------------------------------
1 | export const usernamePatternRule = {
2 | pattern: new RegExp('^[a-zA-Z0-9]*$'),
3 | message: 'Dont allow special chars or space'
4 | };
5 |
--------------------------------------------------------------------------------
/src/lib/storeHolder.ts:
--------------------------------------------------------------------------------
1 | import { Store as RDStore } from 'redux';
2 |
3 | export type Store = RDStore<{}>;
4 |
5 | let store: Store | null = null;
6 |
7 | export default {
8 | getStore: () => store,
9 | setStore: (s: Store) => {
10 | store = s;
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/src/lib/stream.ts:
--------------------------------------------------------------------------------
1 | import storeHolder from './storeHolder';
2 |
3 | export const DEFAULT_OFFLINE_IMAGE_URL = '/offline.png';
4 | export const DEFAULT_PRIVATE_IMAGE_URL = '/private.png';
5 | export const DEFAULT_GROUP_IMAGE_URL = '/group.png';
6 | export const DEFAULT_ONLINE_IMAGE_URL = '';
7 |
8 | export function getPoster(status: string): string {
9 | let poster = '';
10 | const store = storeHolder.getStore();
11 | const { settings = {} } = store.getState() as any;
12 | switch (status) {
13 | case 'private':
14 | poster = settings.defaultPrivateCallImage || DEFAULT_PRIVATE_IMAGE_URL;
15 | break;
16 | case 'offline':
17 | poster = settings.defaultOfflineModelImage || DEFAULT_OFFLINE_IMAGE_URL;
18 | break;
19 | case 'public':
20 | poster = DEFAULT_ONLINE_IMAGE_URL;
21 | break;
22 | case 'group':
23 | poster = settings.defaultGroupChatImage || DEFAULT_GROUP_IMAGE_URL;
24 | break;
25 | default:
26 | poster = DEFAULT_OFFLINE_IMAGE_URL;
27 | break;
28 | }
29 | return poster;
30 | }
31 |
--------------------------------------------------------------------------------
/src/redux/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction } from '@lib/redux';
2 |
3 | export const setReadyState = createAction('APP_STATE_SUCCESS');
4 | export const resetAppState = createAction('APP_STATE_RESET');
5 |
--------------------------------------------------------------------------------
/src/redux/banner/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAsyncAction } from '@lib/redux';
2 |
3 | export const {
4 | getBanners,
5 | getBannersSuccess,
6 | getBannersFail
7 | } = createAsyncAction('getBanners', 'GET_BANNERS');
8 |
--------------------------------------------------------------------------------
/src/redux/banner/reducers.ts:
--------------------------------------------------------------------------------
1 | import { createReducers } from '@lib/redux';
2 | import { merge } from 'lodash';
3 | import { getBannersSuccess, getBannersFail } from './actions';
4 |
5 | const initialState = {
6 | listBanners: {
7 | loading: false,
8 | data: [],
9 | error: null,
10 | success: false
11 | }
12 | };
13 |
14 | const bannerReducer = [
15 | {
16 | on: getBannersSuccess,
17 | reducer(state: any, data: any) {
18 | return {
19 | ...state,
20 | listBanners: {
21 | loading: false,
22 | data: data.payload,
23 | error: null,
24 | success: true
25 | }
26 | };
27 | }
28 | },
29 | {
30 | on: getBannersFail,
31 | reducer(state: any, data: any) {
32 | return {
33 | ...state,
34 | listBanners: {
35 | ...state.listBanners,
36 | loading: false,
37 | data: null,
38 | error: data.payload,
39 | success: false
40 | }
41 | };
42 | }
43 | }
44 | ];
45 |
46 | export default merge(
47 | {},
48 | createReducers('banner', [bannerReducer], initialState)
49 | );
50 |
--------------------------------------------------------------------------------
/src/redux/banner/sagas.ts:
--------------------------------------------------------------------------------
1 | import { flatten } from 'lodash';
2 | import { put } from 'redux-saga/effects';
3 | import { createSagas } from '@lib/redux';
4 | import { bannerService } from 'src/services';
5 | import { IReduxAction } from 'src/interfaces';
6 | import { getBanners, getBannersSuccess, getBannersFail } from './actions';
7 |
8 | const bannerSagas = [
9 | {
10 | on: getBanners,
11 | * worker(data: IReduxAction) {
12 | try {
13 | const resp = yield bannerService.search(data.payload);
14 | yield put(getBannersSuccess(resp.data));
15 | } catch (e) {
16 | const error = yield Promise.resolve(e);
17 | yield put(getBannersFail(error));
18 | }
19 | }
20 | }
21 | ];
22 |
23 | export default flatten([createSagas(bannerSagas)]);
24 |
--------------------------------------------------------------------------------
/src/redux/galleries/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction, createAsyncActions } from '@lib/redux';
2 |
3 | export const [
4 | getPerformerGalleries,
5 | getPerformerGalleriesSuccess,
6 | getPerformerGalleriesFail
7 | ] = createAsyncActions('GET_PERFORMER_GALLERIES');
8 | export const gettingPerformerGalleries = createAction('GETTING_PERFORMER_GALLERIES');
9 |
10 | export const addPerformerGalleries = createAction('ADD_PERFORMER_GALLERIES');
11 | export const purchaseGallerySuccess = createAction('PURCHASE_GALLERY_SUCCESS');
12 |
--------------------------------------------------------------------------------
/src/redux/photos/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction, createAsyncActions } from '@lib/redux';
2 |
3 | export const [
4 | getPerformerPhotos,
5 | getPerformerPhotosSuccess,
6 | getPerformerPhotosFail
7 | ] = createAsyncActions('GET_PERFORMER_PHOTOS');
8 | export const gettingPerformerPhotos = createAction('GETTING_PERFORMER_PHOTOS');
9 |
--------------------------------------------------------------------------------
/src/redux/photos/reducers.ts:
--------------------------------------------------------------------------------
1 | import { createReducers } from '@lib/redux';
2 | import { merge } from 'lodash';
3 | import { IReduxAction, IPhoto, IDataResponse } from 'src/interfaces';
4 | import {
5 | gettingPerformerPhotos,
6 | getPerformerPhotosSuccess,
7 | getPerformerPhotosFail
8 | } from './actions';
9 |
10 | const initialPhotosState = {
11 | error: null,
12 | data: {},
13 | total: 0,
14 | success: false,
15 | searching: false
16 | };
17 | const photoReducers = [
18 | {
19 | on: gettingPerformerPhotos,
20 | reducer() {
21 | return {
22 | ...initialPhotosState,
23 | searching: true
24 | };
25 | }
26 | },
27 | {
28 | on: getPerformerPhotosSuccess,
29 | reducer(_, action: IReduxAction>) {
30 | return {
31 | error: null,
32 | data: action.payload.data,
33 | total: action.payload.total,
34 | success: true,
35 | searching: false
36 | };
37 | }
38 | },
39 | {
40 | on: getPerformerPhotosFail,
41 | reducer(_, action: IReduxAction>) {
42 | return {
43 | data: null,
44 | error: action.payload,
45 | success: false,
46 | searching: false
47 | };
48 | }
49 | }
50 | ];
51 | export default merge(
52 | {},
53 | createReducers('photos', [photoReducers], initialPhotosState)
54 | );
55 |
--------------------------------------------------------------------------------
/src/redux/photos/sagas.ts:
--------------------------------------------------------------------------------
1 | import { put } from 'redux-saga/effects';
2 | import { flatten } from 'lodash';
3 | import { createSagas } from '@lib/redux';
4 | import {
5 | IReduxAction, IResponse, IDataResponse, IPhoto
6 | } from 'src/interfaces';
7 | import { getResponseError } from 'src/lib';
8 | import { photoService } from 'src/services';
9 | import {
10 | getPerformerPhotos,
11 | gettingPerformerPhotos,
12 | getPerformerPhotosSuccess,
13 | getPerformerPhotosFail
14 | } from './actions';
15 |
16 | const photosSagas = [
17 | {
18 | on: getPerformerPhotos,
19 | * worker(action: IReduxAction) {
20 | try {
21 | yield put(gettingPerformerPhotos());
22 | const resp: IResponse> = yield photoService.search(action.payload);
23 | yield put(getPerformerPhotosSuccess({ data: resp.data.data, total: resp.data.total }));
24 | } catch (error) {
25 | const err = getResponseError(error);
26 | yield put(getPerformerPhotosFail(err));
27 | }
28 | }
29 | }
30 | ];
31 |
32 | export default flatten([createSagas(photosSagas)]);
33 |
--------------------------------------------------------------------------------
/src/redux/products/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction, createAsyncActions } from '@lib/redux';
2 |
3 | export const [
4 | getPerformerProducts,
5 | getPerformerProductsSuccess,
6 | getPerformerProductsFail
7 | ] = createAsyncActions('GET_PERFORMER_PRODUCTS');
8 |
9 | export const gettingPerformerProduct = createAction('GETTING_PERFORMER_PRODUCTS');
10 |
11 | export const loadMorePerformerProduct = createAction('LOAD_MORE_PERFORMER_PRODUCT');
12 | export const purchaseProductSuccess = createAction('PURCHASE_PRODUCT_SUCCESS');
13 |
--------------------------------------------------------------------------------
/src/redux/rootReducer.ts:
--------------------------------------------------------------------------------
1 | import { merge } from 'lodash';
2 | import { combineReducers } from 'redux';
3 |
4 | // load reducer here
5 | import settings from './settings/reducers';
6 | import ui from './ui/reducers';
7 | import user from './user/reducers';
8 | import auth from './auth/reducers';
9 | import performer from './performer/reducers';
10 | import message from './message/reducers';
11 | import streamMessage from './stream-chat/reducers';
12 | import streaming from './streaming/reducers';
13 | import videos from './videos/reducers';
14 | import photos from './photos/reducers';
15 | import products from './products/reducers';
16 | import galleries from './galleries/reducers';
17 | import studio from './studio/reducers';
18 | import banner from './banner/reducers';
19 |
20 | const reducers = merge(
21 | settings,
22 | ui,
23 | user,
24 | auth,
25 | performer,
26 | message,
27 | streamMessage,
28 | streaming,
29 | videos,
30 | photos,
31 | products,
32 | galleries,
33 | studio,
34 | banner
35 | );
36 |
37 | export default combineReducers(reducers);
38 |
--------------------------------------------------------------------------------
/src/redux/rootSaga.ts:
--------------------------------------------------------------------------------
1 | import { all, spawn } from 'redux-saga/effects';
2 |
3 | import userSagas from './user/sagas';
4 | import authSagas from './auth/sagas';
5 | import performerSagas from './performer/sagas';
6 | import messageSagas from './message/sagas';
7 | import settingSagas from './settings/sagas';
8 | import streamMessageSagas from './stream-chat/sagas';
9 | import videosSagas from './videos/sagas';
10 | import photosSagas from './photos/sagas';
11 | import productSagas from './products/sagas';
12 | import galleriesSagas from './galleries/sagas';
13 | import studioSagas from './studio/sagas';
14 | import bannerSagas from './banner/sagas';
15 |
16 | function* rootSaga() {
17 | yield all(
18 | [
19 | ...authSagas,
20 | ...userSagas,
21 | ...performerSagas,
22 | ...messageSagas,
23 | ...settingSagas,
24 | ...streamMessageSagas,
25 | ...videosSagas,
26 | ...photosSagas,
27 | ...productSagas,
28 | ...galleriesSagas,
29 | ...studioSagas,
30 | ...bannerSagas
31 | ].map(spawn)
32 | );
33 | }
34 |
35 | export default rootSaga;
36 |
--------------------------------------------------------------------------------
/src/redux/selectors.ts:
--------------------------------------------------------------------------------
1 | import { createSelector } from 'reselect';
2 |
3 | const userSelecter = (state) => state.user.current;
4 | const performerSelecter = (state) => state.performer.current;
5 | const studioSelecter = (state) => state.studio.current;
6 | const authSelecter = (state) => state.auth;
7 |
8 | export const currentUserSelecter = createSelector(
9 | userSelecter,
10 | performerSelecter,
11 | studioSelecter,
12 | authSelecter,
13 | (user, performer, studio, auth) => {
14 | if (!auth.loggedIn) return null;
15 |
16 | if (user?._id) {
17 | return { ...user, role: 'user' };
18 | }
19 |
20 | if (performer?._id) {
21 | return { ...performer, role: 'performer' };
22 | }
23 |
24 | if (studio?._id) {
25 | return { ...studio, role: 'studio' };
26 | }
27 |
28 | return null;
29 | }
30 | );
31 |
--------------------------------------------------------------------------------
/src/redux/settings/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction } from '@lib/redux';
2 |
3 | export const updateSettings = createAction('updateSettings');
4 | export const getCountries = createAction('getCountries');
5 |
--------------------------------------------------------------------------------
/src/redux/settings/reducers.ts:
--------------------------------------------------------------------------------
1 | import { merge } from 'lodash';
2 | import { createReducers } from '@lib/redux';
3 | import { updateSettings } from './actions';
4 |
5 | // TODO -
6 | const initialState = {
7 | countries: []
8 | };
9 |
10 | const settingReducers = [
11 | {
12 | on: updateSettings,
13 | reducer(state: any, data: any) {
14 | return {
15 | ...state,
16 | ...data.payload
17 | };
18 | }
19 | }
20 | ];
21 |
22 | export default merge({}, createReducers('settings', [settingReducers], initialState));
23 |
--------------------------------------------------------------------------------
/src/redux/settings/sagas.ts:
--------------------------------------------------------------------------------
1 | import { put, select } from 'redux-saga/effects';
2 | import { createSagas } from '@lib/redux';
3 | import { IResponse } from 'src/interfaces';
4 | import { settingService } from 'src/services';
5 | import { flatten } from 'lodash';
6 | import { getCountries, updateSettings } from './actions';
7 |
8 | const settingSagas = [
9 | {
10 | on: getCountries,
11 | * worker() {
12 | try {
13 | const countries = yield select((state) => state.settings.countries);
14 | if (countries && countries.length) return;
15 | const resp: IResponse = yield settingService.getCountries();
16 | yield put(updateSettings({ countries: resp.data }));
17 | } catch (e) {
18 | // eslint-disable-next-line no-console
19 | console.log(e);
20 | }
21 | }
22 | }
23 | ];
24 |
25 | export default flatten([createSagas(settingSagas)]);
26 |
--------------------------------------------------------------------------------
/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | import { applyMiddleware, createStore } from 'redux';
2 | import createSagaMiddleware from 'redux-saga';
3 | // import { composeWithDevTools } from 'remote-redux-devtools';
4 | import storeHolder from '@lib/storeHolder';
5 | import rootReducer from './rootReducer';
6 | import rootSaga from './rootSaga';
7 |
8 | const bindMiddleware = (middleware: any) => applyMiddleware(...middleware);
9 |
10 | /**
11 | * const composeEnhancers = composeWithDevTools({
12 | * realtime: true,
13 | * name: 'xcams user',
14 | * hostname: 'localhost',
15 | * port: 8000 // the port your remotedev server is running at
16 | * });
17 | */
18 |
19 | function configureStore(initialState: any) {
20 | const sagaMiddleware = createSagaMiddleware();
21 | const store = createStore(rootReducer, initialState, bindMiddleware([sagaMiddleware])) as any;
22 | /**
23 | * redux dev tool
24 | * const store = createStore(rootReducer, initialState, composeEnhancers(bindMiddleware([sagaMiddleware]))) as any;
25 | */
26 |
27 | store.sagaTask = sagaMiddleware.run(rootSaga);
28 |
29 | storeHolder.setStore(store);
30 |
31 | return store;
32 | }
33 |
34 | export default configureStore;
35 |
--------------------------------------------------------------------------------
/src/redux/stream-chat/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction, createAsyncAction } from '@lib/redux';
2 |
3 | export const {
4 | getStreamConversation,
5 | getStreamConversationSuccess,
6 | getStreamConversationFail
7 | } = createAsyncAction('getStreamConversation', 'GET_STREAM_CONVERSATION');
8 |
9 | export const {
10 | sendStreamMessage,
11 | sendStreamMessageSuccess,
12 | sendStreamMessageFail
13 | } = createAsyncAction('sendStreamMessage', 'SEND_STREAM_MESSAGE');
14 |
15 | export const {
16 | receiveStreamMessageSuccess
17 | } = createAsyncAction('receiveStreamMessageSuccess', 'RECEIVE_STREAM_MESSAGE_SUCCESS');
18 |
19 | export const {
20 | loadStreamMessages,
21 | loadStreamMessagesSuccess,
22 | loadStreamMessagesFail
23 | } = createAsyncAction('loadStreamMessages', 'LOAD_STREAM_MESSAGES');
24 |
25 | export const {
26 | loadMoreStreamMessages,
27 | loadMoreStreamMessagesSuccess,
28 | loadMoreStreamMessagesFail
29 | } = createAsyncAction('loadMoreStreamMessages', 'LOAD_MORE_STREAM_MESSAGES');
30 |
31 | export const fetchingStreamMessage = createAction('fetchingStreamMessage');
32 |
33 | export const resetStreamMessage = createAction('resetStreamMessage');
34 | export const resetAllStreamMessage = createAction('resetAllStreamMessage');
35 | export const resetStreamConversation = createAction('RESET_STREAM_CONVERSATION');
36 |
37 | export const {
38 | deleteMessage,
39 | deleteMessageSuccess,
40 | deleteMessageFail
41 | } = createAsyncAction('deleteMessage', 'DELETE_MESSAGE');
42 |
--------------------------------------------------------------------------------
/src/redux/streaming/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction } from '@lib/redux';
2 |
3 | export const addPrivateRequest = createAction('ADD_PRIVATE_REQUEST');
4 | export const accessPrivateRequest = createAction('ACCESS_PRIVATE_REQUSET');
5 | export const updateLiveStreamSettings = createAction('UPDATE_LIVE_STREAM_SETTINGS');
6 |
--------------------------------------------------------------------------------
/src/redux/streaming/reducers.ts:
--------------------------------------------------------------------------------
1 | import { merge } from 'lodash';
2 | import { createReducers } from '@lib/redux';
3 | import { IReduxAction } from 'src/interfaces';
4 | import {
5 | addPrivateRequest, accessPrivateRequest, updateLiveStreamSettings
6 | } from './actions';
7 |
8 | const initialState = {
9 | privateRequests: [],
10 | settings: {
11 | viewerURL: '',
12 | publisherURL: '',
13 | optionForBroadcast: 'hls',
14 | optionForPrivate: 'hls',
15 | secureOption: false
16 | }
17 | };
18 |
19 | const reducers = [
20 | {
21 | on: addPrivateRequest,
22 | reducer(state: any, action: IReduxAction) {
23 | return {
24 | ...state,
25 | privateRequests: [...state.privateRequests, action.payload]
26 | };
27 | }
28 | },
29 | {
30 | on: accessPrivateRequest,
31 | reducer(state: any, action: IReduxAction) {
32 | return {
33 | ...state,
34 | privateRequests: state.privateRequests.filter((p) => p.conversationId !== action.payload)
35 | };
36 | }
37 | },
38 | {
39 | on: updateLiveStreamSettings,
40 | reducer(state: any, action: IReduxAction) {
41 | return {
42 | ...state,
43 | settings: {
44 | ...state.settings,
45 | ...action.payload
46 | }
47 | };
48 | }
49 | }
50 | ];
51 | export default merge({}, createReducers('streaming', [reducers], initialState));
52 |
--------------------------------------------------------------------------------
/src/redux/ui/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAction } from '@lib/redux';
2 |
3 | export const updateUIValue = createAction('updateUIValue');
4 | export const loadUIValue = createAction('loadUIValue');
5 |
--------------------------------------------------------------------------------
/src/redux/ui/reducers.ts:
--------------------------------------------------------------------------------
1 | import { merge } from 'lodash';
2 | import { createReducers } from '@lib/redux';
3 | import { updateUIValue, loadUIValue } from './actions';
4 |
5 | // TODO -
6 | const initialState = {
7 | theme: 'light',
8 | siteName: '',
9 | logo: '',
10 | banner: '',
11 | menus: [],
12 | placeholderAvatarUrl: '/no-avatar.png',
13 | placeholderLoginUrl: '/img/log-in-img.jpg',
14 | footerContent: '',
15 | enablePopup18Plus: true,
16 | popupContent18Plus: ''
17 | };
18 |
19 | const uiReducers = [
20 | {
21 | on: updateUIValue,
22 | reducer(state: any, data: any) {
23 | if (process.browser) {
24 | Object.keys(data.payload).forEach(
25 | (key) => localStorage && localStorage.setItem(key, data.payload[key])
26 | );
27 | }
28 | return {
29 | ...state,
30 | ...data.payload
31 | };
32 | }
33 | },
34 | {
35 | on: loadUIValue,
36 | reducer(state: any) {
37 | const newVal = {};
38 | if (process.browser) {
39 | Object.keys(initialState).forEach((key) => {
40 | const val = state[key] || localStorage.getItem(key);
41 | if (val) {
42 | newVal[key] = val;
43 | }
44 | });
45 | }
46 | return {
47 | ...state,
48 | ...newVal
49 | };
50 | }
51 | }
52 | ];
53 |
54 | export default merge({}, createReducers('ui', [uiReducers], initialState));
55 |
--------------------------------------------------------------------------------
/src/redux/user/actions.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createAction,
3 | createAsyncAction
4 | } from '@lib/redux';
5 |
6 | export const updateCurrentUser = createAction('updateCurrentUser');
7 | export const updateCurrentUserAvatar = createAction('updateCurrentUserAvatar');
8 | export const updateCurrentUserBalance = createAction(
9 | 'updateCurrentUserBalance'
10 | );
11 |
12 | export const {
13 | updateUser,
14 | updateUserSuccess,
15 | updateUserFail
16 | } = createAsyncAction('updateUser', 'UPDATE_USER');
17 |
18 | export const setUpdating = createAction('updatingUser');
19 |
20 | export const setReducer = createAction('setUserReducer');
21 |
22 | export const buyTokenSuccess = createAction('buyTokenSuccess');
23 |
24 | export const {
25 | getFavoritePerformers,
26 | getFavoritePerformersSuccess,
27 | getFavoritePerformersFailed
28 | } = createAsyncAction('getFavoritePerformers', 'GET_FAVOURITE');
29 | export const gettingFavoritePerformers = createAction('GETTING_FAVORITE');
30 | export const removeFavorite = createAction('REMOVE_FAVORITE');
31 |
32 | export const {
33 | getPaymentTokenHistroy,
34 | getPaymentTokenHistroySuccess,
35 | getPaymentTokenHistroyFail
36 | } = createAsyncAction('getPaymentTokenHistroy', 'GET_PAYMET_TOKE_HISTORY');
37 | export const gettigPaymentTokenHistory = createAction('GETTING_PAYMET_TOKE_HISTORY');
38 |
--------------------------------------------------------------------------------
/src/redux/videos/actions.ts:
--------------------------------------------------------------------------------
1 | import { createAsyncActions, createAction } from '@lib/redux';
2 |
3 | export const [
4 | getPerformersVideos,
5 | getPerformersVideosSuccess,
6 | getPerformersVideosFail
7 | ] = createAsyncActions('GET_PERFOMER_VIDEOS');
8 | export const gettingPerformerVideos = createAction('GETTING_PERFORMER_VIDEOS');
9 | export const addPerformerVideos = createAction('ADD_PERFORMER_VIDEOS');
10 |
--------------------------------------------------------------------------------
/src/redux/withReduxSaga.ts:
--------------------------------------------------------------------------------
1 | import nextReduxWrapper from 'next-redux-wrapper';
2 | import nextReduxSaga from 'next-redux-saga';
3 | import store from './store';
4 |
5 | const withReduxSaga = (BaseComponent: any) => nextReduxWrapper(store as any)(nextReduxSaga(BaseComponent));
6 |
7 | export default withReduxSaga;
8 |
--------------------------------------------------------------------------------
/src/services/banner.service.ts:
--------------------------------------------------------------------------------
1 | import { IBannerSearch } from 'src/interfaces';
2 | import { APIRequest } from './api-request';
3 |
4 | export class BannerService extends APIRequest {
5 | search(query: IBannerSearch) {
6 | return this.get(this.buildUrl('/banners/search', query as any));
7 | }
8 | }
9 |
10 | export const bannerService = new BannerService();
11 |
--------------------------------------------------------------------------------
/src/services/coinbase.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from "./api-request";
2 |
3 | interface ICoinbaseChargeRequest {
4 | tokenPackage: string;
5 | }
6 |
7 | class CoinbaseRequestService extends APIRequest {
8 | async createCharge(
9 | { tokenPackage }: ICoinbaseChargeRequest,
10 | signal?: AbortSignal
11 | ): Promise {
12 | return this.post(`/coinbase/charge`, { tokenPackage }, {}, signal);
13 | }
14 | }
15 |
16 | export const coinbaseRequestService = new CoinbaseRequestService();
17 |
--------------------------------------------------------------------------------
/src/services/config.ts:
--------------------------------------------------------------------------------
1 | let globalConfig = {} as any;
2 |
3 | export const setGlobalConfig = (config: any) => {
4 | globalConfig = config;
5 | };
6 |
7 | export const getGlobalConfig = () => globalConfig;
8 |
--------------------------------------------------------------------------------
/src/services/earning.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | class EarningService extends APIRequest {
4 | search(params?: { [key: string]: string }, role = 'performer') {
5 | return this.get(this.buildUrl(`/earning/${role}/search`, params));
6 | }
7 |
8 | stats(params?: { [key: string]: string }, role = 'performer') {
9 | return this.get(this.buildUrl(`/earning/${role}/stats`, params));
10 | }
11 | }
12 |
13 | export const earningService = new EarningService();
14 |
--------------------------------------------------------------------------------
/src/services/favourite.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | class FavouriteService extends APIRequest {
4 | like(id: string) {
5 | return this.post(`/favourite/${id}/like`);
6 | }
7 |
8 | unlike(id: string) {
9 | return this.post(`/favourite/${id}/unlike`);
10 | }
11 |
12 | favorite(id: string, isFavorited: boolean) {
13 | return this.post(`/favourite/${id}/${isFavorited ? 'unlike' : 'like'}`);
14 | }
15 |
16 | search(query: { [key: string]: string }) {
17 | return this.get(this.buildUrl('/favourite', query));
18 | }
19 | }
20 |
21 | export const favouriteService = new FavouriteService();
22 |
--------------------------------------------------------------------------------
/src/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './auth.service';
2 | export * from './user.service';
3 | export * from './post.service';
4 | export * from './perfomer-categories.service';
5 | export * from './perfomer.service';
6 | export * from './video.service';
7 | export * from './product.service';
8 | export * from './setting.service';
9 | export * from './photo.service';
10 | export * from './gallery.service';
11 | export * from './favourite.service';
12 | export * from './token-package.service';
13 | export * from './transaction.service';
14 | export * from './stream.service';
15 | export * from './message.service';
16 | export * from './purchase-item.service';
17 | export * from './order.service';
18 | export * from './earning.service';
19 | export * from './payout-request';
20 | export * from './refund-request.service';
21 | export * from './utils.service';
22 | export * from './studio.service';
23 | export * from './banner.service';
24 | export * from './payment-information.service';
25 | export * from './stream.service';
26 |
--------------------------------------------------------------------------------
/src/services/order.service.ts:
--------------------------------------------------------------------------------
1 | // import { IGalleryCreate } from 'src/interfaces';
2 | import { APIRequest } from './api-request';
3 |
4 | export class OrderService extends APIRequest {
5 | search(payload) {
6 | return this.get(this.buildUrl('/orders/search', payload));
7 | }
8 |
9 | details(id) {
10 | return this.get(`/orders/details/${id}`);
11 | }
12 |
13 | update(id, data) {
14 | return this.put(`/orders/${id}/update`, data);
15 | }
16 |
17 | userSearch(query) {
18 | return this.get(this.buildUrl('/orders/user/search', query));
19 | }
20 |
21 | userFindDetails(id) {
22 | return this.get(`/orders/user/details/${id}`);
23 | }
24 | }
25 |
26 | export const orderService = new OrderService();
27 |
--------------------------------------------------------------------------------
/src/services/payment-information.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | class PaymentInformationService extends APIRequest {
4 | create(data) {
5 | return this.post('/payment-information', data);
6 | }
7 |
8 | findOne(data) {
9 | return this.get(this.buildUrl('/payment-information', data));
10 | }
11 | }
12 |
13 | export const paymentInformationService = new PaymentInformationService();
14 |
--------------------------------------------------------------------------------
/src/services/payout-request.ts:
--------------------------------------------------------------------------------
1 | import { IResponse } from 'src/interfaces';
2 | import { APIRequest } from './api-request';
3 |
4 | class PayoutRequestService extends APIRequest {
5 | calculate(params: { [key: string]: string }, role: string) {
6 | return this.get(
7 | this.buildUrl(`/earning/${role || 'performer'}/payout`, params)
8 | );
9 | }
10 |
11 | search(query: { [key: string]: string }) {
12 | return this.get(this.buildUrl('/payout-requests/performer/search', query));
13 | }
14 |
15 | studioSearch(query: { [key: string]: string }) {
16 | return this.get(this.buildUrl('/payout-requests/studio/search', query));
17 | }
18 |
19 | create(body: any, role = 'performer') {
20 | return this.post(`/payout-requests/${role}`, body);
21 | }
22 |
23 | update(id: string, body: any, role = 'performer') {
24 | return this.put(`/payout-requests/${role}/${id}`, body);
25 | }
26 |
27 | detail(
28 | id: string,
29 | headers: {
30 | [key: string]: string;
31 | },
32 | role = 'performer'
33 | ): Promise> {
34 | return this.get(`/payout-requests/${role}/${id}/view`, headers);
35 | }
36 | }
37 |
38 | export const payoutRequestService = new PayoutRequestService();
39 |
--------------------------------------------------------------------------------
/src/services/paypal.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from "./api-request";
2 |
3 | interface IPaypalCheckoutRequest {
4 | nonce: string;
5 | tokenId: string;
6 | }
7 |
8 | class PaypalRequestService extends APIRequest {
9 | async purchaseToken(
10 | { nonce, tokenId }: IPaypalCheckoutRequest,
11 | signal?: AbortSignal
12 | ) {
13 | return this.post(
14 | `/paypal/checkout/token/${tokenId}`,
15 | { nonce },
16 | {},
17 | signal
18 | );
19 | }
20 |
21 | async getPaypalClientToken(signal?: AbortSignal) {
22 | const response = await this.get(`/paypal/client_token`, {}, signal);
23 | return response.data.clientToken;
24 | }
25 | }
26 |
27 | export const paypalRequestService = new PaypalRequestService();
28 |
--------------------------------------------------------------------------------
/src/services/perfomer-categories.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class PerformerCategoriesService extends APIRequest {
4 | getList(query?: { [key: string]: any }) {
5 | return this.get(this.buildUrl('/performer-categories', query));
6 | }
7 |
8 | details(id: string) {
9 | return this.get(`/performer-categories/${id}/view`);
10 | }
11 | }
12 |
13 | export const performerCategories = new PerformerCategoriesService();
14 |
--------------------------------------------------------------------------------
/src/services/post.service.ts:
--------------------------------------------------------------------------------
1 | import { IPostSearch } from 'src/interfaces';
2 | import { APIRequest } from './api-request';
3 |
4 | export class PostService extends APIRequest {
5 | search(query: IPostSearch) {
6 | return this.get(this.buildUrl('/posts/search', query as any));
7 | }
8 |
9 | findById(id: string) {
10 | return this.get(`/posts/${id}`);
11 | }
12 |
13 | createContactCotent(data: Record) {
14 | return this.post('/contact', { ...data });
15 | }
16 | }
17 |
18 | export const postService = new PostService();
19 |
--------------------------------------------------------------------------------
/src/services/product.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class ProductService extends APIRequest {
4 | details(id: string, headers?: { [key: string]: string; }) {
5 | return this.get(`/performer/performer-assets/products/${id}/view`, headers);
6 | }
7 |
8 | search(params?: { [key: string]: any }) {
9 | return this.get(this.buildUrl('/user/performer-assets/products/search', params));
10 | }
11 |
12 | purchased(params?: { [key: string]: any }) {
13 | return this.get(this.buildUrl('/purchased-items/user/products', params));
14 | }
15 |
16 | getDownloadLink(id: string) {
17 | return this.get(`/user/performer-assets/products/${id}/download-link`);
18 | }
19 | }
20 |
21 | export const productService = new ProductService();
22 |
--------------------------------------------------------------------------------
/src/services/purchase-item.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class PurchaseItemService extends APIRequest {
4 | search(query) {
5 | return this.get(this.buildUrl('/purchased-items/user/search', query));
6 | }
7 |
8 | purchaseItem(id: string, type: string, data?: any) {
9 | return this.post(`/purchase-items/${type}/${id}`, data);
10 | }
11 |
12 | purchaseProduct(id: string) {
13 | return this.post(`/purchase-items/product/${id}`);
14 | }
15 |
16 | purchaseVideo(id: string) {
17 | return this.post(`/purchase-items/video/${id}`);
18 | }
19 | }
20 |
21 | export const purchaseItemService = new PurchaseItemService();
22 |
--------------------------------------------------------------------------------
/src/services/refund-request.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class RefundRequestService extends APIRequest {
4 | create(data) {
5 | return this.post('/refund-requests', data);
6 | }
7 |
8 | search(params?: { [key: string]: any }) {
9 | return this.get(this.buildUrl('/refund-requests/search', params));
10 | }
11 | }
12 |
13 | export const refundRequestService = new RefundRequestService();
14 |
--------------------------------------------------------------------------------
/src/services/setting.service.ts:
--------------------------------------------------------------------------------
1 | import { ISetting, ICountries } from 'src/interfaces';
2 | import { APIRequest, IResponse } from './api-request';
3 |
4 | export class SettingService extends APIRequest {
5 | all(group = ''): Promise> {
6 | return this.get(this.buildUrl('/settings/public', { group }));
7 | }
8 |
9 | getCountries(): Promise> {
10 | return this.get('/countries/list');
11 | }
12 |
13 | getTimezones(): Promise> {
14 | return this.get('/timezones/list');
15 | }
16 | }
17 |
18 | export const settingService = new SettingService();
19 |
--------------------------------------------------------------------------------
/src/services/token-package.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class TokenPackageService extends APIRequest {
4 | search(params?: { [key: string]: string }) {
5 | return this.get(this.buildUrl('/package/token/search', params));
6 | }
7 |
8 | buyTokens(id: string) {
9 | return this.post(`/payment/purchase-tokens/${id}`);
10 | }
11 | }
12 |
13 | export const tokenPackageService = new TokenPackageService();
14 |
--------------------------------------------------------------------------------
/src/services/transaction.service.ts:
--------------------------------------------------------------------------------
1 | import { APIRequest } from './api-request';
2 |
3 | export class TransactionService extends APIRequest {
4 | search(params?: { [key: string]: any }) {
5 | return this.get(this.buildUrl('/transactions/user/search', params));
6 | }
7 |
8 | sendTipToken(performerId: string, token: number, conversationId?: string) {
9 | return this.post(`/member/send-tip-token/${performerId}`, { token, conversationId });
10 | }
11 |
12 | public sendPaidToken(conversationId: string) {
13 | return this.post(`/member/send-pay-token/${conversationId}`);
14 | }
15 | }
16 |
17 | export const transactionService = new TransactionService();
18 |
--------------------------------------------------------------------------------
/src/services/user.service.ts:
--------------------------------------------------------------------------------
1 | import { IUser } from 'src/interfaces';
2 | import { APIRequest, IResponse } from './api-request';
3 | import { getGlobalConfig } from './config';
4 |
5 | export class UserService extends APIRequest {
6 | me(headers?: { [key: string]: string }): Promise> {
7 | return this.get('/users/me', headers);
8 | }
9 |
10 | updateMe(payload: any) {
11 | return this.put('/users', payload);
12 | }
13 |
14 | getAvatarUploadUrl(userId?: string) {
15 | const config = getGlobalConfig();
16 | if (userId) {
17 | return `${config.NEXT_PUBLIC_API_ENDPOINT}/users/${userId}/avatar/upload`;
18 | }
19 | return `${config.NEXT_PUBLIC_API_ENDPOINT}/users/avatar/upload`;
20 | }
21 |
22 | search(query?: { [key: string]: any }) {
23 | return this.get(this.buildUrl('/users/search', query));
24 | }
25 |
26 | findById(id: string) {
27 | return this.get(`/users/view/${id}`);
28 | }
29 | }
30 |
31 | export const userService = new UserService();
32 |
--------------------------------------------------------------------------------
/src/services/utils.service.ts:
--------------------------------------------------------------------------------
1 | import { ICountry, ILangguges, IPhoneCodes } from 'src/interfaces';
2 | import { APIRequest, IResponse } from './api-request';
3 |
4 | export class UtilsService extends APIRequest {
5 | countriesList(): Promise> {
6 | return this.get('/countries/list');
7 | }
8 |
9 | languagesList(): Promise> {
10 | return this.get('/languages/list');
11 | }
12 |
13 | phoneCodesList(): Promise> {
14 | return this.get('/phone-codes/list');
15 | }
16 |
17 | statistics(): Promise> {
18 | return this.get('/statistics/admin');
19 | }
20 |
21 | verifyRecaptcha(token: string) {
22 | return this.post('/re-captcha/verify', { token });
23 | }
24 | }
25 |
26 | export const utilsService = new UtilsService();
27 |
--------------------------------------------------------------------------------
/src/socket/Event.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { SocketContext } from "./SocketContext";
3 | import { warning } from "./utils";
4 |
5 | interface IEventProps {
6 | event: string;
7 | handler: Function;
8 | }
9 |
10 | class Event extends React.Component {
11 | constructor(props) {
12 | super(props);
13 | }
14 |
15 | componentDidMount() {
16 | const { event, handler } = this.props;
17 | const socket = this.context as any;
18 |
19 | if (!socket) {
20 | warning("Socket IO connection has not been established.");
21 | return;
22 | }
23 |
24 | socket.on(event, handler);
25 | }
26 |
27 | componentWillUnmount() {
28 | const { event } = this.props;
29 | const socket = this.context as any;
30 |
31 | if (!socket) {
32 | warning("Socket IO connection has not been established.");
33 | return;
34 | }
35 |
36 | socket.off(event);
37 | }
38 |
39 | render() {
40 | return false;
41 | }
42 | }
43 |
44 | Event.contextType = SocketContext;
45 |
46 | export default Event;
47 |
--------------------------------------------------------------------------------
/src/socket/SocketContext.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const SocketContext = React.createContext('socket');
4 |
--------------------------------------------------------------------------------
/src/socket/index.ts:
--------------------------------------------------------------------------------
1 | import Socket from './Socket';
2 | import Event from './Event';
3 | import { SocketContext } from './SocketContext';
4 |
5 | if (process.browser) {
6 | if (window) window.ReactSocketIO = { Socket, Event, SocketContext };
7 | }
8 |
9 | export { Socket, Event, SocketContext };
10 |
--------------------------------------------------------------------------------
/src/socket/utils.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable prefer-spread */
2 |
3 | import { getGlobalConfig } from '@services/config';
4 |
5 | /**
6 | * Prints a warning in the console if it exists.
7 | *
8 | * @param {String} message The warning message.
9 | * @returns {void}
10 | */
11 | export const warning = (...args) => {
12 | const config = getGlobalConfig();
13 | // debug on development and staging.
14 | if (config.NODE_ENV === 'production') return;
15 |
16 | /* eslint-disable no-console */
17 | if (typeof console !== 'undefined' && typeof console.error === 'function') {
18 | console.error.apply(console, args);
19 | }
20 | /* eslint-enable no-console */
21 | try {
22 | // This error was thrown as a convenience so that if you enable
23 | // "break on all exceptions" in your console,
24 | // it would pause the execution at this line.
25 |
26 | throw new Error(args.join(' '));
27 | /* eslint-disable no-empty */
28 | } catch (e) {}
29 | /* eslint-enable no-empty */
30 | };
31 |
32 | export const debug = (...args) => {
33 | const config = getGlobalConfig();
34 | // debug on development and staging.
35 | if (config.NODE_ENV === 'production') return;
36 |
37 | /* eslint-disable no-console */
38 | if (typeof console !== 'undefined' && typeof console.debug === 'function') {
39 | console.debug.apply(console, args);
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/src/videojs/contants.ts:
--------------------------------------------------------------------------------
1 | export const eventsToRemove = [
2 | 'mousemove',
3 | 'mouseover',
4 | 'mouseup',
5 | 'mousedown',
6 | 'mouseleave',
7 | 'touchstart'
8 | ];
9 |
--------------------------------------------------------------------------------
/src/videojs/mic-controls/plugin.ts:
--------------------------------------------------------------------------------
1 | import videojs from 'video.js';
2 | import AudioMuteToggleButton from './audio-mute-toggle-button';
3 |
4 | const Plugin = videojs.getPlugin('plugin');
5 |
6 | interface MicControlsPluginOptions {
7 | muteLocalMic: any,
8 | unmuteLocalMic: any
9 | }
10 |
11 | export default class MicControlsPlugin extends Plugin {
12 | private muteTogglesButton: videojs.Button;
13 |
14 | constructor(player, options: MicControlsPluginOptions) {
15 | super(player, options);
16 | this.muteTogglesButton = new AudioMuteToggleButton(this.player, options);
17 | this.player.controlBar.addChild(this.muteTogglesButton, {
18 | componentClass: 'muteToggleButton'
19 | });
20 | }
21 |
22 | dispose() {
23 | super.dispose();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/style/default.less:
--------------------------------------------------------------------------------
1 | // check more here https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
2 | // @import '../node_modules/antd/dist/antd.less';
3 | // @import '../node_modules/antd/lib/style/themes/default.less';
4 |
5 | @desktop-query: 1200px;
6 | @tablet-query: 990px;
7 | @mobile-query: 767px;
8 | @mobile-small-query: 567px;
9 | @border-radius-base: 4px;
10 | @border-radius-image: 10px;
11 | @border-radius-sm: 2px;
12 | @shadow-color: rgba(0, 0, 0, 0.05);
13 | @shadow-1-down: 4px 4px 40px @shadow-color;
14 | @border-color-split: #f4f4f4;
15 | @border-color-base: #e5e5e5;
16 | @border-color-component: #d9d9d9;
17 | @font-size-base: 13px;
18 | @text-color: #666;
19 | @hover-color: #f9f9fc;
20 | @heading-color: rgba(0, 0, 0, 0.85);
21 | @background-container: #d0d0d7;
22 | @background-footer: #fff;
23 | @background-card: rgba(245, 0, 98, 0.1);
24 | @primary-color: #1b3fff;
25 | @text-in-primary-background: #1b3fff;
26 | @headerHeight: 73px;
27 | @headerZIndex: 999;
28 | @body-background-color: #d0d0d7;
29 | @secondary-color:#1b3fff;
30 | @regular-text: #000000;
31 | @light-text: #8c8c8c;
32 | @white-color: #fff;
33 | @content-padding: 100px;
34 | @gray-color: #ccc;
35 | @success-color: #2fb52d;
36 | @warning-color: #f97332;
37 | @danger-color: #ff0f0f;
38 | @form-padding: 16px 24px !important;
39 |
40 | // z-index list, order by `z-index`
41 | @zindex-blocked-thumb: 990;
42 |
--------------------------------------------------------------------------------
/style/mixin.less:
--------------------------------------------------------------------------------
1 | @import './default.less';
2 |
3 | @dark-half: #494949;
4 | @purple: #d897eb;
5 | @shadow-1: 4px 4px 20px 0 rgba(0, 0, 0, 0.01);
6 | @shadow-2: 4px 4px 40px 0 rgba(0, 0, 0, 0.05);
7 | @transition-ease-in: all 0.3s ease-out;
8 | @transition-ease-out: all 0.3s ease-out;
9 | @ease-in: ease-in;
10 |
11 | .text-overflow {
12 | white-space: nowrap;
13 | text-overflow: ellipsis;
14 | overflow: hidden;
15 | }
16 |
17 | .text-gradient {
18 | background-image: -webkit-gradient(
19 | linear,
20 | 37.219838% 34.532506%,
21 | 36.425669% 93.178216%,
22 | from(#29cdff),
23 | to(#0a60ff),
24 | color-stop(0.37, #148eff)
25 | );
26 | -webkit-background-clip: text;
27 | -webkit-text-fill-color: transparent;
28 | }
29 |
30 | .background-hover {
31 | transition: @transition-ease-in;
32 | &:hover {
33 | background-color: @hover-color;
34 | }
35 | }
36 |
37 | .primary-icon {
38 | color: @primary-color !important;
39 | }
40 |
41 | .editable-cell {
42 | position: relative;
43 | }
44 |
45 | .editable-cell-value-wrap {
46 | padding: 5px 12px;
47 | cursor: pointer;
48 | }
49 |
50 | .editable-row:hover .editable-cell-value-wrap {
51 | border: 1px solid #d9d9d9;
52 | border-radius: 4px;
53 | padding: 4px 11px;
54 | }
55 |
56 | [data-theme='dark'] .editable-row:hover .editable-cell-value-wrap {
57 | border: 1px solid #434343;
58 | }
--------------------------------------------------------------------------------
/style/vars.less:
--------------------------------------------------------------------------------
1 | @import './mixin.less';
2 |
--------------------------------------------------------------------------------
/style/videojs.less:
--------------------------------------------------------------------------------
1 | .video-js {
2 | .vjs-tech {
3 | object-fit: cover;
4 | margin: 0px;
5 | padding: 0px;
6 | display: inline;
7 | }
8 |
9 | .vjs-live-control {
10 | margin: 0 5px;
11 | }
12 |
13 | .vjs-audio {
14 | font-family: 'VideoJS';
15 | cursor: pointer;
16 | font-weight: normal;
17 | font-style: normal;
18 | color: #ffffff;
19 |
20 | &.vjs-audio-off {
21 | color: #ff0000;
22 | }
23 | }
24 |
25 | .vjs-volume-tooltip {
26 | display: none;
27 | }
28 |
29 | .vjs-tech{ pointer-events: none; }
30 |
31 | &.vjs-has-started {
32 | z-index: 1;
33 | }
34 | }
35 |
36 | video.broadcaster {
37 | &::-webkit-media-controls-timeline {
38 | display: none;
39 | }
40 |
41 | &::-webkit-media-controls-current-time-display {
42 | display: none;
43 | }
44 |
45 | &::-webkit-media-controls-volume-slider {
46 | display: none;
47 | }
48 |
49 | &::-webkit-media-controls-mute-button {
50 | display: none;
51 | }
52 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "es5",
6 | "es6",
7 | "dom",
8 | "dom.iterable",
9 | "esnext",
10 | "es2015",
11 | "es2017"
12 | ],
13 | "allowJs": true,
14 | "skipLibCheck": true,
15 | "strict": false,
16 | "forceConsistentCasingInFileNames": true,
17 | "noEmit": true,
18 | "esModuleInterop": true,
19 | "module": "esnext",
20 | "moduleResolution": "node",
21 | "resolveJsonModule": true,
22 | "isolatedModules": true,
23 | "jsx": "preserve",
24 | "baseUrl": "./",
25 | "paths": {
26 | "@layouts/*": ["./src/layouts/*"],
27 | "@components/*": ["./src/components/*"],
28 | "@lib/*": ["./src/lib/*"],
29 | "@redux/*": ["./src/redux/*"],
30 | "@services/*": ["./src/services/*"],
31 | "src/*": ["./src/*"]
32 | }
33 | },
34 | "exclude": [
35 | "node_modules",
36 | "./src/**/*.save.*"
37 | ],
38 | "include": [
39 | "next-env.d.ts",
40 | "**/*.ts",
41 | "**/*.tsx",
42 | "./src/**/*"
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/tsconfig.server.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "outDir": "dist",
6 | "target": "es2017",
7 | "isolatedModules": false,
8 | "noEmit": false,
9 | "incremental": true
10 | },
11 | "include": ["server/**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/utils/ActiveLink.js:
--------------------------------------------------------------------------------
1 | import { withRouter } from 'next/router';
2 | import Link from 'next/link';
3 | import React, { Children } from 'react';
4 |
5 | const ActiveLink = ({ router, children, ...props }) => {
6 | const child = Children.only(children);
7 |
8 | let className = child.props.className || '';
9 | if (router.pathname === props.href && props.activeClassName) {
10 | className = `${className} ${props.activeClassName}`.trim();
11 | }
12 |
13 | delete props.activeClassName;
14 |
15 | return {React.cloneElement(child, { className })};
16 | };
17 |
18 | export default withRouter(ActiveLink);
--------------------------------------------------------------------------------
/utils/baseUrl.js:
--------------------------------------------------------------------------------
1 | const baseUrl = process.env.NODE_ENV === "production"
2 | ? 'https://corf-react.envytheme.com'
3 | : 'http://localhost:3000';
4 |
5 | export default baseUrl;
--------------------------------------------------------------------------------