@digilogiclabs/create-saas-app 1.14.0 → 1.17.0

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 (84) hide show
  1. package/README.md +134 -29
  2. package/bin/index.js +1 -1
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cli/prompts/project-setup.d.ts.map +1 -1
  5. package/dist/cli/prompts/project-setup.js +45 -12
  6. package/dist/cli/prompts/project-setup.js.map +1 -1
  7. package/dist/generators/template-generator.d.ts.map +1 -1
  8. package/dist/generators/template-generator.js +27 -4
  9. package/dist/generators/template-generator.js.map +1 -1
  10. package/dist/templates/mobile/ui-auth-payments/template/.env.example +20 -0
  11. package/dist/templates/mobile/ui-auth-payments/template/README.md +218 -0
  12. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/_layout.tsx +153 -0
  13. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/analytics.tsx +668 -0
  14. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/billing.tsx +743 -0
  15. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/index.tsx +676 -0
  16. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/orders.tsx +402 -0
  17. package/dist/templates/mobile/ui-auth-payments/template/app/(tabs)/profile.tsx +580 -0
  18. package/dist/templates/mobile/ui-auth-payments/template/app/_layout.tsx +125 -0
  19. package/dist/templates/mobile/ui-auth-payments/template/app/auth/login.tsx +246 -0
  20. package/dist/templates/mobile/ui-auth-payments/template/app/auth/signup.tsx +362 -0
  21. package/dist/templates/mobile/ui-auth-payments/template/app/onboarding/index.tsx +193 -0
  22. package/dist/templates/mobile/ui-auth-payments/template/app/tour/index.tsx +272 -0
  23. package/dist/templates/mobile/ui-auth-payments/template/app.json +93 -0
  24. package/dist/templates/mobile/ui-auth-payments/template/babel.config.js +23 -0
  25. package/dist/templates/mobile/ui-auth-payments/template/eas.json +45 -0
  26. package/dist/templates/mobile/ui-auth-payments/template/expo-env.d.ts +3 -0
  27. package/dist/templates/mobile/ui-auth-payments/template/jest-setup.ts +74 -0
  28. package/dist/templates/mobile/ui-auth-payments/template/metro.config.js +11 -0
  29. package/dist/templates/mobile/ui-auth-payments/template/package.json +106 -0
  30. package/dist/templates/mobile/ui-auth-payments/template/tsconfig.json +31 -0
  31. package/dist/templates/web/base/template/src/app/dashboard/page.tsx +62 -20
  32. package/dist/templates/web/ui-auth/template/package.json +1 -1
  33. package/dist/templates/web/ui-auth-payments/template/package.json +1 -1
  34. package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +69 -17
  35. package/dist/templates/web/ui-auth-payments-ai/template/package.json +1 -1
  36. package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +218 -7
  37. package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +62 -9
  38. package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +364 -0
  39. package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +532 -0
  40. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +70 -51
  41. package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +76 -60
  42. package/dist/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +1 -1
  43. package/dist/templates/web/ui-auth-payments-audio/template/package.json +1 -1
  44. package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +71 -17
  45. package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +1 -1
  46. package/dist/templates/web/ui-auth-payments-video/template/package.json +1 -1
  47. package/package.json +1 -1
  48. package/src/templates/mobile/ui-auth-payments/template/.env.example +20 -0
  49. package/src/templates/mobile/ui-auth-payments/template/README.md +218 -0
  50. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/_layout.tsx +153 -0
  51. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/analytics.tsx +668 -0
  52. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/billing.tsx +743 -0
  53. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/index.tsx +676 -0
  54. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/orders.tsx +402 -0
  55. package/src/templates/mobile/ui-auth-payments/template/app/(tabs)/profile.tsx +580 -0
  56. package/src/templates/mobile/ui-auth-payments/template/app/_layout.tsx +125 -0
  57. package/src/templates/mobile/ui-auth-payments/template/app/auth/login.tsx +246 -0
  58. package/src/templates/mobile/ui-auth-payments/template/app/auth/signup.tsx +362 -0
  59. package/src/templates/mobile/ui-auth-payments/template/app/onboarding/index.tsx +193 -0
  60. package/src/templates/mobile/ui-auth-payments/template/app/tour/index.tsx +272 -0
  61. package/src/templates/mobile/ui-auth-payments/template/app.json +93 -0
  62. package/src/templates/mobile/ui-auth-payments/template/babel.config.js +23 -0
  63. package/src/templates/mobile/ui-auth-payments/template/eas.json +45 -0
  64. package/src/templates/mobile/ui-auth-payments/template/expo-env.d.ts +3 -0
  65. package/src/templates/mobile/ui-auth-payments/template/jest-setup.ts +74 -0
  66. package/src/templates/mobile/ui-auth-payments/template/metro.config.js +11 -0
  67. package/src/templates/mobile/ui-auth-payments/template/package.json +106 -0
  68. package/src/templates/mobile/ui-auth-payments/template/tsconfig.json +31 -0
  69. package/src/templates/web/base/template/src/app/dashboard/page.tsx +62 -20
  70. package/src/templates/web/ui-auth/template/package.json +1 -1
  71. package/src/templates/web/ui-auth-payments/template/package.json +1 -1
  72. package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +69 -17
  73. package/src/templates/web/ui-auth-payments-ai/template/package.json +1 -1
  74. package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +218 -7
  75. package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +62 -9
  76. package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +364 -0
  77. package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +532 -0
  78. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +70 -51
  79. package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +76 -60
  80. package/src/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +1 -1
  81. package/src/templates/web/ui-auth-payments-audio/template/package.json +1 -1
  82. package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +71 -17
  83. package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +1 -1
  84. package/src/templates/web/ui-auth-payments-video/template/package.json +1 -1
