mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
fix: change the me endpoint to useQuery api
This commit is contained in:
@@ -43,8 +43,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { notify, PageHeader } from '@ema-platform/ui';
|
||||
import { useApiMutation } from '@ema-platform/api';
|
||||
import { setUser } from '@ema-platform/auth';
|
||||
import { useApiMutation, useGetMeQuery, baseApi } from '@ema-platform/api';
|
||||
import type { AuthUser } from '@ema-platform/auth';
|
||||
import { SUPPORTED_LANGUAGES, type AppLanguage } from '../../../i18n/config';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
|
||||
@@ -74,12 +73,13 @@ function passwordScore(pw: string) {
|
||||
export function ProfilePage() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const user = useAppSelector((state) => state.auth.user);
|
||||
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
||||
const layoutMode = useAppSelector((state) => state.preferences.layoutMode);
|
||||
|
||||
const { data: me } = useGetMeQuery();
|
||||
const storeUser = useAppSelector((state) => state.auth.user);
|
||||
const user = (me as AuthUser | undefined) ?? storeUser;
|
||||
const [updateTrigger] = useApiMutation<AuthUser>();
|
||||
const [meTrigger] = useApiMutation<AuthUser>();
|
||||
const [passwordTrigger] = useApiMutation<unknown>();
|
||||
|
||||
const [isSavingProfile, setIsSavingProfile] = useState(false);
|
||||
@@ -89,25 +89,6 @@ export function ProfilePage() {
|
||||
const [twoStepEnabled, setTwoStepEnabled] = useState(false);
|
||||
const [emailNotifications, setEmailNotifications] = useState(true);
|
||||
|
||||
// Load the latest profile from the server on mount so the form always
|
||||
// reflects the current account information (the cached user may be stale).
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
meTrigger({ url: '/auth/me', method: 'GET' })
|
||||
.unwrap()
|
||||
.then((me) => {
|
||||
if (active) dispatch(setUser(me));
|
||||
})
|
||||
.catch(() => {
|
||||
/* fall back to the cached user already in the store */
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
// meTrigger/dispatch are stable; run once on mount.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// ---- Profile form ----
|
||||
const profileSchema = z.object({
|
||||
nameEn: z.string().min(1, { message: t('profile.validation.nameRequired') }),
|
||||
@@ -152,9 +133,7 @@ export function ProfilePage() {
|
||||
},
|
||||
}).unwrap();
|
||||
|
||||
const me = await meTrigger({ url: '/auth/me', method: 'GET' }).unwrap();
|
||||
dispatch(setUser(me));
|
||||
|
||||
dispatch(baseApi.util.invalidateTags(['Me']));
|
||||
notify.success(t('profile.profileUpdated'));
|
||||
} catch {
|
||||
notify.error(t('profile.updateFailed'));
|
||||
|
||||
@@ -138,8 +138,8 @@ export default function UserManagementPage() {
|
||||
style.textContent = UM_OVERRIDES;
|
||||
document.head.appendChild(style);
|
||||
|
||||
const token = localStorage.getItem('ema-backoffice-auth-token') ?? '';
|
||||
const refreshToken = localStorage.getItem('ema-backoffice-refresh-token') ?? undefined;
|
||||
const token = localStorage.getItem('auth-token') ?? '';
|
||||
const refreshToken = localStorage.getItem('refresh-token') ?? undefined;
|
||||
|
||||
const session: UserManagementSessionOptions = {
|
||||
initialSession: token
|
||||
|
||||
@@ -6,7 +6,7 @@ import { am } from './locales/am';
|
||||
export const SUPPORTED_LANGUAGES = ['en', 'am'] as const;
|
||||
export type AppLanguage = (typeof SUPPORTED_LANGUAGES)[number];
|
||||
|
||||
const STORAGE_KEY = 'ema-backoffice-lang';
|
||||
const STORAGE_KEY = 'app-lang';
|
||||
|
||||
function getInitialLanguage(): AppLanguage {
|
||||
const stored =
|
||||
|
||||
@@ -3,7 +3,6 @@ import { baseApi, configureTokenRefresh } from '@ema-platform/api';
|
||||
import {
|
||||
authReducer,
|
||||
signupReducer,
|
||||
configureAuthStorage,
|
||||
authStorage,
|
||||
refreshAccessToken,
|
||||
logout,
|
||||
@@ -11,8 +10,6 @@ import {
|
||||
import type { AuthUser, CurrentProfile } from '@ema-platform/auth';
|
||||
import { preferencesReducer } from './preferences.slice';
|
||||
|
||||
configureAuthStorage('ema-backoffice');
|
||||
|
||||
const preloadedAuth = (() => {
|
||||
const token = authStorage.getToken();
|
||||
const user = authStorage.getUser<AuthUser>();
|
||||
|
||||
@@ -6,7 +6,7 @@ interface PreferencesState {
|
||||
layoutMode: LayoutMode;
|
||||
}
|
||||
|
||||
const PREFERENCES_KEY = 'ema-backoffice-preferences';
|
||||
const PREFERENCES_KEY = 'app-preferences';
|
||||
|
||||
const loadPreferences = (): PreferencesState => {
|
||||
try {
|
||||
|
||||
@@ -44,8 +44,8 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { notify, PageHeader } from '@ema-platform/ui';
|
||||
import { useApiMutation } from '@ema-platform/api';
|
||||
import { authStorage, setUser, setCurrentProfile } from '@ema-platform/auth';
|
||||
import { useApiMutation, useGetMeQuery, baseApi } from '@ema-platform/api';
|
||||
import { authStorage, setCurrentProfile } from '@ema-platform/auth';
|
||||
import type { CurrentProfile } from '@ema-platform/auth';
|
||||
import { SUPPORTED_LANGUAGES, type AppLanguage } from '../../../i18n/config';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
|
||||
@@ -83,12 +83,13 @@ function passwordScore(pw: string) {
|
||||
export function ProfilePage() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const user = useAppSelector((state) => state.auth.user);
|
||||
const currentProfile = useAppSelector((state) => state.auth.currentProfile);
|
||||
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
||||
|
||||
const { data: me } = useGetMeQuery();
|
||||
const storeUser = useAppSelector((state) => state.auth.user);
|
||||
const user = (me as AuthUser | undefined) ?? storeUser;
|
||||
const [updateTrigger] = useApiMutation<AuthUser>();
|
||||
const [meTrigger] = useApiMutation<AuthUser>();
|
||||
const [passwordTrigger] = useApiMutation<unknown>();
|
||||
const [fetchProfessions] = useApiMutation<{ count: number; items: Array<{ id: string; name: { en: string } }> }>();
|
||||
|
||||
@@ -198,19 +199,6 @@ export function ProfilePage() {
|
||||
}
|
||||
}, [currentProfile, user, fetchProfile, dispatch]);
|
||||
|
||||
// Load the latest user from the server on mount
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
meTrigger({ url: '/auth/me', method: 'GET' })
|
||||
.unwrap()
|
||||
.then((me) => {
|
||||
if (active) dispatch(setUser(me));
|
||||
})
|
||||
.catch(() => {});
|
||||
return () => { active = false; };
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// ---- Personal form (auth user data) ----
|
||||
const personalSchema = z.object({
|
||||
nameEn: z.string().min(1, { message: t('profile.validation.nameRequired') }),
|
||||
@@ -251,9 +239,7 @@ export function ProfilePage() {
|
||||
},
|
||||
}).unwrap();
|
||||
|
||||
const me = await meTrigger({ url: '/auth/me', method: 'GET' }).unwrap();
|
||||
dispatch(setUser(me));
|
||||
|
||||
dispatch(baseApi.util.invalidateTags(['Me']));
|
||||
notify.success(t('profile.profileUpdated'));
|
||||
} catch {
|
||||
notify.error(t('profile.updateFailed'));
|
||||
|
||||
@@ -6,7 +6,7 @@ import { am } from './locales/am';
|
||||
export const SUPPORTED_LANGUAGES = ['en', 'am'] as const;
|
||||
export type AppLanguage = (typeof SUPPORTED_LANGUAGES)[number];
|
||||
|
||||
const STORAGE_KEY = 'ema-portal-lang';
|
||||
const STORAGE_KEY = 'app-lang';
|
||||
|
||||
function getInitialLanguage(): AppLanguage {
|
||||
const stored =
|
||||
|
||||
@@ -3,15 +3,12 @@ import { baseApi, configureTokenRefresh } from '@ema-platform/api';
|
||||
import {
|
||||
authReducer,
|
||||
signupReducer,
|
||||
configureAuthStorage,
|
||||
authStorage,
|
||||
refreshAccessToken,
|
||||
logout,
|
||||
} from '@ema-platform/auth';
|
||||
import type { AuthUser, CurrentProfile } from '@ema-platform/auth';
|
||||
|
||||
configureAuthStorage('ema-portal');
|
||||
|
||||
const preloadedAuth = (() => {
|
||||
const token = authStorage.getToken();
|
||||
const user = authStorage.getUser<AuthUser>();
|
||||
|
||||
@@ -4,6 +4,6 @@ import { baseQueryWithReauth } from './base-query-with-reauth';
|
||||
export const baseApi = createApi({
|
||||
reducerPath: 'baseApi',
|
||||
baseQuery: baseQueryWithReauth,
|
||||
tagTypes: ['Api'],
|
||||
tagTypes: ['Api', 'Me'],
|
||||
endpoints: () => ({}),
|
||||
});
|
||||
|
||||
@@ -22,11 +22,15 @@ const queryApi = baseApi.injectEndpoints({
|
||||
headers,
|
||||
}),
|
||||
}),
|
||||
getMe: builder.query<unknown, void>({
|
||||
query: () => '/auth/me',
|
||||
providesTags: ['Me'],
|
||||
}),
|
||||
}),
|
||||
overrideExisting: false,
|
||||
});
|
||||
|
||||
export const { useApiQueryQuery, useApiMutationMutation } = queryApi;
|
||||
export const { useApiQueryQuery, useApiMutationMutation, useGetMeQuery } = queryApi;
|
||||
|
||||
export function useApiQuery<TData = unknown>(
|
||||
args: ApiQueryArgs,
|
||||
|
||||
@@ -5,11 +5,7 @@ export const SESSION_HEADER_KEYS = {
|
||||
currentProjectId: 'x-current-project-id',
|
||||
} as const;
|
||||
|
||||
const TOKEN_STORAGE_KEYS = [
|
||||
'ema-backoffice-auth-token',
|
||||
'ema-portal-auth-token',
|
||||
'auth-token',
|
||||
] as const;
|
||||
const TOKEN_STORAGE_KEYS = ['auth-token'] as const;
|
||||
|
||||
export function resolveTokenFromStorage(): string | undefined {
|
||||
for (const key of TOKEN_STORAGE_KEYS) {
|
||||
|
||||
@@ -8,6 +8,6 @@ export { ForgotPasswordPage } from './lib/pages/ForgotPasswordPage';
|
||||
export { OTPVerificationPage } from './lib/pages/OTPVerificationPage';
|
||||
export { authReducer, loginSuccess, setUser, setCurrentProfile, clearCurrentProfile, logout, hydrateAuth } from './lib/store/auth.slice';
|
||||
export { signupReducer, setSignupData, setSignupStep, resetSignup } from './lib/store/signup.slice';
|
||||
export { configureAuthStorage, authStorage } from './lib/utils/auth-storage';
|
||||
export { authStorage } from './lib/utils/auth-storage';
|
||||
export { refreshAccessToken } from './lib/utils/refresh-token';
|
||||
export type { AuthUser, AuthState, LoginPayload, CurrentProfile, CurrentProfileAddress, CurrentProfileProfession } from './lib/types/auth.types';
|
||||
|
||||
@@ -1,39 +1,29 @@
|
||||
let _prefix = 'ema-auth';
|
||||
|
||||
export function configureAuthStorage(prefix: string) {
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
function key(k: string) {
|
||||
return `${_prefix}-${k}`;
|
||||
}
|
||||
|
||||
export const authStorage = {
|
||||
getToken: () => localStorage.getItem(key('auth-token')) ?? undefined,
|
||||
setToken: (token: string) => localStorage.setItem(key('auth-token'), token),
|
||||
getRefreshToken: () => localStorage.getItem(key('refresh-token')) ?? undefined,
|
||||
setRefreshToken: (t: string) => localStorage.setItem(key('refresh-token'), t),
|
||||
getToken: () => localStorage.getItem('auth-token') ?? undefined,
|
||||
setToken: (token: string) => localStorage.setItem('auth-token', token),
|
||||
getRefreshToken: () => localStorage.getItem('refresh-token') ?? undefined,
|
||||
setRefreshToken: (t: string) => localStorage.setItem('refresh-token', t),
|
||||
getUser: <T = unknown>(): T | null => {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(key('auth-user')) ?? 'null') as T | null;
|
||||
return JSON.parse(localStorage.getItem('auth-user') ?? 'null') as T | null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setUser: <T>(u: T) => localStorage.setItem(key('auth-user'), JSON.stringify(u)),
|
||||
getProfileId: () => localStorage.getItem(key('profile-id')) ?? undefined,
|
||||
setProfileId: (id: string) => localStorage.setItem(key('profile-id'), id),
|
||||
setUser: <T>(u: T) => localStorage.setItem('auth-user', JSON.stringify(u)),
|
||||
getProfileId: () => localStorage.getItem('profile-id') ?? undefined,
|
||||
setProfileId: (id: string) => localStorage.setItem('profile-id', id),
|
||||
getProfile: <T = unknown>(): T | null => {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(key('current-profile')) ?? 'null') as T | null;
|
||||
return JSON.parse(localStorage.getItem('current-profile') ?? 'null') as T | null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
setProfile: <T>(p: T) => localStorage.setItem(key('current-profile'), JSON.stringify(p)),
|
||||
removeProfile: () => localStorage.removeItem(key('current-profile')),
|
||||
setProfile: <T>(p: T) => localStorage.setItem('current-profile', JSON.stringify(p)),
|
||||
removeProfile: () => localStorage.removeItem('current-profile'),
|
||||
clear: () => {
|
||||
[key('auth-token'), key('refresh-token'), key('auth-user'), key('profile-id'), key('current-profile')].forEach((k) =>
|
||||
['auth-token', 'refresh-token', 'auth-user', 'profile-id', 'current-profile'].forEach((k) =>
|
||||
localStorage.removeItem(k),
|
||||
);
|
||||
document.cookie =
|
||||
|
||||
Reference in New Issue
Block a user