@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.
Files changed (257) hide show
  1. package/package.json +6 -5
  2. package/src/auth/Private.d.ts +6 -0
  3. package/src/auth/Private.d.ts.map +1 -0
  4. package/src/auth/Private.js +14 -0
  5. package/src/auth/PrivateRoute.d.ts +8 -0
  6. package/src/auth/PrivateRoute.d.ts.map +1 -0
  7. package/src/auth/PrivateRoute.js +23 -0
  8. package/src/auth/UnAuth.d.ts +6 -0
  9. package/src/auth/UnAuth.d.ts.map +1 -0
  10. package/src/auth/UnAuth.js +14 -0
  11. package/src/auth/UnAuthRoute.d.ts +8 -0
  12. package/src/auth/UnAuthRoute.d.ts.map +1 -0
  13. package/src/auth/UnAuthRoute.js +22 -0
  14. package/src/auth/{index.ts → index.d.ts} +2 -1
  15. package/src/auth/index.d.ts.map +1 -0
  16. package/src/auth/index.js +10 -0
  17. package/src/components/ApiAccess.d.ts +16 -0
  18. package/src/components/ApiAccess.d.ts.map +1 -0
  19. package/src/components/ApiAccess.js +70 -0
  20. package/src/components/BackupCodeLoginForm.d.ts +43 -0
  21. package/src/components/BackupCodeLoginForm.d.ts.map +1 -0
  22. package/src/components/BackupCodeLoginForm.js +106 -0
  23. package/src/components/BackupCodesForm.d.ts +26 -0
  24. package/src/components/BackupCodesForm.d.ts.map +1 -0
  25. package/src/components/BackupCodesForm.js +108 -0
  26. package/src/components/ChangePasswordForm.d.ts +26 -0
  27. package/src/components/ChangePasswordForm.d.ts.map +1 -0
  28. package/src/components/ChangePasswordForm.js +66 -0
  29. package/src/components/ConfirmationDialog.d.ts +13 -0
  30. package/src/components/ConfirmationDialog.d.ts.map +1 -0
  31. package/src/components/ConfirmationDialog.js +10 -0
  32. package/src/components/CurrencyCodeSelector.d.ts +9 -0
  33. package/src/components/CurrencyCodeSelector.d.ts.map +1 -0
  34. package/src/components/CurrencyCodeSelector.js +31 -0
  35. package/src/components/CurrencyInput.d.ts +13 -0
  36. package/src/components/CurrencyInput.d.ts.map +1 -0
  37. package/src/components/CurrencyInput.js +22 -0
  38. package/src/components/DashboardPage.d.ts +8 -0
  39. package/src/components/DashboardPage.d.ts.map +1 -0
  40. package/src/components/DashboardPage.js +10 -0
  41. package/src/components/DropdownMenu.d.ts +9 -0
  42. package/src/components/DropdownMenu.d.ts.map +1 -0
  43. package/src/components/DropdownMenu.js +56 -0
  44. package/src/components/ExpirationSecondsSelector.d.ts +13 -0
  45. package/src/components/ExpirationSecondsSelector.d.ts.map +1 -0
  46. package/src/components/ExpirationSecondsSelector.js +32 -0
  47. package/src/components/Flag.d.ts +20 -0
  48. package/src/components/Flag.d.ts.map +1 -0
  49. package/src/components/Flag.js +43 -0
  50. package/src/components/ForgotPasswordForm.d.ts +18 -0
  51. package/src/components/ForgotPasswordForm.d.ts.map +1 -0
  52. package/src/components/ForgotPasswordForm.js +54 -0
  53. package/src/components/LoginForm.d.ts +44 -0
  54. package/src/components/LoginForm.d.ts.map +1 -0
  55. package/src/components/LoginForm.js +99 -0
  56. package/src/components/LogoutPage.d.ts +8 -0
  57. package/src/components/LogoutPage.d.ts.map +1 -0
  58. package/src/components/LogoutPage.js +16 -0
  59. package/src/components/RegisterForm.d.ts +54 -0
  60. package/src/components/RegisterForm.d.ts.map +1 -0
  61. package/src/components/RegisterForm.js +105 -0
  62. package/src/components/ResetPasswordForm.d.ts +23 -0
  63. package/src/components/ResetPasswordForm.d.ts.map +1 -0
  64. package/src/components/ResetPasswordForm.js +68 -0
  65. package/src/components/SideMenu.d.ts +8 -0
  66. package/src/components/SideMenu.d.ts.map +1 -0
  67. package/src/components/SideMenu.js +25 -0
  68. package/src/components/SideMenuListItem.d.ts +13 -0
  69. package/src/components/SideMenuListItem.d.ts.map +1 -0
  70. package/src/components/SideMenuListItem.js +44 -0
  71. package/src/components/TopMenu.d.ts +24 -0
  72. package/src/components/TopMenu.d.ts.map +1 -0
  73. package/src/components/TopMenu.js +42 -0
  74. package/src/components/TranslatedTitle.d.ts +7 -0
  75. package/src/components/TranslatedTitle.d.ts.map +1 -0
  76. package/src/components/TranslatedTitle.js +15 -0
  77. package/src/components/UserLanguageSelector.d.ts +4 -0
  78. package/src/components/UserLanguageSelector.d.ts.map +1 -0
  79. package/src/components/UserLanguageSelector.js +31 -0
  80. package/src/components/UserMenu.d.ts +4 -0
  81. package/src/components/UserMenu.d.ts.map +1 -0
  82. package/src/components/UserMenu.js +12 -0
  83. package/src/components/UserSettingsForm.d.ts +56 -0
  84. package/src/components/UserSettingsForm.d.ts.map +1 -0
  85. package/src/components/UserSettingsForm.js +93 -0
  86. package/src/components/VerifyEmailPage.d.ts +23 -0
  87. package/src/components/VerifyEmailPage.d.ts.map +1 -0
  88. package/src/components/VerifyEmailPage.js +61 -0
  89. package/src/components/{index.ts → index.d.ts} +1 -1
  90. package/src/components/index.d.ts.map +1 -0
  91. package/src/components/index.js +28 -0
  92. package/src/contexts/AuthProvider.d.ts +152 -0
  93. package/src/contexts/AuthProvider.d.ts.map +1 -0
  94. package/src/contexts/AuthProvider.js +446 -0
  95. package/src/contexts/I18nProvider.d.ts +16 -0
  96. package/src/contexts/I18nProvider.d.ts.map +1 -0
  97. package/src/contexts/I18nProvider.js +46 -0
  98. package/src/contexts/MenuContext.d.ts +20 -0
  99. package/src/contexts/MenuContext.d.ts.map +1 -0
  100. package/src/contexts/MenuContext.js +244 -0
  101. package/src/contexts/SuiteConfigProvider.d.ts +44 -0
  102. package/src/contexts/SuiteConfigProvider.d.ts.map +1 -0
  103. package/src/contexts/SuiteConfigProvider.js +43 -0
  104. package/src/contexts/ThemeProvider.d.ts +15 -0
  105. package/src/contexts/ThemeProvider.d.ts.map +1 -0
  106. package/src/contexts/ThemeProvider.js +36 -0
  107. package/src/contexts/{index.ts → index.d.ts} +1 -0
  108. package/src/contexts/index.d.ts.map +1 -0
  109. package/src/contexts/index.js +8 -0
  110. package/src/hooks/{index.ts → index.d.ts} +1 -0
  111. package/src/hooks/index.d.ts.map +1 -0
  112. package/src/hooks/index.js +8 -0
  113. package/src/hooks/useBackupCodes.d.ts +15 -0
  114. package/src/hooks/useBackupCodes.d.ts.map +1 -0
  115. package/src/hooks/useBackupCodes.js +70 -0
  116. package/src/hooks/useEmailVerification.d.ts +10 -0
  117. package/src/hooks/useEmailVerification.d.ts.map +1 -0
  118. package/src/hooks/useEmailVerification.js +36 -0
  119. package/src/hooks/useExpiringValue.d.ts +14 -0
  120. package/src/hooks/useExpiringValue.d.ts.map +1 -0
  121. package/src/hooks/useExpiringValue.js +53 -0
  122. package/src/hooks/useLocalStorage.d.ts +2 -0
  123. package/src/hooks/useLocalStorage.d.ts.map +1 -0
  124. package/src/hooks/useLocalStorage.js +15 -0
  125. package/src/hooks/useUserSettings.d.ts +46 -0
  126. package/src/hooks/useUserSettings.d.ts.map +1 -0
  127. package/src/hooks/useUserSettings.js +152 -0
  128. package/src/{index.ts → index.d.ts} +1 -1
  129. package/src/index.d.ts.map +1 -0
  130. package/src/index.js +12 -0
  131. package/src/interfaces/IAppConfig.d.ts +6 -0
  132. package/src/interfaces/IAppConfig.d.ts.map +1 -0
  133. package/src/interfaces/IAppConfig.js +2 -0
  134. package/src/interfaces/IMenuConfig.d.ts +11 -0
  135. package/src/interfaces/IMenuConfig.d.ts.map +1 -0
  136. package/src/interfaces/IMenuConfig.js +2 -0
  137. package/src/interfaces/IMenuOption.d.ts +58 -0
  138. package/src/interfaces/IMenuOption.d.ts.map +1 -0
  139. package/src/interfaces/IMenuOption.js +2 -0
  140. package/src/interfaces/index.d.ts +4 -0
  141. package/src/interfaces/index.d.ts.map +1 -0
  142. package/src/interfaces/index.js +6 -0
  143. package/src/services/__mocks__/authService.d.ts +21 -0
  144. package/src/services/__mocks__/authService.d.ts.map +1 -0
  145. package/src/services/__mocks__/authService.js +15 -0
  146. package/src/services/api.d.ts +3 -0
  147. package/src/services/api.d.ts.map +1 -0
  148. package/src/services/api.js +14 -0
  149. package/src/services/authService.d.ts +72 -0
  150. package/src/services/authService.d.ts.map +1 -0
  151. package/src/services/authService.js +347 -0
  152. package/src/services/authenticatedApi.d.ts +3 -0
  153. package/src/services/authenticatedApi.d.ts.map +1 -0
  154. package/src/services/authenticatedApi.js +18 -0
  155. package/src/services/index.d.ts +4 -0
  156. package/src/services/index.d.ts.map +1 -0
  157. package/src/services/index.js +6 -0
  158. package/src/types/MenuType.d.ts +11 -0
  159. package/src/types/MenuType.d.ts.map +1 -0
  160. package/src/types/MenuType.js +12 -0
  161. package/src/types/expirationSeconds.d.ts +3 -0
  162. package/src/types/expirationSeconds.d.ts.map +1 -0
  163. package/src/types/expirationSeconds.js +17 -0
  164. package/src/types/index.d.ts +2 -0
  165. package/src/types/index.d.ts.map +1 -0
  166. package/src/types/index.js +4 -0
  167. package/src/types/translation.d.ts +10 -0
  168. package/src/types/translation.d.ts.map +1 -0
  169. package/src/types/translation.js +9 -0
  170. package/src/wrappers/BackupCodeLoginWrapper.d.ts +8 -0
  171. package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +1 -0
  172. package/src/wrappers/BackupCodeLoginWrapper.js +21 -0
  173. package/src/wrappers/BackupCodesWrapper.d.ts +7 -0
  174. package/src/wrappers/BackupCodesWrapper.d.ts.map +1 -0
  175. package/src/wrappers/BackupCodesWrapper.js +17 -0
  176. package/src/wrappers/ChangePasswordFormWrapper.d.ts +8 -0
  177. package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +1 -0
  178. package/src/wrappers/ChangePasswordFormWrapper.js +21 -0
  179. package/src/wrappers/LoginFormWrapper.d.ts +9 -0
  180. package/src/wrappers/LoginFormWrapper.d.ts.map +1 -0
  181. package/src/wrappers/LoginFormWrapper.js +43 -0
  182. package/src/wrappers/LogoutPageWrapper.d.ts +9 -0
  183. package/src/wrappers/LogoutPageWrapper.d.ts.map +1 -0
  184. package/src/wrappers/LogoutPageWrapper.js +21 -0
  185. package/src/wrappers/RegisterFormWrapper.d.ts +9 -0
  186. package/src/wrappers/RegisterFormWrapper.d.ts.map +1 -0
  187. package/src/wrappers/RegisterFormWrapper.js +26 -0
  188. package/src/wrappers/UserSettingsFormWrapper.d.ts +8 -0
  189. package/src/wrappers/UserSettingsFormWrapper.d.ts.map +1 -0
  190. package/src/wrappers/UserSettingsFormWrapper.js +24 -0
  191. package/src/wrappers/VerifyEmailPageWrapper.d.ts +8 -0
  192. package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +1 -0
  193. package/src/wrappers/VerifyEmailPageWrapper.js +20 -0
  194. package/src/wrappers/{index.tsx → index.d.ts} +1 -8
  195. package/src/wrappers/index.d.ts.map +1 -0
  196. package/src/wrappers/index.js +20 -0
  197. package/LICENSE +0 -21
  198. package/src/auth/Private.tsx +0 -17
  199. package/src/auth/PrivateRoute.tsx +0 -28
  200. package/src/auth/UnAuth.tsx +0 -16
  201. package/src/auth/UnAuthRoute.tsx +0 -30
  202. package/src/components/ApiAccess.tsx +0 -134
  203. package/src/components/BackupCodeLoginForm.tsx +0 -314
  204. package/src/components/BackupCodesForm.tsx +0 -198
  205. package/src/components/ChangePasswordForm.tsx +0 -182
  206. package/src/components/ConfirmationDialog.tsx +0 -48
  207. package/src/components/CurrencyCodeSelector.tsx +0 -60
  208. package/src/components/CurrencyInput.tsx +0 -80
  209. package/src/components/DashboardPage.tsx +0 -24
  210. package/src/components/DropdownMenu.tsx +0 -92
  211. package/src/components/ExpirationSecondsSelector.tsx +0 -65
  212. package/src/components/Flag.tsx +0 -53
  213. package/src/components/ForgotPasswordForm.tsx +0 -120
  214. package/src/components/LoginForm.tsx +0 -307
  215. package/src/components/LogoutPage.tsx +0 -21
  216. package/src/components/RegisterForm.tsx +0 -354
  217. package/src/components/ResetPasswordForm.tsx +0 -164
  218. package/src/components/SideMenu.tsx +0 -46
  219. package/src/components/SideMenuListItem.tsx +0 -74
  220. package/src/components/TopMenu.tsx +0 -149
  221. package/src/components/TranslatedTitle.tsx +0 -22
  222. package/src/components/UserLanguageSelector.tsx +0 -45
  223. package/src/components/UserMenu.tsx +0 -15
  224. package/src/components/UserSettingsForm.tsx +0 -328
  225. package/src/components/VerifyEmailPage.tsx +0 -133
  226. package/src/contexts/AuthProvider.spec.tsx +0 -1060
  227. package/src/contexts/AuthProvider.tsx +0 -741
  228. package/src/contexts/I18nProvider.tsx +0 -85
  229. package/src/contexts/MenuContext.tsx +0 -310
  230. package/src/contexts/SuiteConfigProvider.tsx +0 -93
  231. package/src/contexts/ThemeProvider.tsx +0 -67
  232. package/src/hooks/useBackupCodes.ts +0 -85
  233. package/src/hooks/useEmailVerification.ts +0 -39
  234. package/src/hooks/useExpiringValue.ts +0 -78
  235. package/src/hooks/useLocalStorage.ts +0 -18
  236. package/src/hooks/useUserSettings.ts +0 -216
  237. package/src/interfaces/IAppConfig.ts +0 -5
  238. package/src/interfaces/IMenuConfig.ts +0 -11
  239. package/src/interfaces/IMenuOption.ts +0 -55
  240. package/src/interfaces/index.ts +0 -3
  241. package/src/services/__mocks__/authService.ts +0 -14
  242. package/src/services/api.ts +0 -13
  243. package/src/services/authService.ts +0 -422
  244. package/src/services/authenticatedApi.ts +0 -17
  245. package/src/services/index.ts +0 -3
  246. package/src/types/MenuType.ts +0 -15
  247. package/src/types/expirationSeconds.ts +0 -18
  248. package/src/types/index.ts +0 -1
  249. package/src/types/translation.ts +0 -20
  250. package/src/wrappers/BackupCodeLoginWrapper.tsx +0 -35
  251. package/src/wrappers/BackupCodesWrapper.tsx +0 -28
  252. package/src/wrappers/ChangePasswordFormWrapper.tsx +0 -31
  253. package/src/wrappers/LoginFormWrapper.tsx +0 -59
  254. package/src/wrappers/LogoutPageWrapper.tsx +0 -30
  255. package/src/wrappers/RegisterFormWrapper.tsx +0 -48
  256. package/src/wrappers/UserSettingsFormWrapper.tsx +0 -39
  257. package/src/wrappers/VerifyEmailPageWrapper.tsx +0 -27
