@digitaldefiance/express-suite-react-components 2.9.7 → 2.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -5
- package/src/auth/Private.d.ts +6 -0
- package/src/auth/Private.d.ts.map +1 -0
- package/src/auth/Private.js +14 -0
- package/src/auth/PrivateRoute.d.ts +8 -0
- package/src/auth/PrivateRoute.d.ts.map +1 -0
- package/src/auth/PrivateRoute.js +23 -0
- package/src/auth/UnAuth.d.ts +6 -0
- package/src/auth/UnAuth.d.ts.map +1 -0
- package/src/auth/UnAuth.js +14 -0
- package/src/auth/UnAuthRoute.d.ts +8 -0
- package/src/auth/UnAuthRoute.d.ts.map +1 -0
- package/src/auth/UnAuthRoute.js +22 -0
- package/src/auth/{index.ts → index.d.ts} +2 -1
- package/src/auth/index.d.ts.map +1 -0
- package/src/auth/index.js +10 -0
- package/src/components/ApiAccess.d.ts +16 -0
- package/src/components/ApiAccess.d.ts.map +1 -0
- package/src/components/ApiAccess.js +70 -0
- package/src/components/BackupCodeLoginForm.d.ts +43 -0
- package/src/components/BackupCodeLoginForm.d.ts.map +1 -0
- package/src/components/BackupCodeLoginForm.js +106 -0
- package/src/components/BackupCodesForm.d.ts +26 -0
- package/src/components/BackupCodesForm.d.ts.map +1 -0
- package/src/components/BackupCodesForm.js +108 -0
- package/src/components/ChangePasswordForm.d.ts +26 -0
- package/src/components/ChangePasswordForm.d.ts.map +1 -0
- package/src/components/ChangePasswordForm.js +66 -0
- package/src/components/ConfirmationDialog.d.ts +13 -0
- package/src/components/ConfirmationDialog.d.ts.map +1 -0
- package/src/components/ConfirmationDialog.js +10 -0
- package/src/components/CurrencyCodeSelector.d.ts +9 -0
- package/src/components/CurrencyCodeSelector.d.ts.map +1 -0
- package/src/components/CurrencyCodeSelector.js +31 -0
- package/src/components/CurrencyInput.d.ts +13 -0
- package/src/components/CurrencyInput.d.ts.map +1 -0
- package/src/components/CurrencyInput.js +22 -0
- package/src/components/DashboardPage.d.ts +8 -0
- package/src/components/DashboardPage.d.ts.map +1 -0
- package/src/components/DashboardPage.js +10 -0
- package/src/components/DropdownMenu.d.ts +9 -0
- package/src/components/DropdownMenu.d.ts.map +1 -0
- package/src/components/DropdownMenu.js +56 -0
- package/src/components/ExpirationSecondsSelector.d.ts +13 -0
- package/src/components/ExpirationSecondsSelector.d.ts.map +1 -0
- package/src/components/ExpirationSecondsSelector.js +32 -0
- package/src/components/Flag.d.ts +20 -0
- package/src/components/Flag.d.ts.map +1 -0
- package/src/components/Flag.js +43 -0
- package/src/components/ForgotPasswordForm.d.ts +18 -0
- package/src/components/ForgotPasswordForm.d.ts.map +1 -0
- package/src/components/ForgotPasswordForm.js +54 -0
- package/src/components/LoginForm.d.ts +44 -0
- package/src/components/LoginForm.d.ts.map +1 -0
- package/src/components/LoginForm.js +99 -0
- package/src/components/LogoutPage.d.ts +8 -0
- package/src/components/LogoutPage.d.ts.map +1 -0
- package/src/components/LogoutPage.js +16 -0
- package/src/components/RegisterForm.d.ts +54 -0
- package/src/components/RegisterForm.d.ts.map +1 -0
- package/src/components/RegisterForm.js +105 -0
- package/src/components/ResetPasswordForm.d.ts +23 -0
- package/src/components/ResetPasswordForm.d.ts.map +1 -0
- package/src/components/ResetPasswordForm.js +68 -0
- package/src/components/SideMenu.d.ts +8 -0
- package/src/components/SideMenu.d.ts.map +1 -0
- package/src/components/SideMenu.js +25 -0
- package/src/components/SideMenuListItem.d.ts +13 -0
- package/src/components/SideMenuListItem.d.ts.map +1 -0
- package/src/components/SideMenuListItem.js +44 -0
- package/src/components/TopMenu.d.ts +24 -0
- package/src/components/TopMenu.d.ts.map +1 -0
- package/src/components/TopMenu.js +42 -0
- package/src/components/TranslatedTitle.d.ts +7 -0
- package/src/components/TranslatedTitle.d.ts.map +1 -0
- package/src/components/TranslatedTitle.js +15 -0
- package/src/components/UserLanguageSelector.d.ts +4 -0
- package/src/components/UserLanguageSelector.d.ts.map +1 -0
- package/src/components/UserLanguageSelector.js +31 -0
- package/src/components/UserMenu.d.ts +4 -0
- package/src/components/UserMenu.d.ts.map +1 -0
- package/src/components/UserMenu.js +12 -0
- package/src/components/UserSettingsForm.d.ts +56 -0
- package/src/components/UserSettingsForm.d.ts.map +1 -0
- package/src/components/UserSettingsForm.js +93 -0
- package/src/components/VerifyEmailPage.d.ts +23 -0
- package/src/components/VerifyEmailPage.d.ts.map +1 -0
- package/src/components/VerifyEmailPage.js +61 -0
- package/src/components/{index.ts → index.d.ts} +1 -1
- package/src/components/index.d.ts.map +1 -0
- package/src/components/index.js +28 -0
- package/src/contexts/AuthProvider.d.ts +152 -0
- package/src/contexts/AuthProvider.d.ts.map +1 -0
- package/src/contexts/AuthProvider.js +446 -0
- package/src/contexts/I18nProvider.d.ts +16 -0
- package/src/contexts/I18nProvider.d.ts.map +1 -0
- package/src/contexts/I18nProvider.js +46 -0
- package/src/contexts/MenuContext.d.ts +20 -0
- package/src/contexts/MenuContext.d.ts.map +1 -0
- package/src/contexts/MenuContext.js +244 -0
- package/src/contexts/SuiteConfigProvider.d.ts +44 -0
- package/src/contexts/SuiteConfigProvider.d.ts.map +1 -0
- package/src/contexts/SuiteConfigProvider.js +43 -0
- package/src/contexts/ThemeProvider.d.ts +15 -0
- package/src/contexts/ThemeProvider.d.ts.map +1 -0
- package/src/contexts/ThemeProvider.js +36 -0
- package/src/contexts/{index.ts → index.d.ts} +1 -0
- package/src/contexts/index.d.ts.map +1 -0
- package/src/contexts/index.js +8 -0
- package/src/hooks/{index.ts → index.d.ts} +1 -0
- package/src/hooks/index.d.ts.map +1 -0
- package/src/hooks/index.js +8 -0
- package/src/hooks/useBackupCodes.d.ts +15 -0
- package/src/hooks/useBackupCodes.d.ts.map +1 -0
- package/src/hooks/useBackupCodes.js +70 -0
- package/src/hooks/useEmailVerification.d.ts +10 -0
- package/src/hooks/useEmailVerification.d.ts.map +1 -0
- package/src/hooks/useEmailVerification.js +36 -0
- package/src/hooks/useExpiringValue.d.ts +14 -0
- package/src/hooks/useExpiringValue.d.ts.map +1 -0
- package/src/hooks/useExpiringValue.js +53 -0
- package/src/hooks/useLocalStorage.d.ts +2 -0
- package/src/hooks/useLocalStorage.d.ts.map +1 -0
- package/src/hooks/useLocalStorage.js +15 -0
- package/src/hooks/useUserSettings.d.ts +46 -0
- package/src/hooks/useUserSettings.d.ts.map +1 -0
- package/src/hooks/useUserSettings.js +152 -0
- package/src/{index.ts → index.d.ts} +1 -1
- package/src/index.d.ts.map +1 -0
- package/src/index.js +12 -0
- package/src/interfaces/IAppConfig.d.ts +6 -0
- package/src/interfaces/IAppConfig.d.ts.map +1 -0
- package/src/interfaces/IAppConfig.js +2 -0
- package/src/interfaces/IMenuConfig.d.ts +11 -0
- package/src/interfaces/IMenuConfig.d.ts.map +1 -0
- package/src/interfaces/IMenuConfig.js +2 -0
- package/src/interfaces/IMenuOption.d.ts +58 -0
- package/src/interfaces/IMenuOption.d.ts.map +1 -0
- package/src/interfaces/IMenuOption.js +2 -0
- package/src/interfaces/index.d.ts +4 -0
- package/src/interfaces/index.d.ts.map +1 -0
- package/src/interfaces/index.js +6 -0
- package/src/services/__mocks__/authService.d.ts +21 -0
- package/src/services/__mocks__/authService.d.ts.map +1 -0
- package/src/services/__mocks__/authService.js +15 -0
- package/src/services/api.d.ts +3 -0
- package/src/services/api.d.ts.map +1 -0
- package/src/services/api.js +14 -0
- package/src/services/authService.d.ts +72 -0
- package/src/services/authService.d.ts.map +1 -0
- package/src/services/authService.js +347 -0
- package/src/services/authenticatedApi.d.ts +3 -0
- package/src/services/authenticatedApi.d.ts.map +1 -0
- package/src/services/authenticatedApi.js +18 -0
- package/src/services/index.d.ts +4 -0
- package/src/services/index.d.ts.map +1 -0
- package/src/services/index.js +6 -0
- package/src/types/MenuType.d.ts +11 -0
- package/src/types/MenuType.d.ts.map +1 -0
- package/src/types/MenuType.js +12 -0
- package/src/types/expirationSeconds.d.ts +3 -0
- package/src/types/expirationSeconds.d.ts.map +1 -0
- package/src/types/expirationSeconds.js +17 -0
- package/src/types/index.d.ts +2 -0
- package/src/types/index.d.ts.map +1 -0
- package/src/types/index.js +4 -0
- package/src/types/translation.d.ts +10 -0
- package/src/types/translation.d.ts.map +1 -0
- package/src/types/translation.js +9 -0
- package/src/wrappers/BackupCodeLoginWrapper.d.ts +8 -0
- package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +1 -0
- package/src/wrappers/BackupCodeLoginWrapper.js +21 -0
- package/src/wrappers/BackupCodesWrapper.d.ts +7 -0
- package/src/wrappers/BackupCodesWrapper.d.ts.map +1 -0
- package/src/wrappers/BackupCodesWrapper.js +17 -0
- package/src/wrappers/ChangePasswordFormWrapper.d.ts +8 -0
- package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +1 -0
- package/src/wrappers/ChangePasswordFormWrapper.js +21 -0
- package/src/wrappers/LoginFormWrapper.d.ts +9 -0
- package/src/wrappers/LoginFormWrapper.d.ts.map +1 -0
- package/src/wrappers/LoginFormWrapper.js +43 -0
- package/src/wrappers/LogoutPageWrapper.d.ts +9 -0
- package/src/wrappers/LogoutPageWrapper.d.ts.map +1 -0
- package/src/wrappers/LogoutPageWrapper.js +21 -0
- package/src/wrappers/RegisterFormWrapper.d.ts +9 -0
- package/src/wrappers/RegisterFormWrapper.d.ts.map +1 -0
- package/src/wrappers/RegisterFormWrapper.js +26 -0
- package/src/wrappers/UserSettingsFormWrapper.d.ts +8 -0
- package/src/wrappers/UserSettingsFormWrapper.d.ts.map +1 -0
- package/src/wrappers/UserSettingsFormWrapper.js +24 -0
- package/src/wrappers/VerifyEmailPageWrapper.d.ts +8 -0
- package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +1 -0
- package/src/wrappers/VerifyEmailPageWrapper.js +20 -0
- package/src/wrappers/{index.tsx → index.d.ts} +1 -8
- package/src/wrappers/index.d.ts.map +1 -0
- package/src/wrappers/index.js +20 -0
- package/LICENSE +0 -21
- package/src/auth/Private.tsx +0 -17
- package/src/auth/PrivateRoute.tsx +0 -28
- package/src/auth/UnAuth.tsx +0 -16
- package/src/auth/UnAuthRoute.tsx +0 -30
- package/src/components/ApiAccess.tsx +0 -134
- package/src/components/BackupCodeLoginForm.tsx +0 -314
- package/src/components/BackupCodesForm.tsx +0 -198
- package/src/components/ChangePasswordForm.tsx +0 -182
- package/src/components/ConfirmationDialog.tsx +0 -48
- package/src/components/CurrencyCodeSelector.tsx +0 -60
- package/src/components/CurrencyInput.tsx +0 -80
- package/src/components/DashboardPage.tsx +0 -24
- package/src/components/DropdownMenu.tsx +0 -92
- package/src/components/ExpirationSecondsSelector.tsx +0 -65
- package/src/components/Flag.tsx +0 -53
- package/src/components/ForgotPasswordForm.tsx +0 -120
- package/src/components/LoginForm.tsx +0 -307
- package/src/components/LogoutPage.tsx +0 -21
- package/src/components/RegisterForm.tsx +0 -354
- package/src/components/ResetPasswordForm.tsx +0 -164
- package/src/components/SideMenu.tsx +0 -46
- package/src/components/SideMenuListItem.tsx +0 -74
- package/src/components/TopMenu.tsx +0 -149
- package/src/components/TranslatedTitle.tsx +0 -22
- package/src/components/UserLanguageSelector.tsx +0 -45
- package/src/components/UserMenu.tsx +0 -15
- package/src/components/UserSettingsForm.tsx +0 -328
- package/src/components/VerifyEmailPage.tsx +0 -133
- package/src/contexts/AuthProvider.spec.tsx +0 -1060
- package/src/contexts/AuthProvider.tsx +0 -741
- package/src/contexts/I18nProvider.tsx +0 -85
- package/src/contexts/MenuContext.tsx +0 -310
- package/src/contexts/SuiteConfigProvider.tsx +0 -93
- package/src/contexts/ThemeProvider.tsx +0 -67
- package/src/hooks/useBackupCodes.ts +0 -85
- package/src/hooks/useEmailVerification.ts +0 -39
- package/src/hooks/useExpiringValue.ts +0 -78
- package/src/hooks/useLocalStorage.ts +0 -18
- package/src/hooks/useUserSettings.ts +0 -216
- package/src/interfaces/IAppConfig.ts +0 -5
- package/src/interfaces/IMenuConfig.ts +0 -11
- package/src/interfaces/IMenuOption.ts +0 -55
- package/src/interfaces/index.ts +0 -3
- package/src/services/__mocks__/authService.ts +0 -14
- package/src/services/api.ts +0 -13
- package/src/services/authService.ts +0 -422
- package/src/services/authenticatedApi.ts +0 -17
- package/src/services/index.ts +0 -3
- package/src/types/MenuType.ts +0 -15
- package/src/types/expirationSeconds.ts +0 -18
- package/src/types/index.ts +0 -1
- package/src/types/translation.ts +0 -20
- package/src/wrappers/BackupCodeLoginWrapper.tsx +0 -35
- package/src/wrappers/BackupCodesWrapper.tsx +0 -28
- package/src/wrappers/ChangePasswordFormWrapper.tsx +0 -31
- package/src/wrappers/LoginFormWrapper.tsx +0 -59
- package/src/wrappers/LogoutPageWrapper.tsx +0 -30
- package/src/wrappers/RegisterFormWrapper.tsx +0 -48
- package/src/wrappers/UserSettingsFormWrapper.tsx +0 -39
- package/src/wrappers/VerifyEmailPageWrapper.tsx +0 -27
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface TimerInfo {
|
|
4
|
-
timeout: NodeJS.Timeout;
|
|
5
|
-
startTime: number;
|
|
6
|
-
durationMs: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface ExpiringValueReturn<T> {
|
|
10
|
-
value: T | undefined;
|
|
11
|
-
setValue: (newValue: T, durationSeconds?: number, saveToStorage?: boolean) => () => void;
|
|
12
|
-
clearValue: () => void;
|
|
13
|
-
getRemainingTime: () => number;
|
|
14
|
-
isActive: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function useExpiringValue<T>(
|
|
18
|
-
defaultDurationSeconds: number,
|
|
19
|
-
localStorageKey?: string
|
|
20
|
-
): ExpiringValueReturn<T> {
|
|
21
|
-
const [value, _setValue] = useState<T | undefined>(undefined);
|
|
22
|
-
const [timer, setTimer] = useState<TimerInfo | undefined>(undefined);
|
|
23
|
-
const [durationSeconds, _setDurationSeconds] = useState<number>(() => {
|
|
24
|
-
if (localStorageKey) {
|
|
25
|
-
const stored = localStorage.getItem(localStorageKey);
|
|
26
|
-
return stored ? parseInt(stored, 10) : defaultDurationSeconds;
|
|
27
|
-
}
|
|
28
|
-
return defaultDurationSeconds;
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const getRemainingTime = useCallback((): number => {
|
|
32
|
-
if (!timer) return 0;
|
|
33
|
-
const elapsed = Date.now() - timer.startTime;
|
|
34
|
-
const remaining = Math.max(0, timer.durationMs - elapsed);
|
|
35
|
-
return Math.ceil(remaining / 1000);
|
|
36
|
-
}, [timer]);
|
|
37
|
-
|
|
38
|
-
const setValue = useCallback((newValue: T, customDurationSeconds?: number, saveToStorage?: boolean) => {
|
|
39
|
-
const finalDurationSeconds = customDurationSeconds ?? durationSeconds;
|
|
40
|
-
|
|
41
|
-
if (saveToStorage && customDurationSeconds !== undefined && localStorageKey) {
|
|
42
|
-
_setDurationSeconds(customDurationSeconds);
|
|
43
|
-
localStorage.setItem(localStorageKey, customDurationSeconds.toString());
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
_setValue(newValue);
|
|
47
|
-
|
|
48
|
-
if (timer) {
|
|
49
|
-
clearTimeout(timer.timeout);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const startTime = Date.now();
|
|
53
|
-
const durationMs = finalDurationSeconds * 1000;
|
|
54
|
-
const timeout = setTimeout(() => {
|
|
55
|
-
_setValue(undefined);
|
|
56
|
-
setTimer(undefined);
|
|
57
|
-
}, durationMs);
|
|
58
|
-
|
|
59
|
-
setTimer({ timeout, startTime, durationMs });
|
|
60
|
-
|
|
61
|
-
return () => {
|
|
62
|
-
clearTimeout(timeout);
|
|
63
|
-
setTimer(undefined);
|
|
64
|
-
};
|
|
65
|
-
}, [durationSeconds, timer, localStorageKey]);
|
|
66
|
-
|
|
67
|
-
const clearValue = useCallback(() => {
|
|
68
|
-
if (timer) {
|
|
69
|
-
clearTimeout(timer.timeout);
|
|
70
|
-
setTimer(undefined);
|
|
71
|
-
}
|
|
72
|
-
_setValue(undefined);
|
|
73
|
-
}, [timer]);
|
|
74
|
-
|
|
75
|
-
const isActive = Boolean(timer && value !== undefined);
|
|
76
|
-
|
|
77
|
-
return { value, setValue, clearValue, getRemainingTime, isActive };
|
|
78
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState } from 'react';
|
|
2
|
-
import { LocalStorageManager } from '@digitaldefiance/suite-core-lib';
|
|
3
|
-
|
|
4
|
-
export function useLocalStorage<T>(
|
|
5
|
-
key: string,
|
|
6
|
-
defaultValue: T
|
|
7
|
-
): [T, (value: T) => void] {
|
|
8
|
-
const [storedValue, setStoredValue] = useState<T>(() => {
|
|
9
|
-
return LocalStorageManager.getValue(key, defaultValue);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const setValue = useCallback((value: T) => {
|
|
13
|
-
setStoredValue(value);
|
|
14
|
-
LocalStorageManager.setValue(key, value);
|
|
15
|
-
}, [key]);
|
|
16
|
-
|
|
17
|
-
return [storedValue, setValue];
|
|
18
|
-
}
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState, useEffect } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
CurrencyCode,
|
|
4
|
-
DefaultCurrencyCode,
|
|
5
|
-
DefaultTimezone,
|
|
6
|
-
DefaultLanguageCode,
|
|
7
|
-
Timezone,
|
|
8
|
-
} from '@digitaldefiance/i18n-lib';
|
|
9
|
-
import { EmailString } from '@digitaldefiance/ecies-lib';
|
|
10
|
-
import {
|
|
11
|
-
IUserSettings,
|
|
12
|
-
dehydrateUserSettings,
|
|
13
|
-
IRequestUserDTO,
|
|
14
|
-
IUserSettingsDTO,
|
|
15
|
-
getSuiteCoreTranslation,
|
|
16
|
-
SuiteCoreStringKey,
|
|
17
|
-
TranslatableSuiteError,
|
|
18
|
-
} from '@digitaldefiance/suite-core-lib';
|
|
19
|
-
import { useAuth, useI18n, useTheme } from '../contexts';
|
|
20
|
-
|
|
21
|
-
const defaultUserSettings: Partial<IUserSettings> = {
|
|
22
|
-
darkMode: false,
|
|
23
|
-
currency: new CurrencyCode(DefaultCurrencyCode),
|
|
24
|
-
timezone: new Timezone(DefaultTimezone),
|
|
25
|
-
siteLanguage: DefaultLanguageCode,
|
|
26
|
-
directChallenge: false,
|
|
27
|
-
} as const;
|
|
28
|
-
|
|
29
|
-
export interface UseUserSettingsOptions {
|
|
30
|
-
authenticatedApi: {
|
|
31
|
-
post: (url: string, data: any) => Promise<any>;
|
|
32
|
-
};
|
|
33
|
-
isAuthenticated: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface UseUserSettingsResult {
|
|
37
|
-
currentLanguage: string;
|
|
38
|
-
changeLanguage: (languageCode: string) => Promise<void>;
|
|
39
|
-
userSettings: IUserSettings | undefined;
|
|
40
|
-
setUserSettingAndUpdateSettings: (setting?: Partial<IUserSettings>) => Promise<void>;
|
|
41
|
-
toggleColorMode: () => Promise<void>;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Hook for managing user settings state and synchronization.
|
|
46
|
-
* Used by AuthProvider to handle user settings logic.
|
|
47
|
-
*/
|
|
48
|
-
export const useUserSettings = ({
|
|
49
|
-
authenticatedApi,
|
|
50
|
-
isAuthenticated,
|
|
51
|
-
}: UseUserSettingsOptions): UseUserSettingsResult => {
|
|
52
|
-
const { setColorMode: themeSetPaletteMode, mode: currentThemeMode } = useTheme();
|
|
53
|
-
const { currentLanguage, changeLanguage } = useI18n();
|
|
54
|
-
const [userSettings, setUserSettings] = useState<IUserSettings | undefined>(undefined);
|
|
55
|
-
|
|
56
|
-
const setUserSettingAndUpdateSettings = useCallback(
|
|
57
|
-
async (setting?: Partial<IUserSettings>) => {
|
|
58
|
-
if (setting) {
|
|
59
|
-
// Merge settings with defaults and existing settings
|
|
60
|
-
const merged = {
|
|
61
|
-
...defaultUserSettings,
|
|
62
|
-
...(userSettings ? userSettings : {}),
|
|
63
|
-
...setting,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// TypeScript requires all IUserSettings fields, but during initialization
|
|
67
|
-
// some fields like email may not be set yet. We'll use Partial until
|
|
68
|
-
// all required fields are available.
|
|
69
|
-
setUserSettings(merged as IUserSettings);
|
|
70
|
-
|
|
71
|
-
if (setting.darkMode !== undefined) {
|
|
72
|
-
themeSetPaletteMode(setting.darkMode ? 'dark' : 'light');
|
|
73
|
-
}
|
|
74
|
-
if (setting.siteLanguage !== undefined && setting.siteLanguage !== currentLanguage) {
|
|
75
|
-
changeLanguage(setting.siteLanguage);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Send to server if authenticated and we have complete settings (including email)
|
|
79
|
-
if (isAuthenticated && merged.email) {
|
|
80
|
-
const dehydratedSettings = dehydrateUserSettings(merged as IUserSettings);
|
|
81
|
-
await authenticatedApi.post('/user/settings', dehydratedSettings);
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
setUserSettings(undefined);
|
|
85
|
-
themeSetPaletteMode('light');
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
[isAuthenticated, userSettings, currentLanguage, changeLanguage, themeSetPaletteMode, authenticatedApi]
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const changeLanguageSetting = useCallback(
|
|
92
|
-
async (languageCode: string) => {
|
|
93
|
-
await setUserSettingAndUpdateSettings({ siteLanguage: languageCode });
|
|
94
|
-
},
|
|
95
|
-
[setUserSettingAndUpdateSettings]
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const toggleColorMode = useCallback(async () => {
|
|
99
|
-
// When not authenticated, read from the current theme mode
|
|
100
|
-
// When authenticated, read from userSettings (synced with server)
|
|
101
|
-
const currentDarkMode = isAuthenticated
|
|
102
|
-
? (userSettings?.darkMode ?? false)
|
|
103
|
-
: (currentThemeMode === 'dark');
|
|
104
|
-
await setUserSettingAndUpdateSettings({ darkMode: !currentDarkMode });
|
|
105
|
-
}, [isAuthenticated, userSettings?.darkMode, currentThemeMode, setUserSettingAndUpdateSettings]);
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
changeLanguage: changeLanguageSetting,
|
|
109
|
-
currentLanguage,
|
|
110
|
-
userSettings,
|
|
111
|
-
setUserSettingAndUpdateSettings,
|
|
112
|
-
toggleColorMode,
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// Public-facing hook for components
|
|
117
|
-
export interface UserSettingsValues extends IUserSettingsDTO {
|
|
118
|
-
[key: string]: any;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export interface UseUserSettingsPublicResult {
|
|
122
|
-
settings: UserSettingsValues | null;
|
|
123
|
-
isLoading: boolean;
|
|
124
|
-
error: Error | null;
|
|
125
|
-
updateSettings: (values: UserSettingsValues) => Promise<{
|
|
126
|
-
success: boolean;
|
|
127
|
-
message: string;
|
|
128
|
-
} | {
|
|
129
|
-
error: string;
|
|
130
|
-
errorType?: string;
|
|
131
|
-
field?: string;
|
|
132
|
-
errors?: Array<{ path: string; msg: string }>;
|
|
133
|
-
}>;
|
|
134
|
-
refreshSettings: () => Promise<void>;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Public hook for components to manage user settings.
|
|
139
|
-
* Provides a simpler API for fetching and updating settings.
|
|
140
|
-
*/
|
|
141
|
-
export const useUserSettingsPublic = (): UseUserSettingsPublicResult => {
|
|
142
|
-
const { userData, setUserSetting, userSettings } = useAuth();
|
|
143
|
-
const [settings, setSettings] = useState<UserSettingsValues | null>(null);
|
|
144
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
145
|
-
const [error, setError] = useState<Error | null>(null);
|
|
146
|
-
|
|
147
|
-
const refreshSettings = useCallback(async () => {
|
|
148
|
-
setIsLoading(true);
|
|
149
|
-
setError(null);
|
|
150
|
-
try {
|
|
151
|
-
if (userSettings) {
|
|
152
|
-
const dehydratedSettings = dehydrateUserSettings(userSettings);
|
|
153
|
-
setSettings(dehydratedSettings);
|
|
154
|
-
} else if (userData) {
|
|
155
|
-
const fallback = {
|
|
156
|
-
email: userData.email || '',
|
|
157
|
-
timezone: userData.timezone || 'UTC',
|
|
158
|
-
siteLanguage: userData.siteLanguage || 'en-US',
|
|
159
|
-
currency: userData.currency || 'USD',
|
|
160
|
-
darkMode: userData.darkMode || false,
|
|
161
|
-
directChallenge: userData.directChallenge || false,
|
|
162
|
-
};
|
|
163
|
-
setSettings(fallback);
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
setError(err instanceof Error ? err : new TranslatableSuiteError(SuiteCoreStringKey.Settings_RetrieveFailure));
|
|
167
|
-
} finally {
|
|
168
|
-
setIsLoading(false);
|
|
169
|
-
}
|
|
170
|
-
}, [userSettings, userData]);
|
|
171
|
-
|
|
172
|
-
useEffect(() => {
|
|
173
|
-
refreshSettings();
|
|
174
|
-
}, [refreshSettings]);
|
|
175
|
-
|
|
176
|
-
const updateSettings = useCallback(async (values: UserSettingsValues) => {
|
|
177
|
-
setIsLoading(true);
|
|
178
|
-
setError(null);
|
|
179
|
-
try {
|
|
180
|
-
await setUserSetting({
|
|
181
|
-
darkMode: values.darkMode,
|
|
182
|
-
currency: new CurrencyCode(values.currency),
|
|
183
|
-
timezone: new Timezone(values.timezone),
|
|
184
|
-
siteLanguage: values.siteLanguage,
|
|
185
|
-
email: new EmailString(values.email),
|
|
186
|
-
directChallenge: values.directChallenge,
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
setSettings(values);
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
success: true,
|
|
193
|
-
message: getSuiteCoreTranslation(SuiteCoreStringKey.Settings_SaveSuccess)
|
|
194
|
-
};
|
|
195
|
-
} catch (err: any) {
|
|
196
|
-
const errorMessage = err.response?.data?.message || getSuiteCoreTranslation(SuiteCoreStringKey.Settings_UpdateFailed);
|
|
197
|
-
setError(err instanceof Error ? err : new Error(errorMessage));
|
|
198
|
-
return {
|
|
199
|
-
error: errorMessage,
|
|
200
|
-
errorType: err.response?.data?.errorType,
|
|
201
|
-
field: err.response?.data?.field,
|
|
202
|
-
errors: err.response?.data?.errors,
|
|
203
|
-
};
|
|
204
|
-
} finally {
|
|
205
|
-
setIsLoading(false);
|
|
206
|
-
}
|
|
207
|
-
}, [setUserSetting]);
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
settings,
|
|
211
|
-
isLoading,
|
|
212
|
-
error,
|
|
213
|
-
updateSettings,
|
|
214
|
-
refreshSettings,
|
|
215
|
-
};
|
|
216
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import { IMenuOption } from './IMenuOption';
|
|
3
|
-
import { createMenuType } from '../types';
|
|
4
|
-
|
|
5
|
-
export interface IMenuConfig {
|
|
6
|
-
menuType: ReturnType<typeof createMenuType>;
|
|
7
|
-
menuIcon: ReactElement;
|
|
8
|
-
priority?: number;
|
|
9
|
-
options: IMenuOption[];
|
|
10
|
-
isUserMenu?: boolean;
|
|
11
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import { To } from 'react-router-dom';
|
|
3
|
-
import { MenuType } from '../types/MenuType';
|
|
4
|
-
|
|
5
|
-
export interface IMenuOption {
|
|
6
|
-
/**
|
|
7
|
-
* Unique identifier for the menu option
|
|
8
|
-
*/
|
|
9
|
-
id: string;
|
|
10
|
-
/**
|
|
11
|
-
* Text to display for the menu option
|
|
12
|
-
*/
|
|
13
|
-
label: string;
|
|
14
|
-
/**
|
|
15
|
-
* Where the menu option should be displayed
|
|
16
|
-
*/
|
|
17
|
-
includeOnMenus: MenuType[];
|
|
18
|
-
/**
|
|
19
|
-
* Display order for the menu option. Lower numbers are displayed first.
|
|
20
|
-
*/
|
|
21
|
-
index: number;
|
|
22
|
-
/**
|
|
23
|
-
* Whether the menu option is a divider
|
|
24
|
-
*/
|
|
25
|
-
divider?: boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Icon to display for the menu option
|
|
28
|
-
*/
|
|
29
|
-
icon?: ReactNode;
|
|
30
|
-
/**
|
|
31
|
-
* Link to navigate to when the menu option is clicked
|
|
32
|
-
* Mutually exclusive with `action`
|
|
33
|
-
* Can be a string, a react-router To object, or an object with pathname and optional state
|
|
34
|
-
*/
|
|
35
|
-
link?: To | { pathname: string; state?: unknown };
|
|
36
|
-
/**
|
|
37
|
-
* Function to execute when the menu option is clicked
|
|
38
|
-
* Mutually exclusive with `link`
|
|
39
|
-
* @returns void
|
|
40
|
-
*/
|
|
41
|
-
action?: () => void;
|
|
42
|
-
/**
|
|
43
|
-
* Whether the menu option requires authentication
|
|
44
|
-
* true = requires authentication
|
|
45
|
-
* false = requires unauthenticated
|
|
46
|
-
* undefined = always show
|
|
47
|
-
*/
|
|
48
|
-
requiresAuth: boolean | undefined;
|
|
49
|
-
/**
|
|
50
|
-
* Custom filter function to determine if the menu option should be displayed
|
|
51
|
-
* @param option - The menu option to filter
|
|
52
|
-
* @returns boolean
|
|
53
|
-
*/
|
|
54
|
-
filter?: (option: IMenuOption) => boolean;
|
|
55
|
-
}
|
package/src/interfaces/index.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
|
|
3
|
-
export const mockAuthService = {
|
|
4
|
-
verifyToken: jest.fn(),
|
|
5
|
-
directLogin: jest.fn(),
|
|
6
|
-
emailChallengeLogin: jest.fn(),
|
|
7
|
-
refreshToken: jest.fn(),
|
|
8
|
-
register: jest.fn(),
|
|
9
|
-
requestEmailLogin: jest.fn(),
|
|
10
|
-
backupCodeLogin: jest.fn(),
|
|
11
|
-
changePassword: jest.fn(),
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const createAuthService = jest.fn(() => mockAuthService);
|
package/src/services/api.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
|
|
3
|
-
export function createApiClient(baseURL: string) {
|
|
4
|
-
const api = axios.create({ baseURL });
|
|
5
|
-
|
|
6
|
-
api.interceptors.request.use((config) => {
|
|
7
|
-
const languageCode = localStorage.getItem('languageCode') ?? 'en-US';
|
|
8
|
-
config.headers['Accept-Language'] = languageCode;
|
|
9
|
-
return config;
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
return api;
|
|
13
|
-
}
|