@@ -0,0 +1,246 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Text, StyleSheet, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
3
+ import { Link, router } from 'expo-router';
4
+ import { useForm, Controller } from 'react-hook-form';
5
+ import { zodResolver } from '@hookform/resolvers/zod';
6
+ import { z } from 'zod';
7
+
8
+ // UI Components
9
+ import {
10
+ NativeButton as Button,
11
+ NativeInput as Input,
12
+ NativeCard as Card,
13
+ NativeAlert as Alert,
14
+ NativePageTransition as PageTransition,
15
+ NativeMobileContainer as MobileContainer,
16
+ NativeMobileHero as MobileHero
17
+ } from '@digilogiclabs/saas-factory-ui/native';
18
+
19
+ // Auth Hook
20
+ import { useAuth } from '@digilogiclabs/saas-factory-auth/native';
21
+
22
+ // Validation Schema
23
+ const loginSchema = z.object({
24
+ email: z.string().email('Please enter a valid email address'),
25
+ password: z.string().min(6, 'Password must be at least 6 characters')
26
+ });
27
+
28
+ type LoginFormData = z.infer<typeof loginSchema>;
29
+
30
+ export default function LoginScreen() {
31
+ const { signIn, loading } = useAuth();
32
+ const [error, setError] = useState<string | null>(null);
33
+
34
+ const { control, handleSubmit, formState: { errors, isValid } } = useForm<LoginFormData>({
35
+ resolver: zodResolver(loginSchema),
36
+ mode: 'onChange',
37
+ defaultValues: {
38
+ email: '',
39
+ password: ''
40
+ }
41
+ });
42
+
43
+ const onSubmit = async (data: LoginFormData) => {
44
+ try {
45
+ setError(null);
46
+ await signIn(data.email, data.password);
47
+ router.replace('/(tabs)');
48
+ } catch (err: any) {
49
+ setError(err.message || 'Login failed. Please try again.');
50
+ }
51
+ };
52
+
53
+ return (
54
+ <PageTransition type="slide" direction="horizontal">
55
+ <KeyboardAvoidingView
56
+ style={styles.container}
57
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
58
+ >
59
+ <ScrollView
60
+ style={styles.scrollView}
61
+ contentContainerStyle={styles.scrollContent}
62
+ keyboardShouldPersistTaps="handled"
63
+ >
64
+ <MobileContainer style={styles.content}>
65
+ {/* Header */}
66
+ <View style={styles.header}>
67
+ <Text style={styles.title}>Welcome Back</Text>
68
+ <Text style={styles.subtitle}>Sign in to continue to {{titleCaseName}}</Text>
69
+ </View>
70
+
71
+ {/* Login Form */}
72
+ <Card style={styles.card}>
73
+ <View style={styles.form}>
74
+ {/* Email Input */}
75
+ <View style={styles.inputGroup}>
76
+ <Text style={styles.label}>Email</Text>
77
+ <Controller
78
+ control={control}
79
+ name="email"
80
+ render={({ field: { onChange, onBlur, value } }) => (
81
+ <Input
82
+ placeholder="Enter your email"
83
+ value={value}
84
+ onChangeText={onChange}
85
+ onBlur={onBlur}
86
+ keyboardType="email-address"
87
+ autoCapitalize="none"
88
+ autoComplete="email"
89
+ textContentType="emailAddress"
90
+ error={!!errors.email}
91
+ style={styles.input}
92
+ />
93
+ )}
94
+ />
95
+ {errors.email && (
96
+ <Text style={styles.errorText}>{errors.email.message}</Text>
97
+ )}
98
+ </View>
99
+
100
+ {/* Password Input */}
101
+ <View style={styles.inputGroup}>
102
+ <Text style={styles.label}>Password</Text>
103
+ <Controller
104
+ control={control}
105
+ name="password"
106
+ render={({ field: { onChange, onBlur, value } }) => (
107
+ <Input
108
+ placeholder="Enter your password"
109
+ value={value}
110
+ onChangeText={onChange}
111
+ onBlur={onBlur}
112
+ secureTextEntry
113
+ autoCapitalize="none"
114
+ autoComplete="password"
115
+ textContentType="password"
116
+ error={!!errors.password}
117
+ style={styles.input}
118
+ />
119
+ )}
120
+ />
121
+ {errors.password && (
122
+ <Text style={styles.errorText}>{errors.password.message}</Text>
123
+ )}
124
+ </View>
125
+
126
+ {/* Error Message */}
127
+ {error && (
128
+ <Alert
129
+ type="error"
130
+ message={error}
131
+ style={styles.alert}
132
+ />
133
+ )}
134
+
135
+ {/* Login Button */}
136
+ <Button
137
+ onPress={handleSubmit(onSubmit)}
138
+ disabled={!isValid || loading}
139
+ loading={loading}
140
+ style={styles.loginButton}
141
+ >
142
+ Sign In
143
+ </Button>
144
+
145
+ {/* Forgot Password */}
146
+ <Link href="/auth/forgot-password" asChild>
147
+ <Button variant="ghost" style={styles.forgotButton}>
148
+ Forgot Password?
149
+ </Button>
150
+ </Link>
151
+ </View>
152
+ </Card>
153
+
154
+ {/* Sign Up Link */}
155
+ <View style={styles.footer}>
156
+ <Text style={styles.footerText}>Don't have an account?</Text>
157
+ <Link href="/auth/signup" asChild>
158
+ <Button variant="link" style={styles.signupLink}>
159
+ Sign Up
160
+ </Button>
161
+ </Link>
162
+ </View>
163
+ </MobileContainer>
164
+ </ScrollView>
165
+ </KeyboardAvoidingView>
166
+ </PageTransition>
167
+ );
168
+ }
169
+
170
+ const styles = StyleSheet.create({
171
+ container: {
172
+ flex: 1,
173
+ backgroundColor: '#f8fafc',
174
+ },
175
+ scrollView: {
176
+ flex: 1,
177
+ },
178
+ scrollContent: {
179
+ flexGrow: 1,
180
+ paddingVertical: 40,
181
+ },
182
+ content: {
183
+ flex: 1,
184
+ justifyContent: 'center',
185
+ paddingHorizontal: 24,
186
+ },
187
+ header: {
188
+ alignItems: 'center',
189
+ marginBottom: 32,
190
+ },
191
+ title: {
192
+ fontSize: 32,
193
+ fontWeight: 'bold',
194
+ color: '#1e293b',
195
+ marginBottom: 8,
196
+ },
197
+ subtitle: {
198
+ fontSize: 16,
199
+ color: '#64748b',
200
+ textAlign: 'center',
201
+ },
202
+ card: {
203
+ padding: 24,
204
+ marginBottom: 24,
205
+ },
206
+ form: {
207
+ gap: 20,
208
+ },
209
+ inputGroup: {
210
+ gap: 8,
211
+ },
212
+ label: {
213
+ fontSize: 16,
214
+ fontWeight: '600',
215
+ color: '#374151',
216
+ },
217
+ input: {
218
+ fontSize: 16,
219
+ },
220
+ errorText: {
221
+ fontSize: 14,
222
+ color: '#ef4444',
223
+ },
224
+ alert: {
225
+ marginVertical: 8,
226
+ },
227
+ loginButton: {
228
+ marginTop: 8,
229
+ },
230
+ forgotButton: {
231
+ alignSelf: 'center',
232
+ },
233
+ footer: {
234
+ flexDirection: 'row',
235
+ justifyContent: 'center',
236
+ alignItems: 'center',
237
+ gap: 8,
238
+ },
239
+ footerText: {
240
+ fontSize: 16,
241
+ color: '#64748b',
242
+ },
243
+ signupLink: {
244
+ padding: 0,
245
+ },
246
+ });
@@ -0,0 +1,362 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Text, StyleSheet, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
3
+ import { Link, router } from 'expo-router';
4
+ import { useForm, Controller } from 'react-hook-form';
5
+ import { zodResolver } from '@hookform/resolvers/zod';
6
+ import { z } from 'zod';
7
+
8
+ // UI Components
9
+ import {
10
+ NativeButton as Button,
11
+ NativeInput as Input,
12
+ NativeCard as Card,
13
+ NativeAlert as Alert,
14
+ NativePageTransition as PageTransition,
15
+ NativeMobileContainer as MobileContainer,
16
+ NativeCheckbox as Checkbox
17
+ } from '@digilogiclabs/saas-factory-ui/native';
18
+
19
+ // Auth Hook
20
+ import { useAuth } from '@digilogiclabs/saas-factory-auth/native';
21
+
22
+ // Validation Schema
23
+ const signupSchema = z.object({
24
+ name: z.string().min(2, 'Name must be at least 2 characters'),
25
+ email: z.string().email('Please enter a valid email address'),
26
+ password: z.string().min(8, 'Password must be at least 8 characters'),
27
+ confirmPassword: z.string(),
28
+ agreeToTerms: z.boolean().refine(val => val === true, {
29
+ message: 'You must agree to the terms and conditions'
30
+ })
31
+ }).refine(data => data.password === data.confirmPassword, {
32
+ message: "Passwords don't match",
33
+ path: ["confirmPassword"]
34
+ });
35
+
36
+ type SignupFormData = z.infer<typeof signupSchema>;
37
+
38
+ export default function SignupScreen() {
39
+ const { signUp, loading } = useAuth();
40
+ const [error, setError] = useState<string | null>(null);
41
+ const [success, setSuccess] = useState<string | null>(null);
42
+
43
+ const { control, handleSubmit, formState: { errors, isValid } } = useForm<SignupFormData>({
44
+ resolver: zodResolver(signupSchema),
45
+ mode: 'onChange',
46
+ defaultValues: {
47
+ name: '',
48
+ email: '',
49
+ password: '',
50
+ confirmPassword: '',
51
+ agreeToTerms: false
52
+ }
53
+ });
54
+
55
+ const onSubmit = async (data: SignupFormData) => {
56
+ try {
57
+ setError(null);
58
+ setSuccess(null);
59
+
60
+ await signUp(data.email, data.password, {
61
+ name: data.name
62
+ });
63
+
64
+ setSuccess('Account created successfully! Please check your email to verify your account.');
65
+
66
+ // Navigate to login after a short delay
67
+ setTimeout(() => {
68
+ router.replace('/auth/login');
69
+ }, 3000);
70
+
71
+ } catch (err: any) {
72
+ setError(err.message || 'Signup failed. Please try again.');
73
+ }
74
+ };
75
+
76
+ return (
77
+ <PageTransition type="slide" direction="horizontal">
78
+ <KeyboardAvoidingView
79
+ style={styles.container}
80
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
81
+ >
82
+ <ScrollView
83
+ style={styles.scrollView}
84
+ contentContainerStyle={styles.scrollContent}
85
+ keyboardShouldPersistTaps="handled"
86
+ >
87
+ <View style={styles.content}>
88
+ {/* Header */}
89
+ <View style={styles.header}>
90
+ <Text style={styles.title}>Create Account</Text>
91
+ <Text style={styles.subtitle}>Join {{titleCaseName}} today</Text>
92
+ </View>
93
+
94
+ {/* Signup Form */}
95
+ <Card style={styles.card}>
96
+ <View style={styles.form}>
97
+ {/* Name Input */}
98
+ <View style={styles.inputGroup}>
99
+ <Text style={styles.label}>Full Name</Text>
100
+ <Controller
101
+ control={control}
102
+ name="name"
103
+ render={({ field: { onChange, onBlur, value } }) => (
104
+ <Input
105
+ placeholder="Enter your full name"
106
+ value={value}
107
+ onChangeText={onChange}
108
+ onBlur={onBlur}
109
+ autoCapitalize="words"
110
+ autoComplete="name"
111
+ textContentType="name"
112
+ error={!!errors.name}
113
+ style={styles.input}
114
+ />
115
+ )}
116
+ />
117
+ {errors.name && (
118
+ <Text style={styles.errorText}>{errors.name.message}</Text>
119
+ )}
120
+ </View>
121
+
122
+ {/* Email Input */}
123
+ <View style={styles.inputGroup}>
124
+ <Text style={styles.label}>Email</Text>
125
+ <Controller
126
+ control={control}
127
+ name="email"
128
+ render={({ field: { onChange, onBlur, value } }) => (
129
+ <Input
130
+ placeholder="Enter your email"
131
+ value={value}
132
+ onChangeText={onChange}
133
+ onBlur={onBlur}
134
+ keyboardType="email-address"
135
+ autoCapitalize="none"
136
+ autoComplete="email"
137
+ textContentType="emailAddress"
138
+ error={!!errors.email}
139
+ style={styles.input}
140
+ />
141
+ )}
142
+ />
143
+ {errors.email && (
144
+ <Text style={styles.errorText}>{errors.email.message}</Text>
145
+ )}
146
+ </View>
147
+
148
+ {/* Password Input */}
149
+ <View style={styles.inputGroup}>
150
+ <Text style={styles.label}>Password</Text>
151
+ <Controller
152
+ control={control}
153
+ name="password"
154
+ render={({ field: { onChange, onBlur, value } }) => (
155
+ <Input
156
+ placeholder="Create a password"
157
+ value={value}
158
+ onChangeText={onChange}
159
+ onBlur={onBlur}
160
+ secureTextEntry
161
+ autoCapitalize="none"
162
+ autoComplete="password-new"
163
+ textContentType="newPassword"
164
+ error={!!errors.password}
165
+ style={styles.input}
166
+ />
167
+ )}
168
+ />
169
+ {errors.password && (
170
+ <Text style={styles.errorText}>{errors.password.message}</Text>
171
+ )}
172
+ </View>
173
+
174
+ {/* Confirm Password Input */}
175
+ <View style={styles.inputGroup}>
176
+ <Text style={styles.label}>Confirm Password</Text>
177
+ <Controller
178
+ control={control}
179
+ name="confirmPassword"
180
+ render={({ field: { onChange, onBlur, value } }) => (
181
+ <Input
182
+ placeholder="Confirm your password"
183
+ value={value}
184
+ onChangeText={onChange}
185
+ onBlur={onBlur}
186
+ secureTextEntry
187
+ autoCapitalize="none"
188
+ autoComplete="password-new"
189
+ textContentType="newPassword"
190
+ error={!!errors.confirmPassword}
191
+ style={styles.input}
192
+ />
193
+ )}
194
+ />
195
+ {errors.confirmPassword && (
196
+ <Text style={styles.errorText}>{errors.confirmPassword.message}</Text>
197
+ )}
198
+ </View>
199
+
200
+ {/* Terms Agreement */}
201
+ <View style={styles.checkboxContainer}>
202
+ <Controller
203
+ control={control}
204
+ name="agreeToTerms"
205
+ render={({ field: { onChange, value } }) => (
206
+ <Checkbox
207
+ value={value}
208
+ onValueChange={onChange}
209
+ error={!!errors.agreeToTerms}
210
+ />
211
+ )}
212
+ />
213
+ <View style={styles.checkboxTextContainer}>
214
+ <Text style={styles.checkboxText}>
215
+ I agree to the{' '}
216
+ <Text style={styles.linkText}>Terms of Service</Text>
217
+ {' '}and{' '}
218
+ <Text style={styles.linkText}>Privacy Policy</Text>
219
+ </Text>
220
+ {errors.agreeToTerms && (
221
+ <Text style={styles.errorText}>{errors.agreeToTerms.message}</Text>
222
+ )}
223
+ </View>
224
+ </View>
225
+
226
+ {/* Error/Success Messages */}
227
+ {error && (
228
+ <Alert
229
+ type="error"
230
+ message={error}
231
+ style={styles.alert}
232
+ />
233
+ )}
234
+
235
+ {success && (
236
+ <Alert
237
+ type="success"
238
+ message={success}
239
+ style={styles.alert}
240
+ />
241
+ )}
242
+
243
+ {/* Signup Button */}
244
+ <Button
245
+ onPress={handleSubmit(onSubmit)}
246
+ disabled={!isValid || loading}
247
+ loading={loading}
248
+ style={styles.signupButton}
249
+ >
250
+ Create Account
251
+ </Button>
252
+ </View>
253
+ </Card>
254
+
255
+ {/* Login Link */}
256
+ <View style={styles.footer}>
257
+ <Text style={styles.footerText}>Already have an account?</Text>
258
+ <Link href="/auth/login" asChild>
259
+ <Button variant="link" style={styles.loginLink}>
260
+ Sign In
261
+ </Button>
262
+ </Link>
263
+ </View>
264
+ </View>
265
+ </ScrollView>
266
+ </KeyboardAvoidingView>
267
+ </PageTransition>
268
+ );
269
+ }
270
+
271
+ const styles = StyleSheet.create({
272
+ container: {
273
+ flex: 1,
274
+ backgroundColor: '#f8fafc',
275
+ },
276
+ scrollView: {
277
+ flex: 1,
278
+ },
279
+ scrollContent: {
280
+ flexGrow: 1,
281
+ paddingVertical: 40,
282
+ },
283
+ content: {
284
+ flex: 1,
285
+ justifyContent: 'center',
286
+ paddingHorizontal: 24,
287
+ },
288
+ header: {
289
+ alignItems: 'center',
290
+ marginBottom: 32,
291
+ },
292
+ title: {
293
+ fontSize: 32,
294
+ fontWeight: 'bold',
295
+ color: '#1e293b',
296
+ marginBottom: 8,
297
+ },
298
+ subtitle: {
299
+ fontSize: 16,
300
+ color: '#64748b',
301
+ textAlign: 'center',
302
+ },
303
+ card: {
304
+ padding: 24,
305
+ marginBottom: 24,
306
+ },
307
+ form: {
308
+ gap: 20,
309
+ },
310
+ inputGroup: {
311
+ gap: 8,
312
+ },
313
+ label: {
314
+ fontSize: 16,
315
+ fontWeight: '600',
316
+ color: '#374151',
317
+ },
318
+ input: {
319
+ fontSize: 16,
320
+ },
321
+ errorText: {
322
+ fontSize: 14,
323
+ color: '#ef4444',
324
+ },
325
+ checkboxContainer: {
326
+ flexDirection: 'row',
327
+ alignItems: 'flex-start',
328
+ gap: 12,
329
+ },
330
+ checkboxTextContainer: {
331
+ flex: 1,
332
+ gap: 4,
333
+ },
334
+ checkboxText: {
335
+ fontSize: 14,
336
+ color: '#64748b',
337
+ lineHeight: 20,
338
+ },
339
+ linkText: {
340
+ color: '#3b82f6',
341
+ textDecorationLine: 'underline',
342
+ },
343
+ alert: {
344
+ marginVertical: 8,
345
+ },
346
+ signupButton: {
347
+ marginTop: 8,
348
+ },
349
+ footer: {
350
+ flexDirection: 'row',
351
+ justifyContent: 'center',
352
+ alignItems: 'center',
353
+ gap: 8,
354
+ },
355
+ footerText: {
356
+ fontSize: 16,
357
+ color: '#64748b',
358
+ },
359
+ loginLink: {
360
+ padding: 0,
361
+ },
362
+ });