437 lines
13 KiB
TypeScript
437 lines
13 KiB
TypeScript
import 'antd/dist/antd.less'
|
|
import { AutoSaveProvider } from 'components/AutoSaveProvider'
|
|
import ModulesProvider from 'components/ModulesProvider'
|
|
import NotSupportSizeBrowser from 'components/NotSupportSizeBrowser'
|
|
import Loading from 'components/Loading'
|
|
import { ExchangeRateDefault } from 'constants/exchange-rate'
|
|
import 'fonts/SFProDisplay/stylesheet.scss'
|
|
import { useNotificationRequest, useWindowSize } from 'hooks'
|
|
import { useQuery } from 'hooks/useQuery'
|
|
import Cookies from 'js-cookie'
|
|
import LogRocket from 'logrocket'
|
|
import { getCorrelationId } from '@komi-app/correlation'
|
|
import moment from 'moment'
|
|
import { updateTalentProfileActions } from 'pages/BecomeATalent/Reducer/action'
|
|
import React, { useEffect, useState } from 'react'
|
|
import { isMobile } from 'react-device-detect'
|
|
import { useDispatch } from 'react-redux'
|
|
import { Link, useHistory, useLocation } from 'react-router-dom'
|
|
import { useTypedSelector } from 'redux/rootReducer'
|
|
import {
|
|
detectLocalCurrencyActions,
|
|
getExchangeRateActions,
|
|
getExchangeRateUSDActions,
|
|
getUserProfileActions
|
|
} from 'redux/User/actions'
|
|
import {
|
|
selectIsAdminLogin,
|
|
selectIsCheckLocalCurrency,
|
|
selectUserData,
|
|
selectUserState
|
|
} from 'redux/User/selector'
|
|
import Routes from 'routes'
|
|
|
|
import { KOMI_TALENT_CURRENCY } from 'services/UserService'
|
|
import { IframeMessage } from 'utils/iframeMessage'
|
|
import 'video.js/dist/video-js.css'
|
|
import './App.scss'
|
|
import '@komi-app/creator-ui/dist/style.css'
|
|
import './i18n'
|
|
import { webviewMessage } from './utils/webviewMessage'
|
|
import '@komi-app/components/dist/index.css'
|
|
import { UserAgentProvider } from 'context/user-agent'
|
|
import config from 'config'
|
|
import { initProfileId, linkRedirectService } from 'services'
|
|
import { useLinkRedirect } from 'context/LinkRedirectContext'
|
|
import { TALENT_PROFILE_ID } from 'constants/profile'
|
|
|
|
import {
|
|
KOMI_SPOTIFY_ACCESS_TOKEN,
|
|
KOMI_SPOTIFY_REFRESH_TOKEN
|
|
} from './services/SpotifyService'
|
|
import useMobileView from 'hooks/useMobileView'
|
|
import { setupLink, ToastContextProvider } from '@komi-app/creator-ui'
|
|
|
|
import {
|
|
FLAGS,
|
|
IfFeature,
|
|
isReady,
|
|
useFeatureIsOn,
|
|
useFlags
|
|
} from '@komi-app/flags-sdk'
|
|
import When from '@komi-app/when'
|
|
import {
|
|
CreatorTrackingProvider,
|
|
CreatorTrackingProps
|
|
} from '@komi-app/analytics-sdk'
|
|
import { useIntercomMessengerWidget } from './hooks/useIntercomMessengerWidget'
|
|
import ErrorBoundary from 'components/ErrorBoundary/ErrorBoundary'
|
|
|
|
setupLink(Link)
|
|
|
|
LogRocket.init(config.logRocket.id, {
|
|
rootHostname: 'komi.io',
|
|
dom: {
|
|
privateAttributeBlocklist: ['data-no-track']
|
|
}
|
|
})
|
|
const KOMI_FIRST_SETUP_ONBOARDING = 'KOMI_FIRST_SETUP_ONBOARDING'
|
|
|
|
function isMobileEnabledPath(path: string | undefined) {
|
|
if (!path) {
|
|
return false
|
|
}
|
|
return (
|
|
path === '/admin/send-login-link' || path.startsWith('/admin/onboarding')
|
|
)
|
|
}
|
|
|
|
const App = () => {
|
|
const detectCurrency = useTypedSelector(selectIsCheckLocalCurrency)
|
|
const isAdminLogin = useTypedSelector(selectIsAdminLogin)
|
|
const user = useTypedSelector(selectUserData)
|
|
const userState = useTypedSelector(selectUserState)
|
|
const location = useLocation()
|
|
const query = useQuery()
|
|
//TODO: replace the below accessTokens
|
|
const accessToken = query?.get('access_token') // redirect from admin
|
|
const token = query?.get('token') // redirect from consumer
|
|
const talentProfileId = query?.get('talentProfileId') // redirect from consumer
|
|
const router = useHistory()
|
|
const [isNotSetup, setIsNotSetup] = useState(false)
|
|
const [firstRoute, setFirstRoute] = useState<any>()
|
|
const { width } = useWindowSize()
|
|
const { setLinkRedirect } = useLinkRedirect()
|
|
|
|
useFlags(
|
|
gb => {
|
|
if (user)
|
|
gb.setAttributes({
|
|
...gb.getAttributes(),
|
|
tier: user.tier
|
|
})
|
|
},
|
|
[user]
|
|
)
|
|
|
|
const isLinkRedirectOn = useFeatureIsOn(FLAGS.LINK_REDIRECT)
|
|
const isSpotifyFixOn = useFeatureIsOn(FLAGS.FIX_GS46_SPOTIFY_AUTH_FIX)
|
|
const mobileView = useMobileView()
|
|
const [shouldDisableScreenSizeError, setShouldDisableScreenSizeError] =
|
|
useState(false)
|
|
const isNotSupport = mobileView ? false : width && width < 1040
|
|
|
|
const useAnalyticsSDK = useFeatureIsOn(FLAGS.USE_ANALYTICS_SDK_TALENT)
|
|
const isAnonIdFixOn = useFeatureIsOn(FLAGS.FIX_SB_1274_ANON_ID_RESET_TALENT)
|
|
const shouldRemoveOldAnonIdCookie = useFeatureIsOn(
|
|
FLAGS.FIX_SB_1274_ANON_ID_REMOVE_OLD_COOKIE
|
|
)
|
|
|
|
const [tracking, setTracking] = useState<CreatorTrackingProps>()
|
|
const ready = isReady()
|
|
|
|
useIntercomMessengerWidget()
|
|
|
|
useEffect(() => {
|
|
setShouldDisableScreenSizeError(
|
|
isMobileEnabledPath(router?.location?.pathname)
|
|
)
|
|
}, [router.location.pathname])
|
|
|
|
useEffect(() => {
|
|
setFirstRoute(router?.location?.pathname)
|
|
if (
|
|
firstRoute !== '/collaborator-login' || !isNotSupport
|
|
? !user
|
|
: !talentProfileId
|
|
) {
|
|
return
|
|
}
|
|
const checkSetupStatus = () => {
|
|
if (!isNotSupport && user) {
|
|
const { talentProfile } = user
|
|
|
|
const isOnboarding =
|
|
talentProfile?.onboardSteps &&
|
|
Object.keys(talentProfile?.onboardSteps).every(
|
|
(key: string) => !(talentProfile?.onboardSteps as any)[key]
|
|
)
|
|
if (isOnboarding && talentProfile) {
|
|
const result = localStorage.getItem(KOMI_FIRST_SETUP_ONBOARDING)
|
|
const data = result ? JSON.parse(result) : {}
|
|
if (!data.items?.includes(talentProfile?.id)) {
|
|
localStorage.setItem(
|
|
KOMI_FIRST_SETUP_ONBOARDING,
|
|
JSON.stringify({
|
|
items: [...(data.items || []), talentProfile?.id]
|
|
})
|
|
)
|
|
setIsNotSetup(true)
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
if (talentProfileId) {
|
|
const result = localStorage.getItem(KOMI_FIRST_SETUP_ONBOARDING)
|
|
const data = result ? JSON.parse(result) : {}
|
|
if (!data.items?.includes(talentProfileId)) {
|
|
localStorage.setItem(
|
|
KOMI_FIRST_SETUP_ONBOARDING,
|
|
JSON.stringify({
|
|
items: [...(data.items || []), talentProfileId]
|
|
})
|
|
)
|
|
setIsNotSetup(true)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
checkSetupStatus()
|
|
}, [user, firstRoute, isNotSupport])
|
|
|
|
useNotificationRequest()
|
|
const dispatch = useDispatch()
|
|
moment.updateLocale('en-gb', {
|
|
weekdaysMin: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (!ready || isSpotifyFixOn) {
|
|
return
|
|
}
|
|
|
|
if (Cookies.get(KOMI_SPOTIFY_ACCESS_TOKEN)) {
|
|
Cookies.remove(KOMI_SPOTIFY_ACCESS_TOKEN)
|
|
}
|
|
if (Cookies.get(KOMI_SPOTIFY_REFRESH_TOKEN)) {
|
|
Cookies.remove(KOMI_SPOTIFY_REFRESH_TOKEN)
|
|
}
|
|
}, [isSpotifyFixOn, ready])
|
|
|
|
useEffect(() => {
|
|
// prevents using talent.*
|
|
// or local.komi.ci
|
|
const { location } = window
|
|
if (
|
|
location.hostname.startsWith('talent.') ||
|
|
(location.origin === config.service.url && location.pathname === '/')
|
|
) {
|
|
window.location.href = config.client.url
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (user) {
|
|
const profileId = user.talentProfile?.id
|
|
|
|
if (profileId) {
|
|
initProfileId(profileId)
|
|
Cookies.set(TALENT_PROFILE_ID, profileId as string)
|
|
}
|
|
|
|
if (!isAnonIdFixOn) {
|
|
;(window as any)?.analytics?.reset()
|
|
}
|
|
|
|
if (shouldRemoveOldAnonIdCookie) {
|
|
Cookies.remove('ajs_anonymous_id')
|
|
localStorage.removeItem('ajs_anonymous_id')
|
|
}
|
|
|
|
;(window as any)?.analytics?.identify(user.id, {
|
|
Id: user.id,
|
|
Name: `${user.talentProfile?.firstName} ${user.talentProfile?.lastName}`,
|
|
Email: user.email,
|
|
Platform: webviewMessage.isWebView()
|
|
? 'Webview'
|
|
: isMobile
|
|
? 'Responsive'
|
|
: 'Web'
|
|
})
|
|
}
|
|
}, [user])
|
|
|
|
useEffect(() => {
|
|
const correlationId =
|
|
sessionStorage.getItem('correlationId') || getCorrelationId()
|
|
sessionStorage.setItem('correlationId', correlationId!)
|
|
|
|
LogRocket.identify(
|
|
correlationId!,
|
|
user
|
|
? {
|
|
name: `${user.talentProfile?.firstName} ${user.talentProfile?.lastName}`,
|
|
email: user?.email || ''
|
|
}
|
|
: undefined
|
|
)
|
|
}, [user])
|
|
|
|
useEffect(() => {
|
|
if (ready) dispatch(getUserProfileActions.REQUEST())
|
|
}, [router, dispatch, accessToken, token, ready])
|
|
|
|
useEffect(() => {
|
|
if (ready && user && useAnalyticsSDK && !tracking) {
|
|
const userId = user.id!
|
|
const profileId = user.talentProfile?.id!
|
|
const profileName =
|
|
`${user.talentProfile?.firstName} ${user.talentProfile?.lastName}`.trim()
|
|
const userFullname = `${user.firstName} ${user.lastName}`.trim()
|
|
|
|
const handle = user.talentProfile?.user?.username!
|
|
const talentId = user.talentProfile?.user?.id!
|
|
|
|
setTracking({
|
|
handle,
|
|
profileId,
|
|
profileName,
|
|
userFullname,
|
|
userId,
|
|
talentId
|
|
})
|
|
}
|
|
}, [user, tracking, ready])
|
|
|
|
// obsolete?
|
|
useEffect(() => {
|
|
if (detectCurrency) return
|
|
|
|
if (user && user.localCurrency) {
|
|
Cookies.set(KOMI_TALENT_CURRENCY, user.localCurrency, {
|
|
expires: 999999
|
|
})
|
|
dispatch(getExchangeRateActions.REQUEST(user.localCurrency))
|
|
dispatch(getExchangeRateUSDActions.REQUEST())
|
|
dispatch(detectLocalCurrencyActions.SUCCESS(true))
|
|
} else if (user && !user.localCurrency && !isAdminLogin) {
|
|
// we will not detect local with expert
|
|
if (IframeMessage.inIframe()) return
|
|
;(async () => {
|
|
const currency = ExchangeRateDefault.localCurrency
|
|
Cookies.set(KOMI_TALENT_CURRENCY, currency, { expires: 999999 })
|
|
dispatch(
|
|
updateTalentProfileActions.REQUEST({
|
|
localCurrency: currency,
|
|
userState: userState
|
|
})
|
|
)
|
|
dispatch(getExchangeRateActions.REQUEST(currency))
|
|
dispatch(getExchangeRateUSDActions.REQUEST())
|
|
})()
|
|
}
|
|
|
|
return () => {}
|
|
}, [dispatch, user, detectCurrency])
|
|
|
|
// for Admin (obsolete?)
|
|
useEffect(() => {
|
|
const query = new URLSearchParams(location.search)
|
|
const localCurrency: any = query?.get('localCurrency')
|
|
if (!user || !localCurrency || !IframeMessage.inIframe()) return
|
|
Cookies.set(KOMI_TALENT_CURRENCY, localCurrency, { expires: 999999 })
|
|
dispatch(getExchangeRateActions.REQUEST(localCurrency))
|
|
dispatch(getExchangeRateUSDActions.REQUEST())
|
|
}, [user])
|
|
|
|
useEffect(() => {
|
|
if (!isLinkRedirectOn) return
|
|
const loadExistingRedirect = async () => {
|
|
if (user && user.talentProfile) {
|
|
const result = await linkRedirectService().getLinkRedirect()
|
|
|
|
let isExistingRedirectExpired = true
|
|
|
|
if (
|
|
result?.linkRedirect?.scheduled_end_timestamp != undefined &&
|
|
result?.linkRedirect?.scheduled_timezone != undefined
|
|
) {
|
|
const linkRedirectDateTimeNow = moment().tz(
|
|
result?.linkRedirect?.scheduled_timezone
|
|
)
|
|
if (
|
|
linkRedirectDateTimeNow.isBefore(
|
|
result?.linkRedirect?.scheduled_end_timestamp
|
|
)
|
|
) {
|
|
isExistingRedirectExpired = false
|
|
}
|
|
}
|
|
|
|
setLinkRedirect({
|
|
link: isExistingRedirectExpired ? '' : result?.linkRedirect?.link,
|
|
scheduledTimezone: isExistingRedirectExpired
|
|
? ''
|
|
: result?.linkRedirect?.scheduled_timezone,
|
|
scheduledStartTimestamp: isExistingRedirectExpired
|
|
? moment().valueOf()
|
|
: moment(result?.linkRedirect?.scheduled_start_timestamp).valueOf(),
|
|
scheduledEndTimestamp: isExistingRedirectExpired
|
|
? moment().add(1, 'days').valueOf()
|
|
: moment(result?.linkRedirect?.scheduled_end_timestamp).valueOf(),
|
|
isEnabled: isExistingRedirectExpired
|
|
? false
|
|
: result?.linkRedirect?.is_enabled
|
|
})
|
|
}
|
|
}
|
|
|
|
loadExistingRedirect()
|
|
}, [setLinkRedirect, user?.talentProfile, isLinkRedirectOn])
|
|
|
|
return (
|
|
<ErrorBoundary>
|
|
<CreatorTrackingProvider context={tracking}>
|
|
<IfFeature
|
|
feature={FLAGS.FEAT_SB_331_COPY_URL_PROMPT}
|
|
enabled={
|
|
<When
|
|
value={ready}
|
|
then={
|
|
isNotSupport && !shouldDisableScreenSizeError ? (
|
|
<NotSupportSizeBrowser isNotSetup={isNotSetup} />
|
|
) : (
|
|
<UserAgentProvider>
|
|
<ToastContextProvider>
|
|
<AutoSaveProvider>
|
|
<ModulesProvider>
|
|
<Routes />
|
|
</ModulesProvider>
|
|
</AutoSaveProvider>
|
|
</ToastContextProvider>
|
|
</UserAgentProvider>
|
|
)
|
|
}
|
|
otherwise={<Loading />}
|
|
/>
|
|
}
|
|
disabled={
|
|
<When
|
|
value={ready}
|
|
then={
|
|
isNotSupport && !shouldDisableScreenSizeError ? (
|
|
<NotSupportSizeBrowser isNotSetup={isNotSetup} />
|
|
) : (
|
|
<UserAgentProvider>
|
|
<AutoSaveProvider>
|
|
<ModulesProvider>
|
|
<ToastContextProvider>
|
|
<Routes />
|
|
</ToastContextProvider>
|
|
</ModulesProvider>
|
|
</AutoSaveProvider>
|
|
</UserAgentProvider>
|
|
)
|
|
}
|
|
otherwise={<Loading />}
|
|
/>
|
|
}
|
|
/>
|
|
</CreatorTrackingProvider>
|
|
</ErrorBoundary>
|
|
)
|
|
}
|
|
|
|
export default App
|