diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 47f6f351..8132153a 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -14,6 +14,7 @@ import './i18n/init' import { silenceLiveKitLogs } from '@/utils/livekit.ts' import { queryClient } from '@/api/queryClient' import { useAnalytics } from '@/features/analytics/hooks/useAnalytics' +import { useSupport } from '@/features/support/hooks/useSupport' function App() { const { i18n } = useTranslation() @@ -23,6 +24,7 @@ function App() { silenceLiveKitLogs(isProduction) useAnalytics() + useSupport() return ( diff --git a/src/frontend/src/features/auth/api/useUser.tsx b/src/frontend/src/features/auth/api/useUser.tsx index 5c7b06df..f58d58cc 100644 --- a/src/frontend/src/features/auth/api/useUser.tsx +++ b/src/frontend/src/features/auth/api/useUser.tsx @@ -4,6 +4,7 @@ import { fetchUser } from './fetchUser' import { type ApiUser } from './ApiUser' import { useEffect } from 'react' import { startAnalyticsSession } from '@/features/analytics/hooks/useAnalytics' +import { initializeSupportSession } from '@/features/support/hooks/useSupport' /** * returns info about currently logged-in user @@ -20,6 +21,7 @@ export const useUser = () => { useEffect(() => { if (query?.data) { startAnalyticsSession(query.data) + initializeSupportSession(query.data) } }, [query.data]) diff --git a/src/frontend/src/features/support/hooks/useSupport.tsx b/src/frontend/src/features/support/hooks/useSupport.tsx new file mode 100644 index 00000000..2676c29c --- /dev/null +++ b/src/frontend/src/features/support/hooks/useSupport.tsx @@ -0,0 +1,33 @@ +import { useEffect } from 'react' +import { Crisp } from 'crisp-sdk-web' +import { ApiUser } from '@/features/auth/api/ApiUser' + +const SUPPORT_ID = '58ea6697-8eba-4492-bc59-ad6562585041' + +export const initializeSupportSession = (user: ApiUser) => { + if (!Crisp.isCrispInjected()) return + const { id, email } = user + Crisp.setTokenId(`meet-${id}`) + Crisp.user.setEmail(email) +} + +export const terminateSupportSession = () => { + if (!Crisp.isCrispInjected()) return + Crisp.setTokenId() + Crisp.session.reset() +} + +// Configure Crisp chat for real-time support across all pages. +export const useSupport = () => { + useEffect(() => { + if (!SUPPORT_ID) { + console.warn('Crisp Website ID is not set') + return + } + if (Crisp.isCrispInjected()) return + Crisp.configure(SUPPORT_ID) + Crisp.setHideOnMobile(true) + }, []) + + return null +} diff --git a/src/frontend/src/layout/Header.tsx b/src/frontend/src/layout/Header.tsx index 09f8918a..a037c9e5 100644 --- a/src/frontend/src/layout/Header.tsx +++ b/src/frontend/src/layout/Header.tsx @@ -11,6 +11,7 @@ import { Menu } from '@/primitives/Menu' import { MenuList } from '@/primitives/MenuList' import { ProConnectButton } from '@/components/ProConnectButton' import { terminateAnalyticsSession } from '@/features/analytics/hooks/useAnalytics' +import { terminateSupportSession } from '@/features/support/hooks/useSupport' export const Header = () => { const { t } = useTranslation() @@ -82,6 +83,7 @@ export const Header = () => { onAction={(value) => { if (value === 'logout') { terminateAnalyticsSession() + terminateSupportSession() window.location.href = logoutUrl() } }}