0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-03 21:48:55 -05:00
logto/packages/console/src/hooks/use-user-preferences.ts

91 lines
2.5 KiB
TypeScript
Raw Normal View History

import { languageKeys } from '@logto/core-kit';
import { useLogto } from '@logto/react';
import { AppearanceMode } from '@logto/schemas';
import { Nullable, Optional } from '@silverhand/essentials';
2022-09-24 15:55:13 +08:00
import { t } from 'i18next';
import { useCallback, useEffect, useMemo } from 'react';
2022-09-24 15:55:13 +08:00
import { toast } from 'react-hot-toast';
import useSWR from 'swr';
import { z } from 'zod';
import { themeStorageKey } from '@/consts';
import useApi, { RequestError } from './use-api';
2022-09-24 15:55:13 +08:00
import useLogtoUserId from './use-logto-user-id';
const userPreferencesGuard = z.object({
language: z.enum(languageKeys).optional(),
appearanceMode: z.nativeEnum(AppearanceMode),
experienceNoticeConfirmed: z.boolean().optional(),
getStartedHidden: z.boolean().optional(),
});
export type UserPreferences = z.infer<typeof userPreferencesGuard>;
const key = 'adminConsolePreferences';
const getEnumFromArray = <T extends string>(
array: T[],
value: Nullable<Optional<string>>
): Optional<T> => array.find((element) => element === value);
const useUserPreferences = () => {
const { isAuthenticated, error: authError } = useLogto();
2022-09-24 15:55:13 +08:00
const userId = useLogtoUserId();
const shouldFetch = isAuthenticated && !authError && userId;
const { data, mutate, error } = useSWR<unknown, RequestError>(
2022-09-24 15:55:13 +08:00
shouldFetch && `/api/users/${userId}/custom-data`
);
const api = useApi();
const parseData = useCallback((): UserPreferences => {
try {
return z.object({ [key]: userPreferencesGuard }).parse(data).adminConsolePreferences;
} catch {
return {
appearanceMode:
getEnumFromArray(Object.values(AppearanceMode), localStorage.getItem(themeStorageKey)) ??
AppearanceMode.SyncWithSystem,
};
}
}, [data]);
const userPreferences = useMemo(() => parseData(), [parseData]);
const update = async (data: Partial<UserPreferences>) => {
2022-09-24 15:55:13 +08:00
if (!userId) {
toast.error(t('errors.unexpected_error'));
return;
}
const updated = await api
2022-09-24 15:55:13 +08:00
.patch(`/api/users/${userId}/custom-data`, {
json: {
customData: {
[key]: {
...userPreferences,
...data,
},
},
},
})
.json();
void mutate(updated);
};
useEffect(() => {
localStorage.setItem(themeStorageKey, userPreferences.appearanceMode);
}, [userPreferences.appearanceMode]);
return {
isLoading: !data && !error,
2022-08-05 17:59:03 +08:00
isLoaded: Boolean(data && !error),
data: userPreferences,
update,
error,
};
};
export default useUserPreferences;