@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,328 +0,0 @@
1
- import {
2
- Alert,
3
- Box,
4
- Button,
5
- Container,
6
- FormControl,
7
- FormControlLabel,
8
- InputLabel,
9
- MenuItem,
10
- Select,
11
- Switch,
12
- TextField,
13
- Typography,
14
- } from '@mui/material';
15
- import { useFormik } from 'formik';
16
- import { FC, useState, useMemo } from 'react';
17
- import * as Yup from 'yup';
18
- import moment from 'moment-timezone';
19
- import { CurrencyCode } from '@digitaldefiance/i18n-lib';
20
- import { SuiteCoreComponentId, SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
21
- import { useI18n } from '../contexts';
22
-
23
- export interface UserSettingsFormValues {
24
- email: string;
25
- timezone: string;
26
- siteLanguage: string;
27
- currency: string;
28
- darkMode: boolean;
29
- directChallenge: boolean;
30
- [key: string]: any;
31
- }
32
-
33
- export interface UserSettingsFormProps {
34
- initialValues: UserSettingsFormValues;
35
- onSubmit: (values: UserSettingsFormValues) => Promise<
36
- | { success: boolean; message: string }
37
- | { error: string; errorType?: string; field?: string; errors?: Array<{ path: string; msg: string }> }
38
- >;
39
- languages: Array<{ code: string; label: string }>;
40
- emailValidation?: Yup.StringSchema;
41
- timezoneValidation?: Yup.StringSchema;
42
- siteLanguageValidation?: Yup.StringSchema;
43
- currencyValidation?: Yup.StringSchema;
44
- darkModeValidation?: Yup.BooleanSchema;
45
- directChallengeValidation?: Yup.BooleanSchema;
46
- additionalFields?: (formik: any) => React.ReactNode;
47
- additionalInitialValues?: Record<string, any>;
48
- additionalValidation?: Record<string, Yup.Schema>;
49
- labels?: {
50
- title?: string;
51
- email?: string;
52
- emailHelper?: string;
53
- timezone?: string;
54
- siteLanguage?: string;
55
- currency?: string;
56
- darkMode?: string;
57
- directChallenge?: string;
58
- directChallengeHelper?: string;
59
- saving?: string;
60
- save?: string;
61
- successMessage?: string;
62
- };
63
- }
64
-
65
- export const UserSettingsForm: FC<UserSettingsFormProps> = ({
66
- initialValues,
67
- onSubmit,
68
- languages,
69
- emailValidation,
70
- timezoneValidation,
71
- siteLanguageValidation,
72
- currencyValidation,
73
- darkModeValidation,
74
- directChallengeValidation,
75
- additionalFields,
76
- additionalInitialValues = {},
77
- additionalValidation = {},
78
- labels = {},
79
- }) => {
80
- const { tComponent } = useI18n();
81
- const [apiErrors, setApiErrors] = useState<Record<string, string>>({});
82
- const [saving, setSaving] = useState(false);
83
- const [successMessage, setSuccessMessage] = useState<string | null>(null);
84
-
85
- const timezones = useMemo(() => moment.tz.names(), []);
86
- const currencies = useMemo(() => CurrencyCode.getAllData().map(c => ({ code: c.code, label: `${c.code} - ${c.currency}` })), []);
87
-
88
- const validation = {
89
- email: emailValidation || Yup.string()
90
- .email(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_InvalidEmail))
91
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required)),
92
- timezone: timezoneValidation || Yup.string()
93
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_TimezoneRequired))
94
- .test('valid-timezone', tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_TimezoneInvalid), (value) => !value || moment.tz.zone(value) !== null),
95
- siteLanguage: siteLanguageValidation || Yup.string()
96
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required)),
97
- currency: currencyValidation || Yup.string()
98
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required))
99
- .test('valid-currency', tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required), (value) => !value || CurrencyCode.isValid(value)),
100
- darkMode: darkModeValidation || Yup.boolean()
101
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required)),
102
- directChallenge: directChallengeValidation || Yup.boolean()
103
- .required(tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Validation_Required)),
104
- };
105
-
106
- const formik = useFormik<UserSettingsFormValues>({
107
- initialValues: {
108
- ...initialValues,
109
- ...additionalInitialValues,
110
- },
111
- enableReinitialize: true,
112
- validationSchema: Yup.object({
113
- email: validation.email,
114
- timezone: validation.timezone,
115
- siteLanguage: validation.siteLanguage,
116
- currency: validation.currency,
117
- darkMode: validation.darkMode,
118
- directChallenge: validation.directChallenge,
119
- ...additionalValidation,
120
- }),
121
- onSubmit: async (values, { setSubmitting, setFieldError, setTouched }) => {
122
- setSaving(true);
123
- setSuccessMessage(null);
124
- const result = await onSubmit(values);
125
-
126
- if ('success' in result && result.success) {
127
- setSuccessMessage(result.message || labels.successMessage || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_SaveSuccess));
128
- setApiErrors({});
129
- } else {
130
- const newApiErrors: Record<string, string> = {};
131
- const fieldsToTouch: Record<string, boolean> = {};
132
-
133
- if ('field' in result && result.field) {
134
- setFieldError(result.field, result.error);
135
- fieldsToTouch[result.field] = true;
136
- }
137
-
138
- if ('errors' in result && result.errors) {
139
- result.errors.forEach((err) => {
140
- if (err.path && err.msg) {
141
- setFieldError(err.path, err.msg);
142
- fieldsToTouch[err.path] = true;
143
- }
144
- });
145
- }
146
-
147
- if ('error' in result && result.error && !Object.keys(newApiErrors).length) {
148
- newApiErrors.general = result.error;
149
- }
150
-
151
- setApiErrors(newApiErrors);
152
- setTouched(fieldsToTouch, false);
153
- }
154
- setSubmitting(false);
155
- setSaving(false);
156
- },
157
- });
158
-
159
- return (
160
- <Container maxWidth="sm">
161
- <Box sx={{ mt: 4, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
162
- <Typography variant="h4" component="h1" gutterBottom>
163
- {labels.title || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Title)}
164
- </Typography>
165
-
166
- <Box component="form" onSubmit={formik.handleSubmit} sx={{ mt: 1, width: '100%' }}>
167
- <TextField
168
- fullWidth
169
- id="email"
170
- name="email"
171
- label={labels.email || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_Email)}
172
- value={formik.values.email}
173
- onChange={formik.handleChange}
174
- onBlur={formik.handleBlur}
175
- error={Boolean(formik.touched.email && (formik.errors.email || apiErrors.email))}
176
- helperText={
177
- (formik.touched.email && (formik.errors.email || apiErrors.email)) ||
178
- labels.emailHelper ||
179
- tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_EmailHelper)
180
- }
181
- margin="normal"
182
- />
183
-
184
- <FormControl fullWidth margin="normal">
185
- <InputLabel id="timezone-label">
186
- {labels.timezone || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_Timezone)}
187
- </InputLabel>
188
- <Select
189
- labelId="timezone-label"
190
- id="timezone"
191
- name="timezone"
192
- value={formik.values.timezone}
193
- onChange={formik.handleChange}
194
- onBlur={formik.handleBlur}
195
- error={formik.touched.timezone && Boolean(formik.errors.timezone)}
196
- label={labels.timezone || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_Timezone)}
197
- >
198
- {timezones.map((tz) => (
199
- <MenuItem key={tz} value={tz}>
200
- {tz}
201
- </MenuItem>
202
- ))}
203
- </Select>
204
- {formik.touched.timezone && (formik.errors.timezone || apiErrors.timezone) && (
205
- <Typography color="error" variant="caption">
206
- {formik.errors.timezone || apiErrors.timezone}
207
- </Typography>
208
- )}
209
- </FormControl>
210
-
211
- <FormControl fullWidth margin="normal">
212
- <InputLabel id="language-label">
213
- {labels.siteLanguage || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_SiteLanguage)}
214
- </InputLabel>
215
- <Select
216
- labelId="language-label"
217
- id="siteLanguage"
218
- name="siteLanguage"
219
- value={formik.values.siteLanguage}
220
- onChange={formik.handleChange}
221
- onBlur={formik.handleBlur}
222
- error={formik.touched.siteLanguage && Boolean(formik.errors.siteLanguage)}
223
- label={labels.siteLanguage || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_SiteLanguage)}
224
- >
225
- {languages.map((lang) => (
226
- <MenuItem key={lang.code} value={lang.code}>
227
- {lang.label}
228
- </MenuItem>
229
- ))}
230
- </Select>
231
- {formik.touched.siteLanguage && (formik.errors.siteLanguage || apiErrors.siteLanguage) && (
232
- <Typography color="error" variant="caption">
233
- {formik.errors.siteLanguage || apiErrors.siteLanguage}
234
- </Typography>
235
- )}
236
- </FormControl>
237
-
238
- <FormControl fullWidth margin="normal">
239
- <InputLabel id="currency-label">
240
- {labels.currency || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Currency)}
241
- </InputLabel>
242
- <Select
243
- labelId="currency-label"
244
- id="currency"
245
- name="currency"
246
- value={formik.values.currency}
247
- onChange={formik.handleChange}
248
- onBlur={formik.handleBlur}
249
- error={formik.touched.currency && Boolean(formik.errors.currency)}
250
- label={labels.currency || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Currency)}
251
- >
252
- {currencies.map((curr) => (
253
- <MenuItem key={curr.code} value={curr.code}>
254
- {curr.label}
255
- </MenuItem>
256
- ))}
257
- </Select>
258
- {formik.touched.currency && (formik.errors.currency || apiErrors.currency) && (
259
- <Typography color="error" variant="caption">
260
- {formik.errors.currency || apiErrors.currency}
261
- </Typography>
262
- )}
263
- </FormControl>
264
-
265
- <FormControl fullWidth margin="normal">
266
- <FormControlLabel
267
- control={
268
- <Switch
269
- id="darkMode"
270
- name="darkMode"
271
- checked={formik.values.darkMode}
272
- onChange={formik.handleChange}
273
- />
274
- }
275
- label={labels.darkMode || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_DarkMode)}
276
- />
277
- </FormControl>
278
-
279
- <FormControl fullWidth margin="normal">
280
- <FormControlLabel
281
- control={
282
- <Switch
283
- id="directChallenge"
284
- name="directChallenge"
285
- checked={formik.values.directChallenge}
286
- onChange={formik.handleChange}
287
- />
288
- }
289
- label={labels.directChallenge || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Registration_DirectChallengeLabel)}
290
- />
291
- <Typography variant="caption" color="text.secondary" sx={{ ml: 4, mt: -1 }}>
292
- {labels.directChallengeHelper || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Registration_DirectChallengeHelper)}
293
- </Typography>
294
- </FormControl>
295
-
296
- {additionalFields && additionalFields(formik)}
297
-
298
- {apiErrors.general && (
299
- <Alert severity="error" sx={{ mt: 2, mb: 2 }}>
300
- {apiErrors.general}
301
- </Alert>
302
- )}
303
-
304
- {successMessage && (
305
- <Alert severity="success" sx={{ mt: 2, mb: 2 }}>
306
- {successMessage}
307
- </Alert>
308
- )}
309
-
310
- <Button
311
- type="submit"
312
- fullWidth
313
- variant="contained"
314
- color="primary"
315
- sx={{ mt: 3, mb: 2 }}
316
- disabled={formik.isSubmitting}
317
- >
318
- {saving
319
- ? labels.saving || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Saving)
320
- : labels.save || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Settings_Save)}
321
- </Button>
322
- </Box>
323
- </Box>
324
- </Container>
325
- );
326
- };
327
-
328
- export default UserSettingsForm;
@@ -1,133 +0,0 @@
1
- import {
2
- Alert,
3
- Box,
4
- Button,
5
- CircularProgress,
6
- Container,
7
- Link,
8
- Typography,
9
- } from '@mui/material';
10
- import { FC, useEffect, useState } from 'react';
11
- import { SuiteCoreComponentId, SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
12
- import { useI18n } from '../contexts';
13
-
14
- export interface VerifyEmailPageProps {
15
- token: string | null;
16
- onVerify: (token: string) => Promise<{ success: boolean; message?: string }>;
17
- labels?: {
18
- title?: string;
19
- verifying?: string;
20
- success?: string;
21
- failed?: string;
22
- noToken?: string;
23
- proceedToLogin?: string;
24
- contactSupport?: string;
25
- requestNewEmail?: string;
26
- };
27
- loginLink?: string;
28
- resendLink?: string;
29
- }
30
-
31
- export const VerifyEmailPage: FC<VerifyEmailPageProps> = ({
32
- token,
33
- onVerify,
34
- labels = {},
35
- loginLink = '/login',
36
- resendLink = '/resend-verification',
37
- }) => {
38
- const { t, tComponent } = useI18n();
39
- const [message, setMessage] = useState('');
40
- const [loading, setLoading] = useState(true);
41
- const [verificationStatus, setVerificationStatus] = useState<'pending' | 'success' | 'error'>(
42
- 'pending'
43
- );
44
-
45
- const translatedLabels = {
46
- title: labels.title || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.Common_EmailVerification),
47
- success: labels.success || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.EmailVerification_Success),
48
- failed: labels.failed || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.EmailVerification_Failed),
49
- noToken: labels.noToken || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.NoVerificationTokenProvided),
50
- proceedToLogin: labels.proceedToLogin || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.ProceedToLogin),
51
- contactSupport: labels.contactSupport || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.HavingTroubleContactSupport),
52
- requestNewEmail: labels.requestNewEmail || tComponent<SuiteCoreStringKey>(SuiteCoreComponentId, SuiteCoreStringKey.RequestNewVerificationEmail),
53
- };
54
-
55
- useEffect(() => {
56
- const verifyEmail = async (verificationToken: string) => {
57
- try {
58
- const result = await onVerify(verificationToken);
59
- if (result.success) {
60
- setMessage(result.message || translatedLabels.success);
61
- setVerificationStatus('success');
62
- } else {
63
- setMessage(result.message || translatedLabels.failed);
64
- setVerificationStatus('error');
65
- }
66
- } catch {
67
- setMessage(translatedLabels.failed);
68
- setVerificationStatus('error');
69
- } finally {
70
- setLoading(false);
71
- }
72
- };
73
-
74
- if (token) {
75
- verifyEmail(token);
76
- } else {
77
- setLoading(false);
78
- setMessage(translatedLabels.noToken);
79
- setVerificationStatus('error');
80
- }
81
- }, [token, onVerify, translatedLabels]);
82
-
83
- return (
84
- <Container maxWidth="sm">
85
- <Box
86
- sx={{
87
- mt: 8,
88
- display: 'flex',
89
- flexDirection: 'column',
90
- alignItems: 'center',
91
- }}
92
- >
93
- <Typography variant="h4" component="h1" gutterBottom>
94
- {translatedLabels.title}
95
- </Typography>
96
-
97
- {loading ? (
98
- <CircularProgress />
99
- ) : (
100
- <Box sx={{ width: '100%', mt: 2 }}>
101
- <Alert severity={verificationStatus === 'success' ? 'success' : 'error'} sx={{ mb: 2 }}>
102
- {message}
103
- </Alert>
104
-
105
- {verificationStatus === 'success' && (
106
- <Button
107
- variant="contained"
108
- color="primary"
109
- component={Link}
110
- href={loginLink}
111
- fullWidth
112
- >
113
- {translatedLabels.proceedToLogin}
114
- </Button>
115
- )}
116
-
117
- {verificationStatus === 'error' && (
118
- <Typography variant="body1">
119
- {translatedLabels.contactSupport}{' '}
120
- <Link href={resendLink} color="primary">
121
- {translatedLabels.requestNewEmail}
122
- </Link>
123
- .
124
- </Typography>
125
- )}
126
- </Box>
127
- )}
128
- </Box>
129
- </Container>
130
- );
131
- };
132
-
133
- export default VerifyEmailPage;