@digitaldefiance/express-suite-react-components 2.9.38 → 2.9.40

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 +5 -4
  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 +77 -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 +139 -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 +120 -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 +78 -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 +61 -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 +122 -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 +56 -0
  60. package/src/components/RegisterForm.d.ts.map +1 -0
  61. package/src/components/RegisterForm.js +140 -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 +78 -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 +35 -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 +57 -0
  84. package/src/components/UserSettingsForm.d.ts.map +1 -0
  85. package/src/components/UserSettingsForm.js +126 -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 +70 -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 +502 -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 +273 -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 +74 -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 +40 -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 +48 -0
  126. package/src/hooks/useUserSettings.d.ts.map +1 -0
  127. package/src/hooks/useUserSettings.js +169 -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 +335 -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 +20 -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 +31 -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 -174
  203. package/src/components/BackupCodeLoginForm.tsx +0 -488
  204. package/src/components/BackupCodesForm.tsx +0 -286
  205. package/src/components/ChangePasswordForm.tsx +0 -272
  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 -60
  212. package/src/components/Flag.tsx +0 -52
  213. package/src/components/ForgotPasswordForm.tsx +0 -173
  214. package/src/components/LoginForm.tsx +0 -455
  215. package/src/components/LogoutPage.tsx +0 -21
  216. package/src/components/RegisterForm.tsx +0 -602
  217. package/src/components/ResetPasswordForm.tsx +0 -246
  218. package/src/components/SideMenu.tsx +0 -46
  219. package/src/components/SideMenuListItem.tsx +0 -74
  220. package/src/components/TopMenu.tsx +0 -145
  221. package/src/components/TranslatedTitle.tsx +0 -29
  222. package/src/components/UserLanguageSelector.tsx +0 -45
  223. package/src/components/UserMenu.tsx +0 -15
  224. package/src/components/UserSettingsForm.tsx +0 -505
  225. package/src/components/VerifyEmailPage.tsx +0 -184
  226. package/src/contexts/AuthProvider.spec.tsx +0 -1195
  227. package/src/contexts/AuthProvider.tsx +0 -924
  228. package/src/contexts/I18nProvider.tsx +0 -114
  229. package/src/contexts/MenuContext.tsx +0 -398
  230. package/src/contexts/SuiteConfigProvider.tsx +0 -93
  231. package/src/contexts/ThemeProvider.tsx +0 -67
  232. package/src/hooks/useBackupCodes.ts +0 -105
  233. package/src/hooks/useEmailVerification.ts +0 -49
  234. package/src/hooks/useExpiringValue.ts +0 -78
  235. package/src/hooks/useLocalStorage.ts +0 -18
  236. package/src/hooks/useUserSettings.ts +0 -269
  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 -500
  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 -34
  251. package/src/wrappers/BackupCodesWrapper.tsx +0 -28
  252. package/src/wrappers/ChangePasswordFormWrapper.tsx +0 -34
  253. package/src/wrappers/LoginFormWrapper.tsx +0 -59
  254. package/src/wrappers/LogoutPageWrapper.tsx +0 -30
  255. package/src/wrappers/RegisterFormWrapper.tsx +0 -61
  256. package/src/wrappers/UserSettingsFormWrapper.tsx +0 -39
  257. package/src/wrappers/VerifyEmailPageWrapper.tsx +0 -27
