@dashadmin/dash-app-common 1.3.25 → 1.3.26

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 (165) hide show
  1. package/dist/DashApp.js +176 -1
  2. package/dist/DashAppLoader.js +348 -3
  3. package/dist/DashDefaultResources.js +10 -1
  4. package/dist/components/DashDefaultPrivateApp.js +150 -1
  5. package/dist/components/DashDefaultPrivateResources.js +10 -1
  6. package/dist/components/DashDefaultPublicApp.js +20 -1
  7. package/dist/components/DashResourceLoader.js +245 -1
  8. package/dist/defaults/extensions/bootstrap/DashDefaultErrorBoundary.js +78 -1
  9. package/dist/defaults/extensions/bootstrap/dashDefaultInitializeApp.js +59 -1
  10. package/dist/defaults/extensions/bootstrap/index.js +24 -1
  11. package/dist/defaults/extensions/components/DashDefaultLoader.js +43 -2
  12. package/dist/defaults/extensions/components/dashDefaultAutoAdminComponents.js +67 -1
  13. package/dist/defaults/extensions/components/dashDefaultNotification.js +28 -1
  14. package/dist/defaults/extensions/components/dashDefaultStaticComponents.js +15 -1
  15. package/dist/defaults/extensions/components/index.js +13 -1
  16. package/dist/defaults/extensions/electron/dashDefaultIpcListeners.js +38 -1
  17. package/dist/defaults/extensions/electron/index.js +5 -1
  18. package/dist/defaults/extensions/hooks/index.js +12 -1
  19. package/dist/defaults/extensions/hooks/useDashDefaultLazyAutoAdminComponents.js +17 -1
  20. package/dist/defaults/extensions/hooks/useDashDefaultLazyI18nProvider.js +51 -1
  21. package/dist/defaults/extensions/hooks/useDashDefaultLazyResources.js +19 -1
  22. package/dist/defaults/extensions/hooks/useDashDefaultMountTracker.js +22 -1
  23. package/dist/defaults/extensions/hooks/useDashDefaultRoutePath.js +17 -1
  24. package/dist/defaults/extensions/i18n/dashDefaultI18nProvider.js +44 -1
  25. package/dist/defaults/extensions/i18n/dashDefaultTranslations.js +87 -1
  26. package/dist/defaults/extensions/i18n/index.js +24 -1
  27. package/dist/defaults/extensions/index.js +190 -1
  28. package/dist/defaults/extensions/layout/dashDefaultDomainAppLayout.js +58 -1
  29. package/dist/defaults/extensions/layout/index.js +12 -1
  30. package/dist/defaults/extensions/managers/DashDefaultWSMessagesManager.js +84 -1
  31. package/dist/defaults/extensions/managers/index.js +5 -1
  32. package/dist/defaults/extensions/providers/dashDefaultAuthProvider.js +220 -1
  33. package/dist/defaults/extensions/providers/dashDefaultDataProvider.js +395 -1
  34. package/dist/defaults/extensions/providers/index.js +24 -1
  35. package/dist/defaults/extensions/router/DashDefaultLanding.js +46 -1
  36. package/dist/defaults/extensions/router/dashDefaultPrivateRoutes.js +38 -1
  37. package/dist/defaults/extensions/router/dashDefaultPublicRoutes.js +65 -1
  38. package/dist/defaults/extensions/router/dashDefaultRouter.js +39 -1
  39. package/dist/defaults/extensions/router/dashDefaultSharedRoutes.js +40 -1
  40. package/dist/defaults/extensions/router/index.js +12 -1
  41. package/dist/defaults/extensions/state/dashDefaultAppCommon.js +57 -1
  42. package/dist/defaults/extensions/state/dashDefaultAppSettings.js +38 -1
  43. package/dist/defaults/extensions/state/dashDefaultInitialAppState.js +31 -1
  44. package/dist/defaults/extensions/state/dashDefaultLayoutSettings.js +48 -1
  45. package/dist/defaults/extensions/state/dashDefaultQueryClient.js +58 -1
  46. package/dist/defaults/extensions/state/dashDefaultResourcesIcons.js +24 -1
  47. package/dist/defaults/extensions/state/index.js +29 -1
  48. package/dist/defaults/extensions/styles/index.js +2 -1
  49. package/dist/defaults/extensions/theme/dashDefaultThemeOptions.js +74 -1
  50. package/dist/defaults/extensions/theme/index.js +6 -1
  51. package/dist/defaults/extensions/utils/IPCMessageBrokerContext.js +12 -1
  52. package/dist/defaults/extensions/utils/dashDefaultAuthProviderUtils.js +29 -1
  53. package/dist/defaults/extensions/utils/dashDefaultDataProviderUtils.js +37 -1
  54. package/dist/defaults/extensions/utils/dashDefaultNotificationsProcessor.js +149 -1
  55. package/dist/defaults/extensions/utils/index.js +44 -1
  56. package/dist/defaults/filters/demo/dashDefaultDemoFilters.js +36 -1
  57. package/dist/defaults/filters/demo/index.js +4 -1
  58. package/dist/defaults/filters/index.js +5 -1
  59. package/dist/defaults/index.js +14 -1
  60. package/dist/defaults/pages/Account/DashDefaultRegister.js +282 -1
  61. package/dist/defaults/pages/Account/DashDefaultSignUp.js +420 -1
  62. package/dist/defaults/pages/Account/DashDefaultSignUpSuccess.js +101 -1
  63. package/dist/defaults/pages/Account/index.js +8 -1
  64. package/dist/defaults/pages/DashDefaultLogin.js +218 -1
  65. package/dist/defaults/pages/Misc/DashDefaultNotFound.js +74 -1
  66. package/dist/defaults/pages/Misc/DashDefaultServerError.js +79 -1
  67. package/dist/defaults/pages/Misc/DashDefaultUnauthorized.js +90 -1
  68. package/dist/defaults/pages/Misc/index.js +8 -1
  69. package/dist/defaults/pages/Static/DashDefaultPrivacyPage.js +48 -1
  70. package/dist/defaults/pages/Static/DashDefaultStaticPage.js +55 -1
  71. package/dist/defaults/pages/Static/DashDefaultTermsPage.js +52 -1
  72. package/dist/defaults/pages/Static/index.js +8 -1
  73. package/dist/defaults/pages/index.js +25 -1
  74. package/dist/defaults/schemas/dashDefaultSchema.js +14 -1
  75. package/dist/defaults/schemas/demo/dashDefaultTodoSchema.js +24 -1
  76. package/dist/defaults/schemas/demo/index.js +4 -1
  77. package/dist/defaults/schemas/index.js +7 -1
  78. package/dist/filters/demo/todoFilters.js +36 -1
  79. package/dist/index.js +56 -5975
  80. package/dist/resources/demo/todoResource.js +58 -1
  81. package/dist/schemas/defaultSchema.js +14 -1
  82. package/dist/schemas/demo/todoSchema.js +24 -1
  83. package/package.json +132 -77
  84. package/src/DashApp.tsx +294 -0
  85. package/src/DashAppLoader.tsx +717 -0
  86. package/src/DashDefaultResources.tsx +10 -0
  87. package/src/components/DashDefaultPrivateApp.tsx +358 -0
  88. package/src/components/DashDefaultPrivateResources.tsx +10 -0
  89. package/src/components/DashDefaultPublicApp.tsx +40 -0
  90. package/src/components/DashResourceLoader.tsx +564 -0
  91. package/src/defaults/extensions/bootstrap/DashDefaultErrorBoundary.tsx +113 -0
  92. package/src/defaults/extensions/bootstrap/dashDefaultInitializeApp.ts +81 -0
  93. package/src/defaults/extensions/bootstrap/index.ts +32 -0
  94. package/src/defaults/extensions/components/DashDefaultLoader.tsx +59 -0
  95. package/src/defaults/extensions/components/dashDefaultAutoAdminComponents.tsx +49 -0
  96. package/src/defaults/extensions/components/dashDefaultNotification.tsx +37 -0
  97. package/src/defaults/extensions/components/dashDefaultStaticComponents.tsx +34 -0
  98. package/src/defaults/extensions/components/index.ts +17 -0
  99. package/src/defaults/extensions/electron/dashDefaultIpcListeners.ts +62 -0
  100. package/src/defaults/extensions/electron/index.ts +7 -0
  101. package/src/defaults/extensions/hooks/index.ts +11 -0
  102. package/src/defaults/extensions/hooks/useDashDefaultLazyAutoAdminComponents.ts +25 -0
  103. package/src/defaults/extensions/hooks/useDashDefaultLazyI18nProvider.ts +38 -0
  104. package/src/defaults/extensions/hooks/useDashDefaultLazyResources.ts +29 -0
  105. package/src/defaults/extensions/hooks/useDashDefaultMountTracker.ts +28 -0
  106. package/src/defaults/extensions/hooks/useDashDefaultRoutePath.ts +27 -0
  107. package/src/defaults/extensions/i18n/dashDefaultI18nProvider.ts +66 -0
  108. package/src/defaults/extensions/i18n/dashDefaultTranslations.ts +82 -0
  109. package/src/defaults/extensions/i18n/index.ts +22 -0
  110. package/src/defaults/extensions/index.ts +177 -0
  111. package/src/defaults/extensions/layout/dashDefaultDomainAppLayout.tsx +126 -0
  112. package/src/defaults/extensions/layout/index.ts +12 -0
  113. package/src/defaults/extensions/managers/DashDefaultWSMessagesManager.tsx +99 -0
  114. package/src/defaults/extensions/managers/index.ts +7 -0
  115. package/src/defaults/extensions/providers/dashDefaultAuthProvider.ts +256 -0
  116. package/src/defaults/extensions/providers/dashDefaultDataProvider.ts +513 -0
  117. package/src/defaults/extensions/providers/index.ts +25 -0
  118. package/src/defaults/extensions/router/DashDefaultLanding.tsx +51 -0
  119. package/src/defaults/extensions/router/dashDefaultPrivateRoutes.tsx +50 -0
  120. package/src/defaults/extensions/router/dashDefaultPublicRoutes.tsx +86 -0
  121. package/src/defaults/extensions/router/dashDefaultRouter.tsx +54 -0
  122. package/src/defaults/extensions/router/dashDefaultSharedRoutes.tsx +56 -0
  123. package/src/defaults/extensions/router/index.ts +13 -0
  124. package/src/defaults/extensions/state/dashDefaultAppCommon.ts +54 -0
  125. package/src/defaults/extensions/state/dashDefaultAppSettings.ts +29 -0
  126. package/src/defaults/extensions/state/dashDefaultInitialAppState.ts +75 -0
  127. package/src/defaults/extensions/state/dashDefaultLayoutSettings.ts +59 -0
  128. package/src/defaults/extensions/state/dashDefaultQueryClient.ts +59 -0
  129. package/src/defaults/extensions/state/dashDefaultResourcesIcons.tsx +23 -0
  130. package/src/defaults/extensions/state/index.ts +29 -0
  131. package/src/defaults/extensions/styles/index.ts +17 -0
  132. package/src/defaults/extensions/theme/dashDefaultThemeOptions.ts +89 -0
  133. package/src/defaults/extensions/theme/index.ts +7 -0
  134. package/src/defaults/extensions/utils/IPCMessageBrokerContext.tsx +22 -0
  135. package/src/defaults/extensions/utils/dashDefaultAuthProviderUtils.ts +36 -0
  136. package/src/defaults/extensions/utils/dashDefaultDataProviderUtils.ts +46 -0
  137. package/src/defaults/extensions/utils/dashDefaultNotificationsProcessor.tsx +208 -0
  138. package/src/defaults/extensions/utils/index.ts +42 -0
  139. package/src/defaults/filters/demo/dashDefaultDemoFilters.tsx +50 -0
  140. package/src/defaults/filters/demo/index.ts +6 -0
  141. package/src/defaults/filters/index.ts +11 -0
  142. package/src/defaults/index.ts +27 -0
  143. package/src/defaults/pages/Account/DashDefaultRegister.tsx +281 -0
  144. package/src/defaults/pages/Account/DashDefaultSignUp.tsx +492 -0
  145. package/src/defaults/pages/Account/DashDefaultSignUpSuccess.tsx +113 -0
  146. package/src/defaults/pages/Account/index.ts +8 -0
  147. package/src/defaults/pages/DashDefaultLogin.tsx +224 -0
  148. package/src/defaults/pages/Misc/DashDefaultNotFound.tsx +96 -0
  149. package/src/defaults/pages/Misc/DashDefaultServerError.tsx +102 -0
  150. package/src/defaults/pages/Misc/DashDefaultUnauthorized.tsx +116 -0
  151. package/src/defaults/pages/Misc/index.ts +8 -0
  152. package/src/defaults/pages/Static/DashDefaultPrivacyPage.tsx +85 -0
  153. package/src/defaults/pages/Static/DashDefaultStaticPage.tsx +75 -0
  154. package/src/defaults/pages/Static/DashDefaultTermsPage.tsx +69 -0
  155. package/src/defaults/pages/Static/index.ts +8 -0
  156. package/src/defaults/pages/index.ts +28 -0
  157. package/src/defaults/schemas/dashDefaultSchema.tsx +25 -0
  158. package/src/defaults/schemas/demo/dashDefaultTodoSchema.tsx +39 -0
  159. package/src/defaults/schemas/demo/index.ts +6 -0
  160. package/src/defaults/schemas/index.ts +14 -0
  161. package/src/filters/demo/todoFilters.tsx +39 -0
  162. package/src/index.ts +131 -0
  163. package/src/resources/demo/todoResource.tsx +68 -0
  164. package/src/schemas/defaultSchema.tsx +14 -0
  165. package/src/schemas/demo/todoSchema.tsx +27 -0