@@ -1,85 +0,0 @@
1
- import {
2
- GlobalActiveContext,
3
- IActiveContext,
4
- LanguageRegistry,
5
- I18nEngine,
6
- CoreLanguageCode,
7
- } from '@digitaldefiance/i18n-lib';
8
- import { createContext, FC, ReactNode, useCallback, useContext, useState } from 'react';
9
-
10
- export interface I18nProviderProps {
11
- children: ReactNode;
12
- i18nEngine: I18nEngine;
13
- onLanguageChange?: (language: string) => Promise<void>;
14
- }
15
-
16
- export interface I18nContextType {
17
- t: (key: string, vars?: Record<string, string | number>, language?: string) => string;
18
- tComponent: <TStringKey extends string>(componentId: string, stringKey: TStringKey, vars?: Record<string, string | number>, language?: string) => string;
19
- changeLanguage: (language: string) => void;
20
- currentLanguage: string;
21
- }
22
-
23
- const I18nContext = createContext<I18nContextType | undefined>(undefined);
24
-
25
- export const I18nProvider: FC<I18nProviderProps> = ({
26
- children,
27
- i18nEngine,
28
- onLanguageChange,
29
- }) => {
30
- const context = GlobalActiveContext.getInstance<
31
- string,
32
- IActiveContext<string>
33
- >();
34
- const [currentLanguage, setCurrentLanguage] = useState<string>(
35
- context.userLanguage
36
- );
37
-
38
- const changeLanguage = useCallback(
39
- async (language: string) => {
40
- const languageDetails = LanguageRegistry.getLanguageByCode(language);
41
- if (language && languageDetails) {
42
- context.userLanguage = language;
43
- i18nEngine.setLanguage(language);
44
- localStorage.setItem('language', languageDetails.name);
45
- localStorage.setItem('languageCode', language);
46
- setCurrentLanguage(language);
47
- if (onLanguageChange) {
48
- await onLanguageChange(language);
49
- }
50
- }
51
- },
52
- [onLanguageChange, i18nEngine, context]
53
- );
54
-
55
- const t = useCallback(
56
- (key: string, vars?: Record<string, string | number>, language?: string) => {
57
- return i18nEngine.t(key, vars, language ?? currentLanguage);
58
- },
59
- [i18nEngine, currentLanguage]
60
- );
61
-
62
- const tComponent = useCallback(
63
- <TStringKey extends string>(componentId: string, stringKey: TStringKey, vars?: Record<string, string | number>, language?: string): string => {
64
- return i18nEngine.translate(componentId, stringKey, vars, language ?? currentLanguage);
65
- },
66
- [currentLanguage, i18nEngine]
67
- );
68
-
69
- const value = {
70
- t,
71
- tComponent,
72
- changeLanguage,
73
- currentLanguage,
74
- };
75
-
76
- return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
77
- };
78
-
79
- export const useI18n = () => {
80
- const context = useContext(I18nContext);
81
- if (context === undefined) {
82
- throw new Error('useI18n must be used within an I18nProvider');
83
- }
84
- return context;
85
- };
@@ -1,310 +0,0 @@
1
- // src/app/menuContext.tsx
2
- import { IRoleDTO, SuiteCoreComponentId } from '@digitaldefiance/suite-core-lib';
3
- import { SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
4
- import {
5
- AccountCircle,
6
- Autorenew as AutorenewIcon,
7
- Brightness4,
8
- Brightness7,
9
- Dashboard as DashboardIcon,
10
- Key as KeyIcon,
11
- LockOpen as LockOpenIcon,
12
- LockReset as LockResetIcon,
13
- Login as LoginIcon,
14
- ExitToApp as LogoutIcon,
15
- PersonAdd as PersonAddIcon,
16
- Settings,
17
- } from '@mui/icons-material';
18
- import {
19
- FC,
20
- ReactNode,
21
- createContext,
22
- useCallback,
23
- useContext,
24
- useEffect,
25
- useMemo,
26
- useRef,
27
- useState,
28
- } from 'react';
29
- import { useAuth } from './AuthProvider';
30
- import { useTheme } from './ThemeProvider';
31
- import { MenuType, MenuTypes } from '../types/MenuType';
32
- import { useI18n } from './I18nProvider';
33
- import { IMenuOption } from '../interfaces/IMenuOption';
34
- import { IMenuConfig } from '../interfaces/IMenuConfig';
35
- import { useUserSettings } from '../hooks';
36
- import { useSuiteConfig } from './SuiteConfigProvider';
37
- import { createAuthenticatedApiClient } from '../services';
38
-
39
- interface MenuProviderProps {
40
- children: ReactNode;
41
- menuConfigs?: IMenuConfig[];
42
- enableBackupCodes?: boolean;
43
- }
44
-
45
- interface MenuContextType {
46
- menuOptions: IMenuOption[];
47
- getMenuOptions: (
48
- menuType: MenuType,
49
- includeDividers: boolean,
50
- ) => IMenuOption[];
51
- registerMenuOption: (option: IMenuOption) => () => void;
52
- registerMenuOptions: (options: IMenuOption[]) => () => void;
53
- getTopMenus: () => Array<IMenuConfig>;
54
- }
55
-
56
- const MenuContext = createContext<MenuContextType | undefined>(undefined);
57
-
58
- export const MenuProvider: FC<MenuProviderProps> = ({ children, menuConfigs = [], enableBackupCodes = true }) => {
59
- const { userData: user, isAuthenticated, mnemonic, clearMnemonic, wallet, clearWallet } = useAuth();
60
- const { mode: colorMode } = useTheme();
61
- const registeredMenuOptions = useRef(new Set<() => void>());
62
- const [registeredOptions, setRegisteredOptions] = useState<
63
- Map<string, IMenuOption>
64
- >(new Map<string, IMenuOption>());
65
- const { tComponent } = useI18n();
66
- const { baseUrl } = useSuiteConfig();
67
- const authenticatedApi = useMemo(() => createAuthenticatedApiClient(baseUrl), [baseUrl]);
68
- const { toggleColorMode } = useUserSettings({ authenticatedApi, isAuthenticated });
69
-
70
- const registerMenuOption = useCallback((option: IMenuOption) => {
71
- const unregister = () => {
72
- setRegisteredOptions((prev) => {
73
- const newMap = new Map(prev);
74
- newMap.delete(option.id);
75
- return newMap;
76
- });
77
- registeredMenuOptions.current.delete(unregister);
78
- };
79
-
80
- setRegisteredOptions((prev) => {
81
- const newMap = new Map(prev);
82
- newMap.set(option.id, option);
83
- return newMap;
84
- });
85
- registeredMenuOptions.current.add(unregister);
86
-
87
- return unregister;
88
- }, []);
89
-
90
- const registerMenuOptions = useCallback(
91
- (options: IMenuOption[]) => {
92
- const unregisterFunctions = options.map(registerMenuOption);
93
- return () => unregisterFunctions.forEach((f) => f());
94
- },
95
- [registerMenuOption],
96
- );
97
-
98
- const menuOptions = useMemo(() => {
99
- const isUserRestricted = () => {
100
- return user?.roles?.some((role: IRoleDTO) => role.child) ?? false;
101
- };
102
- let index = 0;
103
- const baseOptions: IMenuOption[] = [
104
- {
105
- id: 'dashboard',
106
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_Dashboard),
107
- icon: <DashboardIcon />,
108
- link: '/dashboard',
109
- requiresAuth: true,
110
- includeOnMenus: [MenuTypes.SideMenu],
111
- index: index++,
112
- },
113
- {
114
- id: 'user-divider',
115
- label: '',
116
- divider: true,
117
- includeOnMenus: [MenuTypes.SideMenu],
118
- index: index++,
119
- requiresAuth: false,
120
- },
121
- {
122
- id: 'logout',
123
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.LogoutButton),
124
- icon: <LogoutIcon />,
125
- link: '/logout',
126
- requiresAuth: true,
127
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
128
- index: index++,
129
- },
130
- {
131
- id: 'login',
132
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Login_LoginButton),
133
- icon: <LoginIcon />,
134
- link: '/login',
135
- requiresAuth: false,
136
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
137
- index: index++,
138
- },
139
- {
140
- id: 'register',
141
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.RegisterButton),
142
- icon: <PersonAddIcon />,
143
- link: '/register',
144
- requiresAuth: false,
145
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
146
- index: index++,
147
- },
148
- {
149
- id: 'forgot-password',
150
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.ForgotPassword_Title),
151
- icon: <LockOpenIcon />,
152
- link: '/forgot-password',
153
- requiresAuth: false,
154
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
155
- index: index++,
156
- },
157
- {
158
- id: 'change-password',
159
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_ChangePassword),
160
- icon: <LockResetIcon />,
161
- link: '/change-password',
162
- requiresAuth: true,
163
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
164
- index: index++,
165
- },
166
- ...(enableBackupCodes ? [{
167
- id: 'backup-code',
168
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.BackupCodeRecovery_Title),
169
- icon: <KeyIcon />,
170
- link: '/backup-code',
171
- requiresAuth: false,
172
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
173
- index: index++,
174
- },
175
- {
176
- id: 'backup-codes',
177
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.BackupCodeRecovery_GenerateNewCodes),
178
- icon: <AutorenewIcon />,
179
- link: '/backup-codes',
180
- requiresAuth: true,
181
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
182
- index: index++,
183
- }] : []),
184
- {
185
- id: 'divider',
186
- label: '',
187
- divider: true,
188
- includeOnMenus: [MenuTypes.SideMenu],
189
- index: index++,
190
- requiresAuth: false,
191
- },
192
- {
193
- id: 'clear-mnemonic',
194
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_ClearMnemonic),
195
- action: clearMnemonic,
196
- icon: <KeyIcon />,
197
- requiresAuth: true,
198
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
199
- index: index++,
200
- filter: () => !!mnemonic,
201
- },
202
- {
203
- id: 'clear-wallet',
204
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_ClearWallet),
205
- action: clearWallet,
206
- icon: <KeyIcon />,
207
- requiresAuth: true,
208
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
209
- index: index++,
210
- filter: () => !!wallet,
211
- },
212
- ...(isUserRestricted() ? [] : []),
213
- {
214
- id: 'color-divider',
215
- label: '',
216
- divider: true,
217
- includeOnMenus: [MenuTypes.SideMenu],
218
- index: index++,
219
- requiresAuth: undefined,
220
- },
221
- {
222
- id: 'theme-toggle',
223
- label:
224
- colorMode === 'dark'
225
- ? tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_ThemeToggle_Light)
226
- : tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_ThemeToggle_Dark),
227
- icon: colorMode === 'dark' ? <Brightness7 /> : <Brightness4 />,
228
- includeOnMenus: [MenuTypes.SideMenu],
229
- index: index++,
230
- requiresAuth: undefined,
231
- action: toggleColorMode,
232
- },
233
- {
234
- id: 'user-settings',
235
- label: tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Title),
236
- icon: <Settings />,
237
- link: '/user-settings',
238
- requiresAuth: true,
239
- includeOnMenus: [MenuTypes.UserMenu, MenuTypes.SideMenu],
240
- index: index++,
241
- }
242
- ];
243
-
244
- const allOptions = [...baseOptions, ...registeredOptions.values()];
245
- return allOptions.sort((a, b) => a.index - b.index);
246
- }, [tComponent, registeredOptions, user?.roles, colorMode, toggleColorMode, clearMnemonic, clearWallet, mnemonic, wallet]);
247
-
248
- const getMenuOptions = useCallback(
249
- (menuType: MenuType, includeDividers: boolean) => {
250
- const MenuFilter = (o: IMenuOption) => {
251
- // Apply the custom filter first
252
- let customFilterPasses = true;
253
- if (o.filter !== undefined) {
254
- customFilterPasses = o.filter(o);
255
- }
256
- if (!customFilterPasses) return false;
257
-
258
- if (o.divider === true && !includeDividers) return false;
259
-
260
- return (
261
- o.includeOnMenus.includes(menuType) &&
262
- (o.requiresAuth === undefined || o.requiresAuth === isAuthenticated)
263
- );
264
- };
265
-
266
- return menuOptions.filter(MenuFilter);
267
- },
268
- [isAuthenticated, menuOptions],
269
- );
270
-
271
- useEffect(() => {
272
- if (menuConfigs.length > 0) {
273
- return registerMenuOptions(menuConfigs.flatMap(config => config.options));
274
- }
275
- return undefined;
276
- }, [menuConfigs, registerMenuOptions]);
277
-
278
- const getTopMenus = useCallback(() => {
279
- const menus: Array<IMenuConfig & { isUserMenu?: boolean }> = [
280
- ...menuConfigs.map(config => ({ ...config, isUserMenu: false })),
281
- { menuType: MenuTypes.UserMenu, menuIcon: <AccountCircle />, priority: 0, options: [], isUserMenu: true }
282
- ];
283
- return menus.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
284
- }, [menuConfigs]);
285
-
286
- const contextValue = useMemo(() => {
287
- return {
288
- menuOptions: menuOptions,
289
- getMenuOptions: getMenuOptions,
290
- registerMenuOption: registerMenuOption,
291
- registerMenuOptions: registerMenuOptions,
292
- getTopMenus: getTopMenus,
293
- };
294
- }, [menuOptions, getMenuOptions, registerMenuOption, registerMenuOptions, getTopMenus]);
295
-
296
- const memoizedChildren = useMemo(() => children, [children]);
297
- return (
298
- <MenuContext.Provider value={contextValue}>
299
- {memoizedChildren}
300
- </MenuContext.Provider>
301
- );
302
- };
303
-
304
- export const useMenu = (): MenuContextType => {
305
- const context = useContext(MenuContext);
306
- if (context === undefined) {
307
- throw new Error('useMenu must be used within a MenuProvider');
308
- }
309
- return context;
310
- };
@@ -1,93 +0,0 @@
1
- import { createContext, ReactNode, useContext } from 'react';
2
-
3
- export interface SuiteConfigRoutes {
4
- dashboard?: string;
5
- login?: string;
6
- register?: string;
7
- verifyEmail?: string;
8
- forgotPassword?: string;
9
- resetPassword?: string;
10
- settings?: string;
11
- }
12
-
13
- export interface SuiteConfigContextData {
14
- /**
15
- * Base URL for API calls
16
- */
17
- baseUrl: string;
18
-
19
- /**
20
- * Application routes for navigation
21
- */
22
- routes: SuiteConfigRoutes;
23
-
24
- /**
25
- * Available languages for the application
26
- */
27
- languages: Array<{ code: string; label: string }>;
28
-
29
- /**
30
- * Available timezones
31
- */
32
- timezones?: string[];
33
- }
34
-
35
- const defaultRoutes: SuiteConfigRoutes = {
36
- dashboard: '/dashboard',
37
- login: '/login',
38
- register: '/register',
39
- verifyEmail: '/verify-email',
40
- forgotPassword: '/forgot-password',
41
- resetPassword: '/reset-password',
42
- settings: '/settings',
43
- };
44
-
45
- const defaultLanguages = [
46
- { code: 'en-US', label: 'English (US)' },
47
- { code: 'en-GB', label: 'English (UK)' },
48
- { code: 'es-ES', label: 'Español' },
49
- { code: 'fr-FR', label: 'Français' },
50
- { code: 'de-DE', label: 'Deutsch' },
51
- { code: 'ja', label: '日本語' },
52
- { code: 'zh-CN', label: '中文 (简体)' },
53
- { code: 'uk', label: 'Українська' },
54
- ];
55
-
56
- const SuiteConfigContext = createContext<SuiteConfigContextData | undefined>(undefined);
57
-
58
- export interface SuiteConfigProviderProps {
59
- children: ReactNode;
60
- baseUrl: string;
61
- routes?: Partial<SuiteConfigRoutes>;
62
- languages?: Array<{ code: string; label: string }>;
63
- timezones?: string[];
64
- }
65
-
66
- export const SuiteConfigProvider = ({
67
- children,
68
- baseUrl,
69
- routes = {},
70
- languages = defaultLanguages,
71
- timezones,
72
- }: SuiteConfigProviderProps) => {
73
- const value: SuiteConfigContextData = {
74
- baseUrl,
75
- routes: { ...defaultRoutes, ...routes },
76
- languages,
77
- timezones,
78
- };
79
-
80
- return (
81
- <SuiteConfigContext.Provider value={value}>
82
- {children}
83
- </SuiteConfigContext.Provider>
84
- );
85
- };
86
-
87
- export const useSuiteConfig = (): SuiteConfigContextData => {
88
- const context = useContext(SuiteConfigContext);
89
- if (!context) {
90
- throw new Error('useSuiteConfig must be used within a SuiteConfigProvider');
91
- }
92
- return context;
93
- };
@@ -1,67 +0,0 @@
1
- import { Brightness4, Brightness7 } from '@mui/icons-material';
2
- import {
3
- IconButton,
4
- ThemeProvider as MuiThemeProvider,
5
- PaletteMode,
6
- createTheme,
7
- Theme,
8
- } from '@mui/material';
9
- import { FC, ReactNode, createContext, useContext, useMemo, useState } from 'react';
10
-
11
- export interface ThemeContextType {
12
- toggleColorMode: () => void;
13
- setColorMode: (mode: PaletteMode) => void;
14
- mode: PaletteMode;
15
- }
16
-
17
- const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
18
-
19
- export const useTheme = () => {
20
- const context = useContext(ThemeContext);
21
- if (!context) {
22
- throw new Error('useTheme must be used within an AppThemeProvider');
23
- }
24
- return context;
25
- };
26
-
27
- export interface AppThemeProviderProps {
28
- children: ReactNode;
29
- customTheme?: (mode: PaletteMode) => Theme;
30
- }
31
-
32
- export const AppThemeProvider: FC<AppThemeProviderProps> = ({ children, customTheme }) => {
33
- const [mode, setMode] = useState<PaletteMode>('light');
34
-
35
- const colorMode = useMemo(
36
- () => ({
37
- toggleColorMode: () => {
38
- setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
39
- },
40
- setColorMode: (newMode: PaletteMode) => {
41
- setMode(newMode);
42
- },
43
- mode,
44
- }),
45
- [mode]
46
- );
47
-
48
- const theme = useMemo(
49
- () => (customTheme ? customTheme(mode) : createTheme({ palette: { mode } })),
50
- [mode, customTheme]
51
- );
52
-
53
- return (
54
- <ThemeContext.Provider value={colorMode}>
55
- <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
56
- </ThemeContext.Provider>
57
- );
58
- };
59
-
60
- export const ThemeToggleButton: FC = () => {
61
- const { mode, toggleColorMode } = useTheme();
62
- return (
63
- <IconButton onClick={toggleColorMode} color="inherit">
64
- {mode === 'dark' ? <Brightness7 /> : <Brightness4 />}
65
- </IconButton>
66
- );
67
- };
@@ -1,85 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import { createAuthenticatedApiClient } from '../services';
3
- import { useSuiteConfig } from '../contexts';
4
- import { SuiteCoreStringKey, TranslatableSuiteError } from '@digitaldefiance/suite-core-lib';
5
-
6
- export interface UseBackupCodesOptions {
7
- initialCodeCount?: number | null;
8
- }
9
-
10
- export interface UseBackupCodesResult {
11
- backupCodesRemaining: number | null;
12
- isLoading: boolean;
13
- error: Error | null;
14
- generateBackupCodes: (password?: string, mnemonic?: string) => Promise<{
15
- message: string;
16
- backupCodes: string[];
17
- }>;
18
- refreshCodeCount: () => Promise<void>;
19
- }
20
-
21
- export const useBackupCodes = (
22
- options: UseBackupCodesOptions = {}
23
- ): UseBackupCodesResult => {
24
- const { baseUrl } = useSuiteConfig();
25
- const [backupCodesRemaining, setBackupCodesRemaining] = useState<number | null>(
26
- options.initialCodeCount ?? null
27
- );
28
- const [isLoading, setIsLoading] = useState(false);
29
- const [error, setError] = useState<Error | null>(null);
30
- const requestedOnMountRef = useRef(false);
31
- const api = useMemo(() => createAuthenticatedApiClient(baseUrl), [baseUrl]);
32
-
33
- const refreshCodeCount = useCallback(async () => {
34
- setIsLoading(true);
35
- setError(null);
36
- try {
37
- const result = await api.get('/user/backup-codes');
38
- if (result?.data?.codeCount !== undefined) {
39
- setBackupCodesRemaining(result.data.codeCount);
40
- }
41
- } catch (err) {
42
- setError(err instanceof Error ? err : new TranslatableSuiteError(SuiteCoreStringKey.BackupCodes_FailedToFetch));
43
- setBackupCodesRemaining(0);
44
- } finally {
45
- setIsLoading(false);
46
- }
47
- }, [api]);
48
-
49
- useEffect(() => {
50
- if (requestedOnMountRef.current) return;
51
- if (backupCodesRemaining !== null) return;
52
-
53
- requestedOnMountRef.current = true;
54
- refreshCodeCount();
55
- }, [backupCodesRemaining, refreshCodeCount]);
56
-
57
- const generateBackupCodes = async (password?: string, mnemonic?: string) => {
58
- setIsLoading(true);
59
- setError(null);
60
- try {
61
- const result = await api.post('/user/backup-codes', {
62
- ...(password ? { password } : {}),
63
- ...(mnemonic ? { mnemonic } : {}),
64
- });
65
- return {
66
- message: result.data.message,
67
- backupCodes: result.data.backupCodes,
68
- };
69
- } catch (err) {
70
- const error = err instanceof Error ? err : new TranslatableSuiteError(SuiteCoreStringKey.BackupCodes_FailedToGenerate);
71
- setError(error);
72
- throw error;
73
- } finally {
74
- setIsLoading(false);
75
- }
76
- };
77
-
78
- return {
79
- backupCodesRemaining,
80
- isLoading,
81
- error,
82
- generateBackupCodes,
83
- refreshCodeCount,
84
- };
85
- };
@@ -1,39 +0,0 @@
1
- import { useMemo, useState } from 'react';
2
- import { createAuthenticatedApiClient } from '../services';
3
- import { useSuiteConfig } from '../contexts';
4
- import { getSuiteCoreTranslation, SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
5
-
6
- export interface UseEmailVerificationResult {
7
- isVerifying: boolean;
8
- error: Error | null;
9
- verifyEmail: (token: string) => Promise<{ success: boolean; message?: string }>;
10
- }
11
-
12
- export const useEmailVerification = (): UseEmailVerificationResult => {
13
- const { baseUrl } = useSuiteConfig();
14
- const api = useMemo(() => createAuthenticatedApiClient(baseUrl), [baseUrl]);
15
- const [isVerifying, setIsVerifying] = useState(false);
16
- const [error, setError] = useState<Error | null>(null);
17
-
18
- const verifyEmail = async (verificationToken: string) => {
19
- setIsVerifying(true);
20
- setError(null);
21
- try {
22
- const result = await api.post('/verify-email', { token: verificationToken });
23
- return { success: true, message: result.data.message };
24
- } catch (err: any) {
25
- const errorMessage = err.response?.data?.message || getSuiteCoreTranslation(SuiteCoreStringKey.Error_VerificationFailed);
26
- const error = new Error(errorMessage);
27
- setError(error);
28
- return { success: false, message: errorMessage };
29
- } finally {
30
- setIsVerifying(false);
31
- }
32
- };
33
-
34
- return {
35
- isVerifying,
36
- error,
37
- verifyEmail,
38
- };
39
- };