@@ -1,505 +0,0 @@
1
- import { CurrencyCode } from '@digitaldefiance/i18n-lib';
2
- import {
3
- SuiteCoreComponentId,
4
- SuiteCoreStringKey,
5
- } from '@digitaldefiance/suite-core-lib';
6
- import {
7
- Alert,
8
- Box,
9
- Button,
10
- Container,
11
- FormControl,
12
- FormControlLabel,
13
- InputLabel,
14
- MenuItem,
15
- Select,
16
- Switch,
17
- TextField,
18
- Typography,
19
- } from '@mui/material';
20
- import { useFormik } from 'formik';
21
- import moment from 'moment-timezone';
22
- import { FC, useMemo, useState } from 'react';
23
- import * as Yup from 'yup';
24
- import { useI18n } from '../contexts';
25
-
26
- export interface UserSettingsFormValues {
27
- email: string;
28
- timezone: string;
29
- siteLanguage: string;
30
- currency: string;
31
- darkMode: boolean;
32
- directChallenge: boolean;
33
- [key: string]: string | boolean;
34
- }
35
-
36
- export interface UserSettingsFormProps {
37
- initialValues: UserSettingsFormValues;
38
- onSubmit: (values: UserSettingsFormValues) => Promise<
39
- | { success: boolean; message: string }
40
- | {
41
- error: string;
42
- errorType?: string;
43
- field?: string;
44
- errors?: Array<{ path: string; msg: string }>;
45
- }
46
- >;
47
- languages: Array<{ code: string; label: string }>;
48
- emailValidation?: Yup.StringSchema;
49
- timezoneValidation?: Yup.StringSchema;
50
- siteLanguageValidation?: Yup.StringSchema;
51
- currencyValidation?: Yup.StringSchema;
52
- darkModeValidation?: Yup.BooleanSchema;
53
- directChallengeValidation?: Yup.BooleanSchema;
54
- additionalFields?: (
55
- formik: ReturnType<typeof useFormik<UserSettingsFormValues>>
56
- ) => React.ReactNode;
57
- additionalInitialValues?: Record<string, string | boolean>;
58
- additionalValidation?: Record<string, Yup.Schema>;
59
- labels?: {
60
- title?: string;
61
- email?: string;
62
- emailHelper?: string;
63
- timezone?: string;
64
- siteLanguage?: string;
65
- currency?: string;
66
- darkMode?: string;
67
- directChallenge?: string;
68
- directChallengeHelper?: string;
69
- saving?: string;
70
- save?: string;
71
- successMessage?: string;
72
- };
73
- }
74
-
75
- export const UserSettingsForm: FC<UserSettingsFormProps> = ({
76
- initialValues,
77
- onSubmit,
78
- languages,
79
- emailValidation,
80
- timezoneValidation,
81
- siteLanguageValidation,
82
- currencyValidation,
83
- darkModeValidation,
84
- directChallengeValidation,
85
- additionalFields,
86
- additionalInitialValues = {},
87
- additionalValidation = {},
88
- labels = {},
89
- }) => {
90
- const { tComponent } = useI18n();
91
- const [apiErrors, setApiErrors] = useState<Record<string, string>>({});
92
- const [saving, setSaving] = useState(false);
93
- const [successMessage, setSuccessMessage] = useState<string | null>(null);
94
-
95
- const timezones = useMemo(() => moment.tz.names(), []);
96
- const currencies = useMemo(
97
- () =>
98
- CurrencyCode.getAllData().map((c) => ({
99
- code: c.code,
100
- label: `${c.code} - ${c.currency}`,
101
- })),
102
- []
103
- );
104
-
105
- const validation = {
106
- email:
107
- emailValidation ||
108
- Yup.string()
109
- .email(
110
- tComponent<SuiteCoreStringKey>(
111
- SuiteCoreComponentId,
112
- SuiteCoreStringKey.Validation_InvalidEmail
113
- )
114
- )
115
- .required(
116
- tComponent<SuiteCoreStringKey>(
117
- SuiteCoreComponentId,
118
- SuiteCoreStringKey.Validation_Required
119
- )
120
- ),
121
- timezone:
122
- timezoneValidation ||
123
- Yup.string()
124
- .required(
125
- tComponent<SuiteCoreStringKey>(
126
- SuiteCoreComponentId,
127
- SuiteCoreStringKey.Validation_TimezoneRequired
128
- )
129
- )
130
- .test(
131
- 'valid-timezone',
132
- tComponent<SuiteCoreStringKey>(
133
- SuiteCoreComponentId,
134
- SuiteCoreStringKey.Validation_TimezoneInvalid
135
- ),
136
- (value) => !value || moment.tz.zone(value) !== null
137
- ),
138
- siteLanguage:
139
- siteLanguageValidation ||
140
- Yup.string().required(
141
- tComponent<SuiteCoreStringKey>(
142
- SuiteCoreComponentId,
143
- SuiteCoreStringKey.Validation_Required
144
- )
145
- ),
146
- currency:
147
- currencyValidation ||
148
- Yup.string()
149
- .required(
150
- tComponent<SuiteCoreStringKey>(
151
- SuiteCoreComponentId,
152
- SuiteCoreStringKey.Validation_Required
153
- )
154
- )
155
- .test(
156
- 'valid-currency',
157
- tComponent<SuiteCoreStringKey>(
158
- SuiteCoreComponentId,
159
- SuiteCoreStringKey.Validation_Required
160
- ),
161
- (value) => !value || CurrencyCode.isValid(value)
162
- ),
163
- darkMode:
164
- darkModeValidation ||
165
- Yup.boolean().required(
166
- tComponent<SuiteCoreStringKey>(
167
- SuiteCoreComponentId,
168
- SuiteCoreStringKey.Validation_Required
169
- )
170
- ),
171
- directChallenge:
172
- directChallengeValidation ||
173
- Yup.boolean().required(
174
- tComponent<SuiteCoreStringKey>(
175
- SuiteCoreComponentId,
176
- SuiteCoreStringKey.Validation_Required
177
- )
178
- ),
179
- };
180
-
181
- const formik = useFormik<UserSettingsFormValues>({
182
- initialValues: {
183
- ...initialValues,
184
- ...additionalInitialValues,
185
- },
186
- enableReinitialize: true,
187
- validationSchema: Yup.object({
188
- email: validation.email,
189
- timezone: validation.timezone,
190
- siteLanguage: validation.siteLanguage,
191
- currency: validation.currency,
192
- darkMode: validation.darkMode,
193
- directChallenge: validation.directChallenge,
194
- ...additionalValidation,
195
- }),
196
- onSubmit: async (values, { setSubmitting, setFieldError, setTouched }) => {
197
- setSaving(true);
198
- setSuccessMessage(null);
199
- const result = await onSubmit(values);
200
-
201
- if ('success' in result && result.success) {
202
- setSuccessMessage(
203
- result.message ||
204
- labels.successMessage ||
205
- tComponent<SuiteCoreStringKey>(
206
- SuiteCoreComponentId,
207
- SuiteCoreStringKey.Settings_SaveSuccess
208
- )
209
- );
210
- setApiErrors({});
211
- } else {
212
- const newApiErrors: Record<string, string> = {};
213
- const fieldsToTouch: Record<string, boolean> = {};
214
-
215
- if ('field' in result && result.field) {
216
- setFieldError(result.field, result.error);
217
- fieldsToTouch[result.field] = true;
218
- }
219
-
220
- if ('errors' in result && result.errors) {
221
- result.errors.forEach((err) => {
222
- if (err.path && err.msg) {
223
- setFieldError(err.path, err.msg);
224
- fieldsToTouch[err.path] = true;
225
- }
226
- });
227
- }
228
-
229
- if (
230
- 'error' in result &&
231
- result.error &&
232
- !Object.keys(newApiErrors).length
233
- ) {
234
- newApiErrors.general = result.error;
235
- }
236
-
237
- setApiErrors(newApiErrors);
238
- setTouched(fieldsToTouch, false);
239
- }
240
- setSubmitting(false);
241
- setSaving(false);
242
- },
243
- });
244
-
245
- return (
246
- <Container maxWidth="sm">
247
- <Box
248
- sx={{
249
- mt: 4,
250
- display: 'flex',
251
- flexDirection: 'column',
252
- alignItems: 'center',
253
- }}
254
- >
255
- <Typography variant="h4" component="h1" gutterBottom>
256
- {labels.title ||
257
- tComponent<SuiteCoreStringKey>(
258
- SuiteCoreComponentId,
259
- SuiteCoreStringKey.Settings_Title
260
- )}
261
- </Typography>
262
-
263
- <Box
264
- component="form"
265
- onSubmit={formik.handleSubmit}
266
- sx={{ mt: 1, width: '100%' }}
267
- >
268
- <TextField
269
- fullWidth
270
- id="email"
271
- name="email"
272
- label={
273
- labels.email ||
274
- tComponent<SuiteCoreStringKey>(
275
- SuiteCoreComponentId,
276
- SuiteCoreStringKey.Common_Email
277
- )
278
- }
279
- value={formik.values.email}
280
- onChange={formik.handleChange}
281
- onBlur={formik.handleBlur}
282
- error={Boolean(
283
- formik.touched.email && (formik.errors.email || apiErrors.email)
284
- )}
285
- helperText={
286
- (formik.touched.email &&
287
- (formik.errors.email || apiErrors.email)) ||
288
- labels.emailHelper ||
289
- tComponent<SuiteCoreStringKey>(
290
- SuiteCoreComponentId,
291
- SuiteCoreStringKey.Settings_EmailHelper
292
- )
293
- }
294
- margin="normal"
295
- />
296
-
297
- <FormControl fullWidth margin="normal">
298
- <InputLabel id="timezone-label">
299
- {labels.timezone ||
300
- tComponent<SuiteCoreStringKey>(
301
- SuiteCoreComponentId,
302
- SuiteCoreStringKey.Common_Timezone
303
- )}
304
- </InputLabel>
305
- <Select
306
- labelId="timezone-label"
307
- id="timezone"
308
- name="timezone"
309
- value={formik.values.timezone}
310
- onChange={formik.handleChange}
311
- onBlur={formik.handleBlur}
312
- error={formik.touched.timezone && Boolean(formik.errors.timezone)}
313
- label={
314
- labels.timezone ||
315
- tComponent<SuiteCoreStringKey>(
316
- SuiteCoreComponentId,
317
- SuiteCoreStringKey.Common_Timezone
318
- )
319
- }
320
- >
321
- {timezones.map((tz) => (
322
- <MenuItem key={tz} value={tz}>
323
- {tz}
324
- </MenuItem>
325
- ))}
326
- </Select>
327
- {formik.touched.timezone &&
328
- (formik.errors.timezone || apiErrors.timezone) && (
329
- <Typography color="error" variant="caption">
330
- {formik.errors.timezone || apiErrors.timezone}
331
- </Typography>
332
- )}
333
- </FormControl>
334
-
335
- <FormControl fullWidth margin="normal">
336
- <InputLabel id="language-label">
337
- {labels.siteLanguage ||
338
- tComponent<SuiteCoreStringKey>(
339
- SuiteCoreComponentId,
340
- SuiteCoreStringKey.Settings_SiteLanguage
341
- )}
342
- </InputLabel>
343
- <Select
344
- labelId="language-label"
345
- id="siteLanguage"
346
- name="siteLanguage"
347
- value={formik.values.siteLanguage}
348
- onChange={formik.handleChange}
349
- onBlur={formik.handleBlur}
350
- error={
351
- formik.touched.siteLanguage &&
352
- Boolean(formik.errors.siteLanguage)
353
- }
354
- label={
355
- labels.siteLanguage ||
356
- tComponent<SuiteCoreStringKey>(
357
- SuiteCoreComponentId,
358
- SuiteCoreStringKey.Settings_SiteLanguage
359
- )
360
- }
361
- >
362
- {languages.map((lang) => (
363
- <MenuItem key={lang.code} value={lang.code}>
364
- {lang.label}
365
- </MenuItem>
366
- ))}
367
- </Select>
368
- {formik.touched.siteLanguage &&
369
- (formik.errors.siteLanguage || apiErrors.siteLanguage) && (
370
- <Typography color="error" variant="caption">
371
- {formik.errors.siteLanguage || apiErrors.siteLanguage}
372
- </Typography>
373
- )}
374
- </FormControl>
375
-
376
- <FormControl fullWidth margin="normal">
377
- <InputLabel id="currency-label">
378
- {labels.currency ||
379
- tComponent<SuiteCoreStringKey>(
380
- SuiteCoreComponentId,
381
- SuiteCoreStringKey.Settings_Currency
382
- )}
383
- </InputLabel>
384
- <Select
385
- labelId="currency-label"
386
- id="currency"
387
- name="currency"
388
- value={formik.values.currency}
389
- onChange={formik.handleChange}
390
- onBlur={formik.handleBlur}
391
- error={formik.touched.currency && Boolean(formik.errors.currency)}
392
- label={
393
- labels.currency ||
394
- tComponent<SuiteCoreStringKey>(
395
- SuiteCoreComponentId,
396
- SuiteCoreStringKey.Settings_Currency
397
- )
398
- }
399
- >
400
- {currencies.map((curr) => (
401
- <MenuItem key={curr.code} value={curr.code}>
402
- {curr.label}
403
- </MenuItem>
404
- ))}
405
- </Select>
406
- {formik.touched.currency &&
407
- (formik.errors.currency || apiErrors.currency) && (
408
- <Typography color="error" variant="caption">
409
- {formik.errors.currency || apiErrors.currency}
410
- </Typography>
411
- )}
412
- </FormControl>
413
-
414
- <FormControl fullWidth margin="normal">
415
- <FormControlLabel
416
- control={
417
- <Switch
418
- id="darkMode"
419
- name="darkMode"
420
- checked={formik.values.darkMode}
421
- onChange={formik.handleChange}
422
- />
423
- }
424
- label={
425
- labels.darkMode ||
426
- tComponent<SuiteCoreStringKey>(
427
- SuiteCoreComponentId,
428
- SuiteCoreStringKey.Settings_DarkMode
429
- )
430
- }
431
- />
432
- </FormControl>
433
-
434
- <FormControl fullWidth margin="normal">
435
- <FormControlLabel
436
- control={
437
- <Switch
438
- id="directChallenge"
439
- name="directChallenge"
440
- checked={formik.values.directChallenge}
441
- onChange={formik.handleChange}
442
- />
443
- }
444
- label={
445
- labels.directChallenge ||
446
- tComponent<SuiteCoreStringKey>(
447
- SuiteCoreComponentId,
448
- SuiteCoreStringKey.Registration_DirectChallengeLabel
449
- )
450
- }
451
- />
452
- <Typography
453
- variant="caption"
454
- color="text.secondary"
455
- sx={{ ml: 4, mt: -1 }}
456
- >
457
- {labels.directChallengeHelper ||
458
- tComponent<SuiteCoreStringKey>(
459
- SuiteCoreComponentId,
460
- SuiteCoreStringKey.Registration_DirectChallengeHelper
461
- )}
462
- </Typography>
463
- </FormControl>
464
-
465
- {additionalFields && additionalFields(formik)}
466
-
467
- {apiErrors.general && (
468
- <Alert severity="error" sx={{ mt: 2, mb: 2 }}>
469
- {apiErrors.general}
470
- </Alert>
471
- )}
472
-
473
- {successMessage && (
474
- <Alert severity="success" sx={{ mt: 2, mb: 2 }}>
475
- {successMessage}
476
- </Alert>
477
- )}
478
-
479
- <Button
480
- type="submit"
481
- fullWidth
482
- variant="contained"
483
- color="primary"
484
- sx={{ mt: 3, mb: 2 }}
485
- disabled={formik.isSubmitting}
486
- >
487
- {saving
488
- ? labels.saving ||
489
- tComponent<SuiteCoreStringKey>(
490
- SuiteCoreComponentId,
491
- SuiteCoreStringKey.Settings_Saving
492
- )
493
- : labels.save ||
494
- tComponent<SuiteCoreStringKey>(
495
- SuiteCoreComponentId,
496
- SuiteCoreStringKey.Settings_Save
497
- )}
498
- </Button>
499
- </Box>
500
- </Box>
501
- </Container>
502
- );
503
- };
504
-
505
- export default UserSettingsForm;
@@ -1,184 +0,0 @@
1
- import {
2
- SuiteCoreComponentId,
3
- SuiteCoreStringKey,
4
- } from '@digitaldefiance/suite-core-lib';
5
- import {
6
- Alert,
7
- Box,
8
- Button,
9
- CircularProgress,
10
- Container,
11
- Link,
12
- Typography,
13
- } from '@mui/material';
14
- import { FC, useEffect, useMemo, useState } from 'react';
15
- import { useI18n } from '../contexts';
16
-
17
- export interface VerifyEmailPageProps {
18
- token: string | null;
19
- onVerify: (token: string) => Promise<{ success: boolean; message?: string }>;
20
- labels?: {
21
- title?: string;
22
- verifying?: string;
23
- success?: string;
24
- failed?: string;
25
- noToken?: string;
26
- proceedToLogin?: string;
27
- contactSupport?: string;
28
- requestNewEmail?: string;
29
- };
30
- loginLink?: string;
31
- resendLink?: string;
32
- }
33
-
34
- export const VerifyEmailPage: FC<VerifyEmailPageProps> = ({
35
- token,
36
- onVerify,
37
- labels = {},
38
- loginLink = '/login',
39
- resendLink = '/resend-verification',
40
- }) => {
41
- const { tComponent } = useI18n();
42
- const [message, setMessage] = useState('');
43
- const [loading, setLoading] = useState(true);
44
- const [verificationStatus, setVerificationStatus] = useState<
45
- 'pending' | 'success' | 'error'
46
- >('pending');
47
-
48
- const translatedLabels = useMemo<{
49
- title: string;
50
- success: string;
51
- failed: string;
52
- noToken: string;
53
- proceedToLogin: string;
54
- contactSupport: string;
55
- requestNewEmail: string;
56
- }>(() => {
57
- return {
58
- title:
59
- labels.title ||
60
- tComponent<SuiteCoreStringKey>(
61
- SuiteCoreComponentId,
62
- SuiteCoreStringKey.Common_EmailVerification
63
- ),
64
- success:
65
- labels.success ||
66
- tComponent<SuiteCoreStringKey>(
67
- SuiteCoreComponentId,
68
- SuiteCoreStringKey.EmailVerification_Success
69
- ),
70
- failed:
71
- labels.failed ||
72
- tComponent<SuiteCoreStringKey>(
73
- SuiteCoreComponentId,
74
- SuiteCoreStringKey.EmailVerification_Failed
75
- ),
76
- noToken:
77
- labels.noToken ||
78
- tComponent<SuiteCoreStringKey>(
79
- SuiteCoreComponentId,
80
- SuiteCoreStringKey.NoVerificationTokenProvided
81
- ),
82
- proceedToLogin:
83
- labels.proceedToLogin ||
84
- tComponent<SuiteCoreStringKey>(
85
- SuiteCoreComponentId,
86
- SuiteCoreStringKey.ProceedToLogin
87
- ),
88
- contactSupport:
89
- labels.contactSupport ||
90
- tComponent<SuiteCoreStringKey>(
91
- SuiteCoreComponentId,
92
- SuiteCoreStringKey.HavingTroubleContactSupport
93
- ),
94
- requestNewEmail:
95
- labels.requestNewEmail ||
96
- tComponent<SuiteCoreStringKey>(
97
- SuiteCoreComponentId,
98
- SuiteCoreStringKey.RequestNewVerificationEmail
99
- ),
100
- };
101
- }, [labels, tComponent]);
102
-
103
- useEffect(() => {
104
- const verifyEmail = async (verificationToken: string) => {
105
- try {
106
- const result = await onVerify(verificationToken);
107
- if (result.success) {
108
- setMessage(result.message || translatedLabels.success);
109
- setVerificationStatus('success');
110
- } else {
111
- setMessage(result.message || translatedLabels.failed);
112
- setVerificationStatus('error');
113
- }
114
- } catch {
115
- setMessage(translatedLabels.failed);
116
- setVerificationStatus('error');
117
- } finally {
118
- setLoading(false);
119
- }
120
- };
121
-
122
- if (token) {
123
- verifyEmail(token);
124
- } else {
125
- setLoading(false);
126
- setMessage(translatedLabels.noToken);
127
- setVerificationStatus('error');
128
- }
129
- }, [token, onVerify, translatedLabels]);
130
-
131
- return (
132
- <Container maxWidth="sm">
133
- <Box
134
- sx={{
135
- mt: 8,
136
- display: 'flex',
137
- flexDirection: 'column',
138
- alignItems: 'center',
139
- }}
140
- >
141
- <Typography variant="h4" component="h1" gutterBottom>
142
- {translatedLabels.title}
143
- </Typography>
144
-
145
- {loading ? (
146
- <CircularProgress />
147
- ) : (
148
- <Box sx={{ width: '100%', mt: 2 }}>
149
- <Alert
150
- severity={verificationStatus === 'success' ? 'success' : 'error'}
151
- sx={{ mb: 2 }}
152
- >
153
- {message}
154
- </Alert>
155
-
156
- {verificationStatus === 'success' && (
157
- <Button
158
- variant="contained"
159
- color="primary"
160
- component={Link}
161
- href={loginLink}
162
- fullWidth
163
- >
164
- {translatedLabels.proceedToLogin}
165
- </Button>
166
- )}
167
-
168
- {verificationStatus === 'error' && (
169
- <Typography variant="body1">
170
- {translatedLabels.contactSupport}{' '}
171
- <Link href={resendLink} color="primary">
172
- {translatedLabels.requestNewEmail}
173
- </Link>
174
- .
175
- </Typography>
176
- )}
177
- </Box>
178
- )}
179
- </Box>
180
- </Container>
181
- );
182
- };
183
-
184
- export default VerifyEmailPage;