@@ -0,0 +1,492 @@
1
+ /**
2
+ * Default SignUp Page
3
+ *
4
+ * SignUp page with subscription plan selection.
5
+ */
6
+ import React, { createRef, useEffect, useState } from 'react';
7
+ import { useDispatch } from 'react-redux';
8
+ import { useForm } from 'react-hook-form';
9
+ import Button from '@mui/material/Button';
10
+ import { useNavigate } from 'react-router-dom';
11
+ import { useNotify } from 'react-admin';
12
+ import ReCAPTCHA from 'react-google-recaptcha';
13
+ import {
14
+ Grid,
15
+ IconButton,
16
+ TextField,
17
+ Card,
18
+ CardContent,
19
+ Typography,
20
+ Box,
21
+ Chip,
22
+ FormControl,
23
+ FormLabel,
24
+ Divider,
25
+ Alert,
26
+ useTheme,
27
+ useMediaQuery
28
+ } from '@mui/material';
29
+ import HomeIcon from '@mui/icons-material/Home';
30
+ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
31
+ import GoogleIcon from '@mui/icons-material/Google';
32
+
33
+ import { DASH_REDUX_ACTIONS } from 'dash-admin-state';
34
+ import DictionaryContext from 'dash-admin/src/contexts/dictionary/DictionaryContext';
35
+ import { useAxios } from 'dash-axios-hook';
36
+ import { useDialog } from 'dash-dialog';
37
+ import { DASHAdminSystemConstants } from 'dash-constants';
38
+ import { RutValidator } from 'dash-admin/src/utils/validators';
39
+ import FullLayoutMarkup from 'dash-admin/src/default-theme/FullLayoutMarkup';
40
+ import { priceFormatter } from 'dash-utils';
41
+
42
+ interface SubscriptionPlan {
43
+ id: number;
44
+ name: string;
45
+ slug: string;
46
+ description: string;
47
+ price: number;
48
+ billing_cycle: 'monthly' | 'yearly';
49
+ features: string[];
50
+ is_active: boolean;
51
+ trial_days: number;
52
+ }
53
+
54
+ interface SignUpFormData {
55
+ email: string;
56
+ clientname: string;
57
+ public_id: string;
58
+ name: string;
59
+ lastname: string;
60
+ password: string;
61
+ confirm_password: string;
62
+ phone: string;
63
+ selected_plan_id?: number;
64
+ 'g-recaptcha-response'?: string;
65
+ }
66
+
67
+ interface DefaultSignUpPageProps {
68
+ panelSettings?: {
69
+ horizontalLogo?: string;
70
+ loginBackground?: string;
71
+ };
72
+ showRutField?: boolean;
73
+ }
74
+
75
+ const DefaultSignUpPage: React.FC<DefaultSignUpPageProps> = (props) => {
76
+ const { panelSettings, showRutField = true } = props;
77
+
78
+ const enableRecaptcha: boolean = DASHAdminSystemConstants.system.RECAPTCHA_ENABLED;
79
+ const enableGoogleSignup: boolean = DASHAdminSystemConstants.system.GOOGLE_SIGNUP !== false;
80
+ const recaptchaRef = createRef<ReCAPTCHA>();
81
+ const [recpatcha, setRecaptcha] = useState(null);
82
+ const [plans, setPlans] = useState<SubscriptionPlan[]>([]);
83
+ const [selectedPlan, setSelectedPlan] = useState<number | null>(null);
84
+ const [loading, setLoading] = useState(false);
85
+ const [plansLoading, setPlansLoading] = useState(true);
86
+ const [googleAuthLoading, setGoogleAuthLoading] = useState(false);
87
+
88
+ const theme = useTheme();
89
+ const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
90
+
91
+ const dispatch = useDispatch();
92
+ const dialog = useDialog();
93
+ const dict = React.useContext(DictionaryContext);
94
+ const navigate = useNavigate();
95
+ const form = useForm<SignUpFormData>();
96
+ const {
97
+ register,
98
+ handleSubmit,
99
+ setError,
100
+ clearErrors,
101
+ formState: { errors },
102
+ setValue,
103
+ watch
104
+ } = form;
105
+ const axios = useAxios();
106
+ const notify = useNotify();
107
+
108
+ const onChangeRecaptcha = (value: string) => {
109
+ clearErrors('g-recaptcha-response');
110
+ setRecaptcha(value);
111
+ };
112
+
113
+ // Load subscription plans
114
+ useEffect(() => {
115
+ const loadPlans = async () => {
116
+ try {
117
+ setPlansLoading(true);
118
+ const response = await axios.get('/subscription-plans');
119
+ if (response.data?.data) {
120
+ setPlans(response.data.data);
121
+ if (response.data.data.length > 0) {
122
+ setSelectedPlan(response.data.data[0].id);
123
+ setValue('selected_plan_id', response.data.data[0].id);
124
+ }
125
+ }
126
+ } catch (error) {
127
+ console.error('Error loading subscription plans:', error);
128
+ notify('Error loading subscription plans', { type: 'warning' });
129
+ } finally {
130
+ setPlansLoading(false);
131
+ }
132
+ };
133
+
134
+ loadPlans();
135
+ }, []);
136
+
137
+ useEffect(() => {
138
+ dispatch(
139
+ DASH_REDUX_ACTIONS.updatePage({
140
+ title: null,
141
+ }),
142
+ );
143
+ }, []);
144
+
145
+ const handlePlanSelection = (planId: number) => {
146
+ setSelectedPlan(planId);
147
+ setValue('selected_plan_id', planId);
148
+ clearErrors('selected_plan_id');
149
+ };
150
+
151
+ const handleGoogleSignUp = async () => {
152
+ if (!enableGoogleSignup) {
153
+ notify('Google signup is currently disabled', { type: 'warning' });
154
+ return;
155
+ }
156
+
157
+ try {
158
+ setGoogleAuthLoading(true);
159
+ const googleAuthUrl = DASHAdminSystemConstants.system.API_URL + `/api/auth/google/redirect?signup=true&plan_id=${selectedPlan || ''}`;
160
+ window.location.href = googleAuthUrl;
161
+ } catch (error) {
162
+ console.error('Google authentication error:', error);
163
+ notify('Google authentication error', { type: 'error' });
164
+ } finally {
165
+ setGoogleAuthLoading(false);
166
+ }
167
+ };
168
+
169
+ async function onSubmit(data: SignUpFormData) {
170
+ try {
171
+ setLoading(true);
172
+ clearErrors();
173
+
174
+ if (!selectedPlan) {
175
+ setError('selected_plan_id', {
176
+ type: 'required',
177
+ message: 'Please select a subscription plan'
178
+ });
179
+ return;
180
+ }
181
+
182
+ if (data.clientname) {
183
+ const bracketed_name = 'client[name]';
184
+ data[bracketed_name] = data.clientname;
185
+ delete data.clientname;
186
+ }
187
+
188
+ data.selected_plan_id = selectedPlan;
189
+
190
+ if (enableRecaptcha) {
191
+ const recaptchaValue =
192
+ recaptchaRef.current && recaptchaRef.current.getValue
193
+ ? recaptchaRef.current.getValue()
194
+ : recpatcha;
195
+ data['g-recaptcha-response'] = recaptchaValue;
196
+ }
197
+
198
+ const response = await axios.post('/auth/user/signup', data, {
199
+ headers: { 'Content-Type': 'multipart/form-data' },
200
+ });
201
+
202
+ if (response.status >= 200) {
203
+ notify('Account created successfully!', { type: 'success' });
204
+ navigate('/signup-success', {
205
+ state: {
206
+ email: data.email,
207
+ planName: plans.find(p => p.id === selectedPlan)?.name
208
+ }
209
+ });
210
+ } else {
211
+ dialog({
212
+ variant: 'danger',
213
+ title: 'Error',
214
+ content: 'An error occurred, please try again',
215
+ });
216
+ }
217
+ } catch (error: any) {
218
+ console.error('SignUp error:', error);
219
+
220
+ if (error.response?.data?.errors) {
221
+ const errors = error.response.data.errors;
222
+ for (const key in errors) {
223
+ if (key === 'client.name') {
224
+ setError('clientname', {
225
+ type: 'custom',
226
+ message: dict.get(errors[key], true),
227
+ });
228
+ } else {
229
+ setError(key as keyof SignUpFormData, {
230
+ type: 'custom',
231
+ message: dict.get(errors[key], true)
232
+ });
233
+ }
234
+ }
235
+ } else {
236
+ notify('Registration error occurred', { type: 'error' });
237
+ }
238
+ } finally {
239
+ setLoading(false);
240
+ }
241
+ }
242
+
243
+ const formatPrice = (price: number, billingCycle: string) => {
244
+ return `${priceFormatter(price, 'USD')}/${billingCycle === 'monthly' ? 'mo' : 'yr'}`;
245
+ };
246
+
247
+ const getTrialText = (trialDays: number) => {
248
+ return trialDays > 0 ? `${trialDays} days free trial` : 'No trial period';
249
+ };
250
+
251
+ return (
252
+ <FullLayoutMarkup
253
+ className='dash-signup'
254
+ logo={panelSettings?.horizontalLogo}
255
+ loginBackground={panelSettings?.loginBackground}
256
+ >
257
+ <form onSubmit={handleSubmit(onSubmit)} className='dash-app-login-form'>
258
+ <Box sx={{ display: 'flex', alignItems: 'center', mb: 4, mt: 2, gap: 1 }}>
259
+ <IconButton color='primary' size='large' onClick={() => navigate('/')}>
260
+ <HomeIcon />
261
+ </IconButton>
262
+ <Typography
263
+ variant={isMobile ? "h5" : "h4"}
264
+ component="h1"
265
+ className='dash-app-login-form-title'
266
+ sx={{ fontWeight: 'bold' }}
267
+ >
268
+ Create Your Account
269
+ </Typography>
270
+ </Box>
271
+
272
+ {enableGoogleSignup && (
273
+ <>
274
+ <div className='dash-app-form-item'>
275
+ <Button
276
+ fullWidth
277
+ variant="outlined"
278
+ startIcon={<GoogleIcon />}
279
+ onClick={handleGoogleSignUp}
280
+ disabled={googleAuthLoading || !selectedPlan}
281
+ size="large"
282
+ >
283
+ {googleAuthLoading ? 'Connecting...' : 'Continue with Google'}
284
+ </Button>
285
+ </div>
286
+ <Divider sx={{ my: 3 }}>
287
+ <Typography variant="body2" color="textSecondary">
288
+ or sign up with email
289
+ </Typography>
290
+ </Divider>
291
+ </>
292
+ )}
293
+
294
+ {/* Subscription Plans */}
295
+ <div className='dash-app-form-item'>
296
+ <FormControl component="fieldset" fullWidth>
297
+ <FormLabel component="legend">
298
+ <Typography variant={isMobile ? "h6" : "h5"} gutterBottom>
299
+ Choose Your Plan
300
+ </Typography>
301
+ </FormLabel>
302
+
303
+ {plansLoading ? (
304
+ <Box display="flex" justifyContent="center" p={2}>
305
+ <Typography>Loading plans...</Typography>
306
+ </Box>
307
+ ) : (
308
+ <Grid container spacing={2}>
309
+ {plans.map((plan) => (
310
+ <Grid key={plan.id} size={{ xs: 12, sm: 6, md: 4 }}>
311
+ <Card
312
+ variant={selectedPlan === plan.id ? "outlined" : "elevation"}
313
+ sx={{
314
+ cursor: 'pointer',
315
+ border: selectedPlan === plan.id ? 2 : 1,
316
+ borderColor: selectedPlan === plan.id ? 'primary.main' : 'divider',
317
+ '&:hover': { borderColor: 'primary.main' },
318
+ height: '100%'
319
+ }}
320
+ onClick={() => handlePlanSelection(plan.id)}
321
+ >
322
+ <CardContent>
323
+ <Box display="flex" alignItems="center" mb={2}>
324
+ <Typography variant="h6">{plan.name}</Typography>
325
+ {selectedPlan === plan.id && (
326
+ <CheckCircleIcon color="primary" sx={{ ml: 'auto' }} />
327
+ )}
328
+ </Box>
329
+ <Typography variant="h4" color="primary" gutterBottom>
330
+ ${formatPrice(plan.price, plan.billing_cycle)}
331
+ </Typography>
332
+ <Chip label={getTrialText(plan.trial_days)} color="secondary" size="small" sx={{ mb: 2 }} />
333
+ <Typography variant="body2" color="textSecondary">
334
+ {plan.description}
335
+ </Typography>
336
+ </CardContent>
337
+ </Card>
338
+ </Grid>
339
+ ))}
340
+ </Grid>
341
+ )}
342
+
343
+ {errors.selected_plan_id && (
344
+ <Alert severity="error" sx={{ mt: 2 }}>
345
+ {errors.selected_plan_id.message}
346
+ </Alert>
347
+ )}
348
+ </FormControl>
349
+ </div>
350
+
351
+ {/* User Information Form */}
352
+ <Typography variant="h6" gutterBottom sx={{ mt: 4 }}>
353
+ Account Information
354
+ </Typography>
355
+
356
+ <div className='dash-app-form-item'>
357
+ <TextField
358
+ label="Email"
359
+ required
360
+ fullWidth
361
+ {...register('email', { required: 'Email is required' })}
362
+ inputProps={{ type: 'email' }}
363
+ error={!!errors.email}
364
+ helperText={errors.email?.message}
365
+ />
366
+ </div>
367
+
368
+ <div className='dash-app-form-item'>
369
+ <TextField
370
+ label="Business Name"
371
+ required
372
+ fullWidth
373
+ {...register('clientname', { required: 'Business name is required' })}
374
+ error={!!errors.clientname}
375
+ helperText={errors.clientname?.message}
376
+ />
377
+ </div>
378
+
379
+ {showRutField && (
380
+ <div className='dash-app-form-item'>
381
+ <TextField
382
+ label="RUT"
383
+ placeholder='11.111.111-1'
384
+ fullWidth
385
+ {...register('public_id', { validate: RutValidator })}
386
+ error={!!errors.public_id}
387
+ helperText={errors.public_id?.message}
388
+ />
389
+ </div>
390
+ )}
391
+
392
+ <Grid container spacing={2}>
393
+ <Grid size={{ xs: 12, sm: 6 }}>
394
+ <div className='dash-app-form-item'>
395
+ <TextField
396
+ label="First Name"
397
+ required
398
+ fullWidth
399
+ {...register('name', { required: 'First name is required' })}
400
+ error={!!errors.name}
401
+ helperText={errors.name?.message}
402
+ />
403
+ </div>
404
+ </Grid>
405
+ <Grid size={{ xs: 12, sm: 6 }}>
406
+ <div className='dash-app-form-item'>
407
+ <TextField
408
+ label="Last Name"
409
+ required
410
+ fullWidth
411
+ {...register('lastname', { required: 'Last name is required' })}
412
+ error={!!errors.lastname}
413
+ helperText={errors.lastname?.message}
414
+ />
415
+ </div>
416
+ </Grid>
417
+ </Grid>
418
+
419
+ <Grid container spacing={2}>
420
+ <Grid size={{ xs: 12, sm: 6 }}>
421
+ <div className='dash-app-form-item'>
422
+ <TextField
423
+ label="Password"
424
+ type='password'
425
+ required
426
+ fullWidth
427
+ {...register('password', { required: 'Password is required', minLength: { value: 8, message: 'Password must be at least 8 characters' } })}
428
+ error={!!errors.password}
429
+ helperText={errors.password?.message}
430
+ />
431
+ </div>
432
+ </Grid>
433
+ <Grid size={{ xs: 12, sm: 6 }}>
434
+ <div className='dash-app-form-item'>
435
+ <TextField
436
+ label="Confirm Password"
437
+ type='password'
438
+ required
439
+ fullWidth
440
+ {...register('confirm_password', { required: 'Please confirm your password' })}
441
+ error={!!errors.confirm_password}
442
+ helperText={errors.confirm_password?.message}
443
+ />
444
+ </div>
445
+ </Grid>
446
+ </Grid>
447
+
448
+ <div className='dash-app-form-item'>
449
+ <TextField
450
+ label="Contact Phone"
451
+ placeholder='+1 234 567 8900'
452
+ required
453
+ fullWidth
454
+ {...register('phone', { required: 'Phone number is required' })}
455
+ error={!!errors.phone}
456
+ helperText={errors.phone?.message}
457
+ />
458
+ </div>
459
+
460
+ {enableRecaptcha && (
461
+ <div className='dash-app-form-item'>
462
+ <ReCAPTCHA
463
+ ref={recaptchaRef}
464
+ sitekey={DASHAdminSystemConstants.system.RECAPTCHA_TOKEN}
465
+ onChange={onChangeRecaptcha}
466
+ />
467
+ </div>
468
+ )}
469
+
470
+ <div className='dash-app-form-item'>
471
+ <Button
472
+ disabled={(!recpatcha && enableRecaptcha) || loading || !selectedPlan}
473
+ type='submit'
474
+ fullWidth
475
+ variant='contained'
476
+ size="large"
477
+ >
478
+ {loading ? 'Creating Account...' : 'Create Account & Start Trial'}
479
+ </Button>
480
+ </div>
481
+
482
+ <div className='dash-app-form-item'>
483
+ <Button fullWidth onClick={() => navigate('/')} disabled={loading}>
484
+ Cancel
485
+ </Button>
486
+ </div>
487
+ </form>
488
+ </FullLayoutMarkup>
489
+ );
490
+ };
491
+
492
+ export default DefaultSignUpPage;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Default SignUp Success Page
3
+ *
4
+ * Success page displayed after successful registration.
5
+ */
6
+ import React from 'react';
7
+ import { useLocation, useNavigate } from 'react-router-dom';
8
+ import {
9
+ Box,
10
+ Typography,
11
+ Button,
12
+ Paper,
13
+ Container
14
+ } from '@mui/material';
15
+ import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
16
+ import EmailIcon from '@mui/icons-material/Email';
17
+
18
+ import FullLayoutMarkup from 'dash-admin/src/default-theme/FullLayoutMarkup';
19
+
20
+ interface SignUpSuccessState {
21
+ email?: string;
22
+ planName?: string;
23
+ }
24
+
25
+ interface DefaultSignUpSuccessPageProps {
26
+ panelSettings?: {
27
+ horizontalLogo?: string;
28
+ loginBackground?: string;
29
+ };
30
+ }
31
+
32
+ const DefaultSignUpSuccessPage: React.FC<DefaultSignUpSuccessPageProps> = (props) => {
33
+ const { panelSettings } = props;
34
+ const location = useLocation();
35
+ const navigate = useNavigate();
36
+ const state = location.state as SignUpSuccessState;
37
+
38
+ return (
39
+ <FullLayoutMarkup
40
+ className='dash-signup-success'
41
+ logo={panelSettings?.horizontalLogo}
42
+ loginBackground={panelSettings?.loginBackground}
43
+ >
44
+ <Container maxWidth="sm">
45
+ <Paper
46
+ elevation={3}
47
+ sx={{
48
+ p: 4,
49
+ textAlign: 'center',
50
+ borderRadius: 2
51
+ }}
52
+ >
53
+ <CheckCircleOutlineIcon
54
+ color="success"
55
+ sx={{ fontSize: 80, mb: 2 }}
56
+ />
57
+
58
+ <Typography variant="h4" component="h1" gutterBottom>
59
+ Account Created Successfully!
60
+ </Typography>
61
+
62
+ <Typography variant="body1" color="textSecondary" paragraph>
63
+ Thank you for signing up{state?.planName ? ` for the ${state.planName} plan` : ''}.
64
+ </Typography>
65
+
66
+ <Box
67
+ sx={{
68
+ display: 'flex',
69
+ alignItems: 'center',
70
+ justifyContent: 'center',
71
+ bgcolor: 'info.light',
72
+ borderRadius: 1,
73
+ p: 2,
74
+ my: 3
75
+ }}
76
+ >
77
+ <EmailIcon sx={{ mr: 1, color: 'info.dark' }} />
78
+ <Typography variant="body2" color="info.dark">
79
+ We've sent a verification email to <strong>{state?.email || 'your email address'}</strong>.
80
+ Please check your inbox and verify your email to complete the registration.
81
+ </Typography>
82
+ </Box>
83
+
84
+ <Typography variant="body2" color="textSecondary" paragraph>
85
+ If you don't see the email, please check your spam folder or request a new verification email.
86
+ </Typography>
87
+
88
+ <Box sx={{ mt: 4, display: 'flex', flexDirection: 'column', gap: 2 }}>
89
+ <Button
90
+ variant="contained"
91
+ color="primary"
92
+ size="large"
93
+ onClick={() => navigate('/login')}
94
+ fullWidth
95
+ >
96
+ Go to Login
97
+ </Button>
98
+
99
+ <Button
100
+ variant="outlined"
101
+ onClick={() => navigate('/')}
102
+ fullWidth
103
+ >
104
+ Back to Home
105
+ </Button>
106
+ </Box>
107
+ </Paper>
108
+ </Container>
109
+ </FullLayoutMarkup>
110
+ );
111
+ };
112
+
113
+ export default DefaultSignUpSuccessPage;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Account Pages Module
3
+ *
4
+ * Exports all default account-related pages.
5
+ */
6
+ export { default as DashDefaultRegister } from './DashDefaultRegister';
7
+ export { default as DashDefaultSignUp } from './DashDefaultSignUp';
8
+ export { default as DashDefaultSignUpSuccess } from './DashDefaultSignUpSuccess';