✨(frontend) add hook to sync user preferences
Implement new hook that synchronizes user language and timezone preferences from frontend to backend. Ensures consistent localization across and notifications. Note: Current implementation works but auth code requires future refactoring.
This commit is contained in:
committed by
aleb_the_flash
parent
7f0e866eac
commit
ec114808b2
@@ -3,12 +3,14 @@ import { useConfig } from '@/api/useConfig'
|
|||||||
import { useAnalytics } from '@/features/analytics/hooks/useAnalytics'
|
import { useAnalytics } from '@/features/analytics/hooks/useAnalytics'
|
||||||
import { useSupport } from '@/features/support/hooks/useSupport'
|
import { useSupport } from '@/features/support/hooks/useSupport'
|
||||||
import { useLocation } from 'wouter'
|
import { useLocation } from 'wouter'
|
||||||
|
import { useSyncUserPreferencesWithBackend } from '@/features/auth'
|
||||||
|
|
||||||
const SDK_BASE_ROUTE = '/sdk'
|
const SDK_BASE_ROUTE = '/sdk'
|
||||||
|
|
||||||
export const AppInitialization = () => {
|
export const AppInitialization = () => {
|
||||||
const { data } = useConfig()
|
const { data } = useConfig()
|
||||||
const [location] = useLocation()
|
const [location] = useLocation()
|
||||||
|
useSyncUserPreferencesWithBackend()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
analytics = {},
|
analytics = {},
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
import { BackendLanguage } from '@/utils/languages'
|
||||||
|
|
||||||
export type ApiUser = {
|
export type ApiUser = {
|
||||||
id: string
|
id: string
|
||||||
email: string
|
email: string
|
||||||
full_name: string
|
full_name: string
|
||||||
last_name: string
|
last_name: string
|
||||||
|
language: BackendLanguage
|
||||||
|
timezone: string
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/frontend/src/features/auth/api/updateUserPreferences.ts
Normal file
15
src/frontend/src/features/auth/api/updateUserPreferences.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { type ApiUser } from './ApiUser'
|
||||||
|
import { fetchApi } from '@/api/fetchApi'
|
||||||
|
|
||||||
|
export type ApiUserPreferences = Pick<ApiUser, 'id' | 'timezone' | 'language'>
|
||||||
|
|
||||||
|
export const updateUserPreferences = async ({
|
||||||
|
user,
|
||||||
|
}: {
|
||||||
|
user: ApiUserPreferences
|
||||||
|
}): Promise<ApiUser> => {
|
||||||
|
return await fetchApi(`/users/${user.id}/`, {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify({ timezone: user.timezone, language: user.language }),
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { useMutation } from '@tanstack/react-query'
|
||||||
|
import { keys } from '@/api/queryKeys'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { queryClient } from '@/api/queryClient'
|
||||||
|
import { updateUserPreferences } from './updateUserPreferences'
|
||||||
|
import { convertToBackendLanguage } from '@/utils/languages'
|
||||||
|
import { useUser } from './useUser'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook that synchronizes user browser preferences (language, timezone) with backend user settings.
|
||||||
|
* Automatically updates backend when browser settings change for logged-in users.
|
||||||
|
*/
|
||||||
|
export const useSyncUserPreferencesWithBackend = () => {
|
||||||
|
const { i18n } = useTranslation()
|
||||||
|
const { user, isLoggedIn } = useUser()
|
||||||
|
|
||||||
|
const { mutateAsync } = useMutation({
|
||||||
|
mutationFn: updateUserPreferences,
|
||||||
|
onSuccess: (updatedUser) => {
|
||||||
|
queryClient.setQueryData([keys.user], updatedUser)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!user || !isLoggedIn) return
|
||||||
|
|
||||||
|
const syncBrowserPreferencesToBackend = async () => {
|
||||||
|
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
const currentLanguage = convertToBackendLanguage(i18n.language)
|
||||||
|
if (
|
||||||
|
currentLanguage !== user.language ||
|
||||||
|
currentTimezone !== user.timezone
|
||||||
|
) {
|
||||||
|
await mutateAsync({
|
||||||
|
user: {
|
||||||
|
id: user.id,
|
||||||
|
timezone: currentTimezone,
|
||||||
|
language: currentLanguage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncBrowserPreferencesToBackend()
|
||||||
|
}, [i18n.language, isLoggedIn, user, mutateAsync])
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export { useUser } from './api/useUser'
|
export { useUser } from './api/useUser'
|
||||||
|
export { useSyncUserPreferencesWithBackend } from './api/useSyncUserPreferencesWithBackend'
|
||||||
export { authUrl } from './utils/authUrl'
|
export { authUrl } from './utils/authUrl'
|
||||||
export { UserAware } from './components/UserAware'
|
export { UserAware } from './components/UserAware'
|
||||||
|
|||||||
16
src/frontend/src/utils/languages.ts
Normal file
16
src/frontend/src/utils/languages.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Map frontend language codes to backend language codes
|
||||||
|
|
||||||
|
export type BackendLanguage = 'en-us' | 'fr-fr' | 'nl-nl'
|
||||||
|
export type FrontendLanguage = 'en' | 'fr' | 'nl'
|
||||||
|
|
||||||
|
const frontendToBackendMap: Record<FrontendLanguage, BackendLanguage> = {
|
||||||
|
en: 'en-us',
|
||||||
|
fr: 'fr-fr',
|
||||||
|
nl: 'nl-nl',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const convertToBackendLanguage = (
|
||||||
|
frontendLang: string = 'fr'
|
||||||
|
): BackendLanguage => {
|
||||||
|
return frontendToBackendMap[frontendLang as FrontendLanguage]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user