0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

refactor(console): merge useMeCustomData hook into useCurrentUser (#5196)

This commit is contained in:
Xiao Yijun 2024-01-04 11:16:11 +08:00 committed by GitHub
parent 0d1a0a9746
commit 7a68967267
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 70 deletions

View file

@ -22,7 +22,6 @@ import CloudAppRoutes from '@/cloud/AppRoutes';
import AppLoading from '@/components/AppLoading';
import { isCloud } from '@/consts/env';
import { cloudApi, getManagementApi, meApi } from '@/consts/resources';
import useMeCustomData from '@/hooks/use-me-custom-data';
import useTrackUserId from '@/hooks/use-track-user-id';
import { OnboardingRoutes } from '@/onboarding';
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
@ -35,6 +34,7 @@ import AppConfirmModalProvider from './contexts/AppConfirmModalProvider';
import AppDataProvider, { AppDataContext } from './contexts/AppDataProvider';
import { AppThemeProvider } from './contexts/AppThemeProvider';
import TenantsProvider, { TenantsContext } from './contexts/TenantsProvider';
import useCurrentUser from './hooks/use-current-user';
import initI18n from './i18n/init';
void initI18n();
@ -141,7 +141,7 @@ function Providers() {
/** Renders different routes based on the user's onboarding status. */
function AppRoutes() {
const { tenantEndpoint } = useContext(AppDataContext);
const { isLoaded } = useMeCustomData();
const { isLoaded } = useCurrentUser();
const { isOnboarding } = useUserOnboardingData();
const { isAuthenticated } = useLogto();

View file

@ -1,5 +1,5 @@
import AppLoading from '@/components/AppLoading';
import useMeCustomData from '@/hooks/use-me-custom-data';
import useCurrentUser from '@/hooks/use-current-user';
import useUserDefaultTenantId from '@/hooks/use-user-default-tenant-id';
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
@ -8,7 +8,7 @@ import Redirect from './Redirect';
import TenantLandingPage from './TenantLandingPage';
export default function Main() {
const { isLoaded } = useMeCustomData();
const { isLoaded } = useCurrentUser();
const { isOnboarding } = useUserOnboardingData();
const { defaultTenantId } = useUserDefaultTenantId();

View file

@ -9,7 +9,7 @@ import DynamicT from '@/ds-components/DynamicT';
import FormField from '@/ds-components/FormField';
import ModalLayout from '@/ds-components/ModalLayout';
import TextInput from '@/ds-components/TextInput';
import useMeCustomData from '@/hooks/use-me-custom-data';
import useCurrentUser from '@/hooks/use-current-user';
import * as modalStyles from '@/scss/modal.module.scss';
type Props = {
@ -32,13 +32,13 @@ export default function RequestForm({
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const [inputValue, setInputValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
const { data, update } = useMeCustomData();
const guideRequests = data?.guideRequests;
const { customData, updateCustomData } = useCurrentUser();
const guideRequests = customData?.guideRequests;
const submit = async () => {
setIsLoading(true);
try {
await update({
await updateCustomData({
guideRequests: Array.isArray(guideRequests)
? guideRequests.concat(inputValue)
: [inputValue],

View file

@ -1,5 +1,8 @@
import { useLogto } from '@logto/react';
import type { UserProfileResponse } from '@logto/schemas';
import type { JsonObject, UserProfileResponse } from '@logto/schemas';
import { useCallback } from 'react';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
import useSWR from 'swr';
import { adminTenantEndpoint, meApi } from '@/consts';
@ -10,17 +13,45 @@ import useSwrFetcher from './use-swr-fetcher';
const useCurrentUser = () => {
const { isAuthenticated } = useLogto();
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const api = useStaticApi({ prefixUrl: adminTenantEndpoint, resourceIndicator: meApi.indicator });
const fetcher = useSwrFetcher<UserProfileResponse>(api);
const {
data: user,
error,
isLoading,
mutate,
} = useSWR<UserProfileResponse, RequestError>(isAuthenticated && 'me', fetcher);
const isLoading = !user && !error;
const updateCustomData = useCallback(
async (customData: JsonObject) => {
if (!user) {
toast.error(t('errors.unexpected_error'));
return;
}
return { user, isLoading, error, reload: mutate, api };
await mutate({
...user,
customData: await api
.patch(`me/custom-data`, {
json: customData,
})
.json<JsonObject>(),
});
},
[api, mutate, t, user]
);
return {
user,
isLoading,
error,
isLoaded: !isLoading && !error,
reload: mutate,
customData: user?.customData,
/** Patch (shallow merge) the custom data of the current user. */
updateCustomData,
};
};
export default useCurrentUser;

View file

@ -1,41 +0,0 @@
import { type JsonObject } from '@logto/schemas';
import { useCallback } from 'react';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
import useCurrentUser from './use-current-user';
const useMeCustomData = () => {
const { user, isLoading, error, reload, api } = useCurrentUser();
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const update = useCallback(
async (customData: JsonObject) => {
if (!user) {
toast.error(t('errors.unexpected_error'));
return;
}
await reload({
...user,
customData: await api
.patch(`me/custom-data`, {
json: customData,
})
.json<JsonObject>(),
});
},
[api, reload, t, user]
);
return {
data: user?.customData,
error,
isLoading,
isLoaded: !isLoading && !error,
/** Patch (shallow merge) the custom data of the current user. */
update,
};
};
export default useMeCustomData;

View file

@ -6,7 +6,7 @@ import { z } from 'zod';
import { isCloud } from '@/consts/env';
import { TenantsContext } from '@/contexts/TenantsProvider';
import useMeCustomData from './use-me-custom-data';
import useCurrentUser from './use-current-user';
const key = 'defaultTenantId';
@ -17,12 +17,12 @@ const key = 'defaultTenantId';
* - If the default tenant ID is not available to the user anymore, it semantically equals to the first tenant ID.
*/
const useUserDefaultTenantId = () => {
const { data, update: updateMeCustomData } = useMeCustomData();
const { tenants, currentTenantId } = useContext(TenantsContext);
const { customData, updateCustomData } = useCurrentUser();
const { tenants } = useContext(TenantsContext);
/** The current stored default tenant ID in the user's `customData`. */
const storedId = useMemo(
() => trySafe(() => z.object({ [key]: z.string() }).parse(data)[key]),
[data]
() => trySafe(() => z.object({ [key]: z.string() }).parse(customData)[key]),
[customData]
);
const defaultTenantId = useMemo(() => {
@ -47,11 +47,11 @@ const useUserDefaultTenantId = () => {
return;
}
await updateMeCustomData({
await updateCustomData({
[key]: tenantId,
});
},
[updateMeCustomData]
[updateCustomData]
);
return useMemo(

View file

@ -7,7 +7,7 @@ import { AppThemeContext, buildDefaultAppearanceMode } from '@/contexts/AppTheme
import type { DynamicAppearanceMode } from '@/types/appearance-mode';
import { appearanceModeGuard } from '@/types/appearance-mode';
import useMeCustomData from './use-me-custom-data';
import useCurrentUser from './use-current-user';
const adminConsolePreferencesKey = 'adminConsolePreferences';
@ -33,11 +33,13 @@ const defaultUserPreferences: DefaultUserPreference = {
};
const useUserPreferences = () => {
const { data, error, isLoading, isLoaded, update: updateMeCustomData } = useMeCustomData();
const { customData, error, isLoading, isLoaded, updateCustomData } = useCurrentUser();
const { setAppearanceMode } = useContext(AppThemeContext);
const userPreferences = useMemo(() => {
const parsed = z.object({ [adminConsolePreferencesKey]: userPreferencesGuard }).safeParse(data);
const parsed = z
.object({ [adminConsolePreferencesKey]: userPreferencesGuard })
.safeParse(customData);
return parsed.success
? {
@ -45,10 +47,10 @@ const useUserPreferences = () => {
...parsed.data[adminConsolePreferencesKey],
}
: defaultUserPreferences;
}, [data]);
}, [customData]);
const update = async (data: Partial<UserPreferences>) => {
await updateMeCustomData({
await updateCustomData({
[adminConsolePreferencesKey]: {
...userPreferences,
...data,

View file

@ -4,7 +4,7 @@ import { z } from 'zod';
import { isCloud } from '@/consts/env';
import { TenantsContext } from '@/contexts/TenantsProvider';
import useMeCustomData from '@/hooks/use-me-custom-data';
import useCurrentUser from '@/hooks/use-current-user';
import type { UserOnboardingData } from '../types';
import { Project, userOnboardingDataGuard } from '../types';
@ -12,14 +12,16 @@ import { Project, userOnboardingDataGuard } from '../types';
const userOnboardingDataKey = 'onboarding';
const useUserOnboardingData = () => {
const { data, error, isLoading, isLoaded, update: updateMeCustomData } = useMeCustomData();
const { customData, error, isLoading, isLoaded, updateCustomData } = useCurrentUser();
const { currentTenantId } = useContext(TenantsContext);
const userOnboardingData = useMemo(() => {
const parsed = z.object({ [userOnboardingDataKey]: userOnboardingDataGuard }).safeParse(data);
const parsed = z
.object({ [userOnboardingDataKey]: userOnboardingDataGuard })
.safeParse(customData);
return parsed.success ? parsed.data[userOnboardingDataKey] : {};
}, [data]);
}, [customData]);
const isOnboarding = useMemo(() => {
if (!isCloud) {
@ -47,14 +49,14 @@ const useUserOnboardingData = () => {
const update = useCallback(
async (data: Partial<UserOnboardingData>) => {
await updateMeCustomData({
await updateCustomData({
[userOnboardingDataKey]: {
...userOnboardingData,
...data,
},
});
},
[updateMeCustomData, userOnboardingData]
[updateCustomData, userOnboardingData]
);
return {