@oxyhq/services 5.11.10 → 5.11.12

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 (181) hide show
  1. package/lib/commonjs/ui/components/AnimationExample.js +1 -1
  2. package/lib/commonjs/ui/components/AnimationExample.js.map +1 -1
  3. package/lib/commonjs/ui/components/FollowButton.js +1 -1
  4. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  5. package/lib/commonjs/ui/components/Header.js +2 -2
  6. package/lib/commonjs/ui/components/Header.js.map +1 -1
  7. package/lib/commonjs/ui/components/OxyProvider.js +3 -3
  8. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  9. package/lib/commonjs/ui/components/StepBasedScreen.README.md +337 -0
  10. package/lib/commonjs/ui/components/StepBasedScreen.js +361 -0
  11. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -0
  12. package/lib/commonjs/ui/components/icon/OxyIcon.js +3 -3
  13. package/lib/commonjs/ui/components/icon/OxyIcon.js.map +1 -1
  14. package/lib/commonjs/ui/components/internal/PinInput.js +1 -1
  15. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  16. package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
  17. package/lib/commonjs/ui/context/OxyContext.js +7 -7
  18. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  19. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +1 -1
  20. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  21. package/lib/commonjs/ui/screens/ProfileScreen.js +55 -55
  22. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  23. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +87 -219
  24. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  25. package/lib/commonjs/ui/screens/SignInScreen.js +138 -235
  26. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  27. package/lib/commonjs/ui/screens/SignUpScreen.js +139 -742
  28. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  29. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +3 -3
  30. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  31. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -2
  32. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  33. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +110 -0
  34. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -0
  35. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +138 -0
  36. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -0
  37. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +141 -0
  38. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -0
  39. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +165 -0
  40. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -0
  41. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +150 -0
  42. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -0
  43. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +171 -0
  44. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -0
  45. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +163 -0
  46. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -0
  47. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +170 -0
  48. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -0
  49. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +72 -0
  50. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -0
  51. package/lib/module/ui/components/AnimationExample.js +1 -1
  52. package/lib/module/ui/components/AnimationExample.js.map +1 -1
  53. package/lib/module/ui/components/FollowButton.js +1 -1
  54. package/lib/module/ui/components/FollowButton.js.map +1 -1
  55. package/lib/module/ui/components/Header.js +2 -2
  56. package/lib/module/ui/components/Header.js.map +1 -1
  57. package/lib/module/ui/components/OxyProvider.js +3 -3
  58. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  59. package/lib/module/ui/components/Section.js.map +1 -1
  60. package/lib/module/ui/components/SectionTitle.js.map +1 -1
  61. package/lib/module/ui/components/StepBasedScreen.README.md +337 -0
  62. package/lib/module/ui/components/StepBasedScreen.js +356 -0
  63. package/lib/module/ui/components/StepBasedScreen.js.map +1 -0
  64. package/lib/module/ui/components/icon/FAIRWalletIcon.js.map +1 -1
  65. package/lib/module/ui/components/icon/OxyIcon.js +3 -3
  66. package/lib/module/ui/components/icon/OxyIcon.js.map +1 -1
  67. package/lib/module/ui/components/internal/PinInput.js +1 -1
  68. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  69. package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
  70. package/lib/module/ui/context/OxyContext.js +7 -7
  71. package/lib/module/ui/context/OxyContext.js.map +1 -1
  72. package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
  73. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  74. package/lib/module/ui/screens/ProfileScreen.js +55 -55
  75. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  76. package/lib/module/ui/screens/RecoverAccountScreen.js +91 -222
  77. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  78. package/lib/module/ui/screens/SignInScreen.js +140 -237
  79. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  80. package/lib/module/ui/screens/SignUpScreen.js +141 -743
  81. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  82. package/lib/module/ui/screens/internal/SignInPasswordStep.js +3 -3
  83. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  84. package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -2
  85. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  86. package/lib/module/ui/screens/steps/RecoverRequestStep.js +105 -0
  87. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -0
  88. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +133 -0
  89. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -0
  90. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +136 -0
  91. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -0
  92. package/lib/module/ui/screens/steps/SignInPasswordStep.js +160 -0
  93. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -0
  94. package/lib/module/ui/screens/steps/SignInUsernameStep.js +145 -0
  95. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -0
  96. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +166 -0
  97. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -0
  98. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +158 -0
  99. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -0
  100. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +165 -0
  101. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -0
  102. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +67 -0
  103. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -0
  104. package/lib/typescript/models/interfaces.d.ts +4 -3
  105. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  106. package/lib/typescript/ui/components/AnimationExample.d.ts +1 -1
  107. package/lib/typescript/ui/components/AnimationExample.d.ts.map +1 -1
  108. package/lib/typescript/ui/components/OxyPayButton.d.ts +2 -2
  109. package/lib/typescript/ui/components/OxyPayButton.d.ts.map +1 -1
  110. package/lib/typescript/ui/components/Section.d.ts +2 -1
  111. package/lib/typescript/ui/components/Section.d.ts.map +1 -1
  112. package/lib/typescript/ui/components/SectionTitle.d.ts +2 -1
  113. package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -1
  114. package/lib/typescript/ui/components/StepBasedScreen.d.ts +24 -0
  115. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -0
  116. package/lib/typescript/ui/components/icon/FAIRWalletIcon.d.ts +2 -1
  117. package/lib/typescript/ui/components/icon/FAIRWalletIcon.d.ts.map +1 -1
  118. package/lib/typescript/ui/components/icon/OxyIcon.d.ts +1 -1
  119. package/lib/typescript/ui/components/icon/OxyIcon.d.ts.map +1 -1
  120. package/lib/typescript/ui/components/internal/PinInput.d.ts +9 -1
  121. package/lib/typescript/ui/components/internal/PinInput.d.ts.map +1 -1
  122. package/lib/typescript/ui/context/OxyContext.d.ts +2 -1
  123. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  124. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts +2 -2
  125. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  126. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  127. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +2 -9
  128. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  129. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  130. package/lib/typescript/ui/screens/SignUpScreen.d.ts +1 -1
  131. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  132. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts +21 -0
  133. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -0
  134. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts +18 -0
  135. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -0
  136. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts +24 -0
  137. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -0
  138. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +27 -0
  139. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -0
  140. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts +27 -0
  141. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -0
  142. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts +25 -0
  143. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -0
  144. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts +26 -0
  145. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -0
  146. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts +16 -0
  147. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -0
  148. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts +13 -0
  149. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -0
  150. package/package.json +2 -3
  151. package/src/models/interfaces.ts +5 -3
  152. package/src/ui/components/AnimationExample.tsx +9 -8
  153. package/src/ui/components/FollowButton.tsx +2 -2
  154. package/src/ui/components/Header.tsx +2 -2
  155. package/src/ui/components/OxyPayButton.tsx +2 -2
  156. package/src/ui/components/OxyProvider.tsx +4 -4
  157. package/src/ui/components/Section.tsx +7 -7
  158. package/src/ui/components/SectionTitle.tsx +2 -2
  159. package/src/ui/components/StepBasedScreen.README.md +337 -0
  160. package/src/ui/components/StepBasedScreen.tsx +417 -0
  161. package/src/ui/components/icon/FAIRWalletIcon.tsx +2 -2
  162. package/src/ui/components/icon/OxyIcon.tsx +10 -11
  163. package/src/ui/components/internal/PinInput.tsx +13 -4
  164. package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +1 -1
  165. package/src/ui/context/OxyContext.tsx +12 -11
  166. package/src/ui/screens/PaymentGatewayScreen.tsx +3 -3
  167. package/src/ui/screens/ProfileScreen.tsx +54 -54
  168. package/src/ui/screens/RecoverAccountScreen.tsx +98 -211
  169. package/src/ui/screens/SignInScreen.tsx +148 -271
  170. package/src/ui/screens/SignUpScreen.tsx +146 -748
  171. package/src/ui/screens/internal/SignInPasswordStep.tsx +3 -3
  172. package/src/ui/screens/internal/SignInUsernameStep.tsx +2 -2
  173. package/src/ui/screens/steps/RecoverRequestStep.tsx +130 -0
  174. package/src/ui/screens/steps/RecoverSuccessStep.tsx +131 -0
  175. package/src/ui/screens/steps/RecoverVerifyStep.tsx +153 -0
  176. package/src/ui/screens/steps/SignInPasswordStep.tsx +172 -0
  177. package/src/ui/screens/steps/SignInUsernameStep.tsx +176 -0
  178. package/src/ui/screens/steps/SignUpIdentityStep.tsx +204 -0
  179. package/src/ui/screens/steps/SignUpSecurityStep.tsx +191 -0
  180. package/src/ui/screens/steps/SignUpSummaryStep.tsx +130 -0
  181. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +65 -0
@@ -1,364 +1,70 @@
1
1
  "use strict";
2
2
 
3
- import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
4
- import { View, Text, TextInput, StyleSheet, ActivityIndicator, Platform, KeyboardAvoidingView, ScrollView, Animated, StatusBar } from 'react-native';
3
+ import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
5
4
  import { useOxy } from '../context/OxyContext';
6
- import { useThemeColors, createAuthStyles } from '../styles';
7
- import { Ionicons } from '@expo/vector-icons';
5
+ import { useThemeColors } from '../styles';
8
6
  import { toast } from '../../lib/sonner';
9
- import SignUpIdentityStep from './internal/SignUpIdentityStep';
10
- import SignUpSecurityStep from './internal/SignUpSecurityStep';
11
- import SignUpSummaryStep from './internal/SignUpSummaryStep';
12
- import SignUpWelcomeStep from './internal/SignUpWelcomeStep';
7
+ import StepBasedScreen from '../components/StepBasedScreen';
8
+ import SignUpWelcomeStep from './steps/SignUpWelcomeStep';
9
+ import SignUpIdentityStep from './steps/SignUpIdentityStep';
10
+ import SignUpSecurityStep from './steps/SignUpSecurityStep';
11
+ import SignUpSummaryStep from './steps/SignUpSummaryStep';
13
12
 
14
13
  // Types for better type safety
15
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import { jsx as _jsx } from "react/jsx-runtime";
16
15
  // Constants
17
16
  const USERNAME_MIN_LENGTH = 3;
18
17
  const PASSWORD_MIN_LENGTH = 8;
19
- const VALIDATION_DEBOUNCE_MS = 800;
20
- const CACHE_DURATION_MS = 5 * 60 * 1000; // 5 minutes
21
18
 
22
19
  // Email validation regex
23
20
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
24
21
 
25
- // Styles factory function
26
- const createStyles = (colors, theme) => StyleSheet.create({
27
- container: {
28
- flex: 1
29
- },
30
- scrollContent: {
31
- flexGrow: 1,
32
- paddingHorizontal: 24,
33
- paddingTop: 4,
34
- paddingBottom: 20
35
- },
36
- stepContainer: {
37
- flex: 1,
38
- justifyContent: 'flex-start',
39
- alignItems: 'flex-start'
40
- },
41
- modernHeader: {
42
- alignItems: 'flex-start',
43
- width: '100%',
44
- marginBottom: 24
45
- },
46
- modernTitle: {
47
- fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
48
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
49
- fontSize: 62,
50
- lineHeight: 48,
51
- marginBottom: 18,
52
- textAlign: 'left',
53
- letterSpacing: -1
54
- },
55
- modernSubtitle: {
56
- fontSize: 18,
57
- lineHeight: 24,
58
- textAlign: 'left',
59
- opacity: 0.8,
60
- marginBottom: 24
61
- },
62
- welcomeImageContainer: {
63
- alignItems: 'center',
64
- justifyContent: 'center',
65
- marginVertical: 20
66
- },
67
- welcomeTitle: {
68
- fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
69
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
70
- fontSize: 42,
71
- lineHeight: 48,
72
- marginBottom: 12,
73
- textAlign: 'left',
74
- letterSpacing: -1
75
- },
76
- welcomeText: {
77
- fontSize: 18,
78
- lineHeight: 24,
79
- textAlign: 'left',
80
- opacity: 0.8,
81
- marginBottom: 24
82
- },
83
- stepTitle: {
84
- fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
85
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
86
- fontSize: 42,
87
- lineHeight: 48,
88
- marginBottom: 12,
89
- textAlign: 'left',
90
- letterSpacing: -1
91
- },
92
- inputContainer: {
93
- width: '100%',
94
- marginBottom: 24
95
- },
96
- premiumInputWrapper: {
97
- flexDirection: 'row',
98
- alignItems: 'center',
99
- height: 56,
100
- borderRadius: 16,
101
- paddingHorizontal: 20,
102
- borderWidth: 2,
103
- backgroundColor: colors.inputBackground
104
- },
105
- inputIcon: {
106
- marginRight: 12
107
- },
108
- inputContent: {
109
- flex: 1
110
- },
111
- modernLabel: {
112
- fontSize: 12,
113
- fontWeight: '500',
114
- marginBottom: 2
115
- },
116
- modernInput: {
117
- flex: 1,
118
- fontSize: 16,
119
- height: '100%'
120
- },
121
- validationIndicator: {
122
- marginLeft: 8
123
- },
124
- validationCard: {
125
- flexDirection: 'row',
126
- alignItems: 'center',
127
- padding: 12,
128
- borderRadius: 12,
129
- marginTop: 8,
130
- gap: 8
131
- },
132
- belowInputMessage: {
133
- flexDirection: 'row',
134
- alignItems: 'center',
135
- marginTop: 4,
136
- marginBottom: 0,
137
- gap: 6
138
- },
139
- belowInputText: {
140
- fontSize: 13,
141
- fontWeight: '500'
142
- },
143
- validationIconContainer: {
144
- width: 32,
145
- height: 32,
146
- borderRadius: 16,
147
- justifyContent: 'center',
148
- alignItems: 'center',
149
- marginRight: 12
150
- },
151
- validationTextContainer: {
152
- flex: 1
153
- },
154
- validationTitle: {
155
- fontSize: 12,
156
- fontWeight: '600',
157
- marginBottom: 2
158
- },
159
- validationSubtitle: {
160
- fontSize: 11,
161
- opacity: 0.8
162
- },
163
- passwordToggle: {
164
- padding: 4
165
- },
166
- passwordHint: {
167
- fontSize: 12,
168
- marginTop: 4
169
- },
170
- button: {
171
- flexDirection: 'row',
172
- alignItems: 'center',
173
- justifyContent: 'center',
174
- paddingVertical: 18,
175
- paddingHorizontal: 32,
176
- borderRadius: 16,
177
- marginVertical: 8,
178
- gap: 8,
179
- width: '100%',
180
- ...Platform.select({
181
- web: {
182
- boxShadow: '0 4px 8px rgba(0,0,0,0.3)'
183
- },
184
- default: {
185
- shadowOffset: {
186
- width: 0,
187
- height: 4
188
- },
189
- shadowOpacity: 0.3,
190
- shadowRadius: 8,
191
- elevation: 6
192
- }
193
- })
194
- },
195
- buttonText: {
196
- color: '#FFFFFF',
197
- fontSize: 16,
198
- fontWeight: '600',
199
- letterSpacing: 0.5
200
- },
201
- footerTextContainer: {
202
- flexDirection: 'row',
203
- justifyContent: 'center',
204
- marginTop: 16
205
- },
206
- footerText: {
207
- fontSize: 15
208
- },
209
- linkText: {
210
- fontSize: 14,
211
- lineHeight: 20,
212
- fontWeight: '600',
213
- textDecorationLine: 'underline'
214
- },
215
- userInfoContainer: {
216
- padding: 20,
217
- marginVertical: 20,
218
- borderRadius: 24,
219
- alignItems: 'center',
220
- ...Platform.select({
221
- web: {
222
- boxShadow: '0 1px 4px rgba(0,0,0,0.04)'
223
- },
224
- default: {
225
- shadowColor: '#000',
226
- shadowOpacity: 0.04,
227
- shadowOffset: {
228
- width: 0,
229
- height: 1
230
- },
231
- shadowRadius: 4,
232
- elevation: 1
233
- }
234
- })
235
- },
236
- userInfoText: {
237
- fontSize: 16,
238
- marginBottom: 8,
239
- textAlign: 'center'
240
- },
241
- actionButtonsContainer: {
242
- marginTop: 24
243
- },
244
- navigationButtons: {
245
- flexDirection: 'row',
246
- justifyContent: 'center',
247
- marginTop: 16,
248
- marginBottom: 8,
249
- width: '100%',
250
- gap: 8
251
- },
252
- navButton: {
253
- flexDirection: 'row',
254
- alignItems: 'center',
255
- paddingVertical: 6,
256
- paddingHorizontal: 12,
257
- gap: 6,
258
- minWidth: 70,
259
- borderWidth: 1,
260
- ...Platform.select({
261
- web: {
262
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
263
- },
264
- default: {
265
- shadowOffset: {
266
- width: 0,
267
- height: 2
268
- },
269
- shadowOpacity: 0.1,
270
- shadowRadius: 4,
271
- elevation: 2
272
- }
273
- })
274
- },
275
- backButton: {
276
- backgroundColor: 'transparent',
277
- borderTopLeftRadius: 35,
278
- borderBottomLeftRadius: 35,
279
- borderTopRightRadius: 12,
280
- borderBottomRightRadius: 12
281
- },
282
- nextButton: {
283
- backgroundColor: 'transparent',
284
- borderTopRightRadius: 35,
285
- borderBottomRightRadius: 35,
286
- borderTopLeftRadius: 12,
287
- borderBottomLeftRadius: 12
288
- },
289
- navButtonText: {
290
- fontSize: 13,
291
- fontWeight: '500'
292
- },
293
- progressContainer: {
294
- flexDirection: 'row',
295
- justifyContent: 'center',
296
- marginBottom: 20,
297
- marginTop: 8
298
- },
299
- progressDot: {
300
- height: 10,
301
- width: 10,
302
- borderRadius: 5,
303
- marginHorizontal: 6,
304
- borderWidth: 2,
305
- borderColor: '#fff',
306
- ...Platform.select({
307
- web: {
308
- boxShadow: '0 1px 2px rgba(0,0,0,0.08)'
309
- },
310
- default: {
311
- shadowColor: colors.primary,
312
- shadowOpacity: 0.08,
313
- shadowOffset: {
314
- width: 0,
315
- height: 1
316
- },
317
- shadowRadius: 2,
318
- elevation: 1
319
- }
320
- })
321
- },
322
- summaryContainer: {
323
- padding: 0,
324
- marginBottom: 24,
325
- width: '100%'
326
- },
327
- summaryRow: {
328
- flexDirection: 'row',
329
- marginBottom: 10
330
- },
331
- summaryLabel: {
332
- fontSize: 15,
333
- width: 90
334
- },
335
- summaryValue: {
336
- fontSize: 15,
337
- fontWeight: '600',
338
- flex: 1
339
- }
340
- });
22
+ // Main component
23
+ const SignUpScreen = ({
24
+ navigate,
25
+ goBack,
26
+ onAuthenticated,
27
+ theme
28
+ }) => {
29
+ const {
30
+ signUp,
31
+ oxyServices
32
+ } = useOxy();
33
+ const colors = useThemeColors(theme);
341
34
 
342
- // Custom hooks for better separation of concerns
343
- const useFormValidation = oxyServices => {
35
+ // Form data state
36
+ const [username, setUsername] = useState('');
37
+ const [email, setEmail] = useState('');
38
+ const [password, setPassword] = useState('');
39
+ const [confirmPassword, setConfirmPassword] = useState('');
40
+ const [showPassword, setShowPassword] = useState(false);
41
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
42
+ const [isLoading, setIsLoading] = useState(false);
43
+
44
+ // Validation state
344
45
  const [validationState, setValidationState] = useState({
345
46
  status: 'idle',
346
47
  message: ''
347
48
  });
348
- const validationCache = useRef(new Map());
349
- const validateUsername = useCallback(async username => {
350
- if (!username || username.length < USERNAME_MIN_LENGTH) {
49
+
50
+ // Error message state
51
+ const [errorMessage, setErrorMessage] = useState('');
52
+
53
+ // Username validation with caching
54
+ const usernameCache = useRef(new Map());
55
+ const validateUsername = useCallback(async usernameToValidate => {
56
+ if (!usernameToValidate || usernameToValidate.length < USERNAME_MIN_LENGTH) {
351
57
  setValidationState({
352
58
  status: 'invalid',
353
- message: ''
59
+ message: 'Username must be at least 3 characters'
354
60
  });
355
61
  return false;
356
62
  }
357
63
 
358
64
  // Check cache first
359
- const cached = validationCache.current.get(username);
65
+ const cached = usernameCache.current.get(usernameToValidate);
360
66
  const now = Date.now();
361
- if (cached && now - cached.timestamp < CACHE_DURATION_MS) {
67
+ if (cached && now - cached.timestamp < 5 * 60 * 1000) {
362
68
  const isValid = cached.available;
363
69
  setValidationState({
364
70
  status: isValid ? 'valid' : 'invalid',
@@ -371,11 +77,11 @@ const useFormValidation = oxyServices => {
371
77
  message: ''
372
78
  });
373
79
  try {
374
- const result = await oxyServices.checkUsernameAvailability(username);
80
+ const result = await oxyServices.checkUsernameAvailability(usernameToValidate);
375
81
  const isValid = result.available;
376
82
 
377
83
  // Cache the result
378
- validationCache.current.set(username, {
84
+ usernameCache.current.set(usernameToValidate, {
379
85
  available: isValid,
380
86
  timestamp: now
381
87
  });
@@ -393,435 +99,127 @@ const useFormValidation = oxyServices => {
393
99
  return false;
394
100
  }
395
101
  }, [oxyServices]);
396
- const validateEmail = useCallback(email => {
397
- return EMAIL_REGEX.test(email);
398
- }, []);
399
- const validatePassword = useCallback(password => {
400
- return password.length >= PASSWORD_MIN_LENGTH;
401
- }, []);
402
- const validatePasswordsMatch = useCallback((password, confirmPassword) => {
403
- return password === confirmPassword;
404
- }, []);
405
102
 
406
- // Cleanup cache on unmount
407
- useEffect(() => {
408
- return () => {
409
- validationCache.current.clear();
410
- };
411
- }, []);
412
- return {
413
- validationState,
414
- validateUsername,
415
- validateEmail,
416
- validatePassword,
417
- validatePasswordsMatch
418
- };
419
- };
420
- const useFormData = () => {
421
- const [formData, setFormData] = useState({
422
- username: '',
423
- email: '',
424
- password: '',
425
- confirmPassword: ''
426
- });
427
- const [passwordVisibility, setPasswordVisibility] = useState({
428
- password: false,
429
- confirmPassword: false
430
- });
431
- const updateField = useCallback((field, value) => {
432
- setFormData(prev => ({
433
- ...prev,
434
- [field]: value
435
- }));
436
- }, []);
437
- const togglePasswordVisibility = useCallback(field => {
438
- setPasswordVisibility(prev => ({
439
- ...prev,
440
- [field]: !prev[field]
441
- }));
442
- }, []);
443
- const resetForm = useCallback(() => {
444
- setFormData({
445
- username: '',
446
- email: '',
447
- password: '',
448
- confirmPassword: ''
449
- });
450
- setPasswordVisibility({
451
- password: false,
452
- confirmPassword: false
453
- });
103
+ // Email validation
104
+ const validateEmail = useCallback(emailToValidate => {
105
+ return EMAIL_REGEX.test(emailToValidate);
454
106
  }, []);
455
- return {
456
- formData,
457
- passwordVisibility,
458
- updateField,
459
- togglePasswordVisibility,
460
- resetForm
461
- };
462
- };
463
-
464
- // Reusable components
465
- const ValidationIndicator = /*#__PURE__*/React.memo(({
466
- status,
467
- colors,
468
- styles
469
- }) => {
470
- if (status === 'validating') {
471
- return /*#__PURE__*/_jsx(ActivityIndicator, {
472
- size: "small",
473
- color: colors.primary,
474
- style: styles.validationIndicator
475
- });
476
- }
477
- if (status === 'valid') {
478
- return /*#__PURE__*/_jsx(Ionicons, {
479
- name: "checkmark-circle",
480
- size: 22,
481
- color: colors.success,
482
- style: styles.validationIndicator
483
- });
484
- }
485
- if (status === 'invalid') {
486
- return /*#__PURE__*/_jsx(Ionicons, {
487
- name: "close-circle",
488
- size: 22,
489
- color: colors.error,
490
- style: styles.validationIndicator
491
- });
492
- }
493
- return null;
494
- });
495
- const ValidationMessage = /*#__PURE__*/React.memo(({
496
- validationState,
497
- colors,
498
- styles
499
- }) => {
500
- if (validationState.status === 'idle' || !validationState.message) return null;
501
- const isSuccess = validationState.status === 'valid';
502
- const backgroundColor = isSuccess ? colors.success + '10' : colors.error + '10';
503
- const borderColor = isSuccess ? colors.success + '30' : colors.error + '30';
504
- const iconColor = isSuccess ? colors.success : colors.error;
505
- const iconName = isSuccess ? 'checkmark-circle' : 'alert-circle';
506
- const title = isSuccess ? 'Username Available' : 'Username Taken';
507
- const subtitle = isSuccess ? 'Good choice! This username is available' : validationState.message;
508
- return /*#__PURE__*/_jsxs(View, {
509
- style: [styles.validationCard, {
510
- backgroundColor,
511
- borderColor
512
- }],
513
- children: [/*#__PURE__*/_jsx(View, {
514
- style: [styles.validationIconContainer, {
515
- backgroundColor: iconColor + '20'
516
- }],
517
- children: /*#__PURE__*/_jsx(Ionicons, {
518
- name: iconName,
519
- size: 16,
520
- color: iconColor
521
- })
522
- }), /*#__PURE__*/_jsxs(View, {
523
- style: styles.validationTextContainer,
524
- children: [/*#__PURE__*/_jsx(Text, {
525
- style: [styles.validationTitle, {
526
- color: iconColor
527
- }],
528
- children: title
529
- }), /*#__PURE__*/_jsx(Text, {
530
- style: [styles.validationSubtitle, {
531
- color: colors.secondaryText
532
- }],
533
- children: subtitle
534
- })]
535
- })]
536
- });
537
- });
538
- const FormInput = /*#__PURE__*/React.memo(({
539
- icon,
540
- label,
541
- value,
542
- onChangeText,
543
- secureTextEntry = false,
544
- keyboardType = 'default',
545
- autoCapitalize = 'sentences',
546
- autoCorrect = true,
547
- testID,
548
- colors,
549
- styles,
550
- borderColor,
551
- rightComponent
552
- }) => /*#__PURE__*/_jsx(View, {
553
- style: styles.inputContainer,
554
- children: /*#__PURE__*/_jsxs(View, {
555
- style: [styles.premiumInputWrapper, {
556
- borderColor: borderColor || colors.border,
557
- backgroundColor: colors.inputBackground,
558
- shadowColor: colors.primary,
559
- shadowOffset: {
560
- width: 0,
561
- height: 4
562
- },
563
- shadowOpacity: 0.1,
564
- shadowRadius: 12,
565
- elevation: 3
566
- }],
567
- children: [/*#__PURE__*/_jsx(Ionicons, {
568
- name: icon,
569
- size: 22,
570
- color: colors.secondaryText,
571
- style: styles.inputIcon
572
- }), /*#__PURE__*/_jsxs(View, {
573
- style: styles.inputContent,
574
- children: [/*#__PURE__*/_jsx(Text, {
575
- style: [styles.modernLabel, {
576
- color: colors.secondaryText
577
- }],
578
- children: label
579
- }), /*#__PURE__*/_jsx(TextInput, {
580
- style: [styles.modernInput, {
581
- color: colors.text
582
- }],
583
- value: value,
584
- onChangeText: onChangeText,
585
- secureTextEntry: secureTextEntry,
586
- keyboardType: keyboardType,
587
- autoCapitalize: autoCapitalize,
588
- autoCorrect: autoCorrect,
589
- testID: testID,
590
- placeholderTextColor: "transparent"
591
- })]
592
- }), rightComponent]
593
- })
594
- }));
595
- const ProgressIndicator = /*#__PURE__*/React.memo(({
596
- currentStep,
597
- totalSteps,
598
- colors,
599
- styles
600
- }) => /*#__PURE__*/_jsx(View, {
601
- style: styles.progressContainer,
602
- children: Array.from({
603
- length: totalSteps
604
- }, (_, index) => /*#__PURE__*/_jsx(View, {
605
- style: [styles.progressDot, currentStep === index ? {
606
- backgroundColor: colors.primary,
607
- width: 24
608
- } : {
609
- backgroundColor: colors.border
610
- }]
611
- }, index))
612
- }));
613
-
614
- // Main component
615
- const SignUpScreen = ({
616
- navigate,
617
- goBack,
618
- onAuthenticated,
619
- theme
620
- }) => {
621
- const {
622
- signUp,
623
- isLoading,
624
- user,
625
- isAuthenticated,
626
- oxyServices
627
- } = useOxy();
628
- const colors = useThemeColors(theme);
629
-
630
- // Form state
631
- const {
632
- formData,
633
- passwordVisibility,
634
- updateField,
635
- togglePasswordVisibility,
636
- resetForm
637
- } = useFormData();
638
- const {
639
- validationState,
640
- validateUsername,
641
- validateEmail,
642
- validatePassword,
643
- validatePasswordsMatch
644
- } = useFormValidation(oxyServices);
645
-
646
- // UI state
647
- const [currentStep, setCurrentStep] = useState(0);
648
- const [errorMessage, setErrorMessage] = useState('');
649
-
650
- // Animation refs
651
- const fadeAnim = useRef(new Animated.Value(1)).current;
652
- const slideAnim = useRef(new Animated.Value(0)).current;
653
107
 
654
- // Memoized styles
655
- const styles = useMemo(() => createAuthStyles(colors, theme), [colors, theme]);
108
+ // Password validation
109
+ const validatePassword = useCallback(passwordToValidate => {
110
+ return passwordToValidate.length >= PASSWORD_MIN_LENGTH;
111
+ }, []);
656
112
 
657
- // Debounced username validation
658
- useEffect(() => {
659
- if (!formData.username || formData.username.length < USERNAME_MIN_LENGTH) {
113
+ // Handle form completion
114
+ const handleComplete = useCallback(async stepData => {
115
+ if (!username || !email || !password) {
116
+ toast.error('Please fill in all required fields');
660
117
  return;
661
118
  }
662
- const timeoutId = setTimeout(() => {
663
- validateUsername(formData.username);
664
- }, VALIDATION_DEBOUNCE_MS);
665
- return () => clearTimeout(timeoutId);
666
- }, [formData.username, validateUsername]);
667
-
668
- // Animation functions
669
- const animateTransition = useCallback(nextStep => {
670
- Animated.timing(fadeAnim, {
671
- toValue: 0,
672
- duration: 250,
673
- useNativeDriver: Platform.OS !== 'web'
674
- }).start(() => {
675
- setCurrentStep(nextStep);
676
- slideAnim.setValue(-100);
677
- Animated.parallel([Animated.timing(fadeAnim, {
678
- toValue: 1,
679
- duration: 250,
680
- useNativeDriver: Platform.OS !== 'web'
681
- }), Animated.timing(slideAnim, {
682
- toValue: 0,
683
- duration: 300,
684
- useNativeDriver: Platform.OS !== 'web'
685
- })]).start();
686
- });
687
- }, [fadeAnim, slideAnim]);
688
- const nextStep = useCallback(() => {
689
- if (currentStep < 3) {
690
- animateTransition(currentStep + 1);
691
- }
692
- }, [currentStep, animateTransition]);
693
- const prevStep = useCallback(() => {
694
- if (currentStep > 0) {
695
- animateTransition(currentStep - 1);
696
- }
697
- }, [currentStep, animateTransition]);
698
-
699
- // Form validation helpers
700
- const isIdentityStepValid = useCallback(() => {
701
- return formData.username && formData.email && validateEmail(formData.email) && validationState.status === 'valid';
702
- }, [formData.username, formData.email, validateEmail, validationState.status]);
703
- const isSecurityStepValid = useCallback(() => {
704
- return formData.password && validatePassword(formData.password) && validatePasswordsMatch(formData.password, formData.confirmPassword);
705
- }, [formData.password, formData.confirmPassword, validatePassword, validatePasswordsMatch]);
706
-
707
- // Custom next handlers for validation
708
- const handleIdentityNext = useCallback(() => {
709
- if (!isIdentityStepValid()) {
710
- toast.error('Please enter a valid username and email.');
119
+ if (!validateEmail(email)) {
120
+ toast.error('Please enter a valid email address');
711
121
  return;
712
122
  }
713
- nextStep();
714
- }, [isIdentityStepValid, nextStep]);
715
- const handleSecurityNext = useCallback(() => {
716
- if (!isSecurityStepValid()) {
717
- toast.error('Please enter a valid password and confirm it.');
123
+ if (!validatePassword(password)) {
124
+ toast.error('Password must be at least 8 characters long');
718
125
  return;
719
126
  }
720
- nextStep();
721
- }, [isSecurityStepValid, nextStep]);
722
-
723
- // Sign up handler
724
- const handleSignUp = useCallback(async () => {
725
- if (!isIdentityStepValid() || !isSecurityStepValid()) {
726
- toast.error('Please fill in all fields correctly');
127
+ if (password !== confirmPassword) {
128
+ toast.error('Passwords do not match');
727
129
  return;
728
130
  }
729
131
  try {
730
- setErrorMessage('');
731
- const user = await signUp(formData.username, formData.email, formData.password);
132
+ setIsLoading(true);
133
+ const user = await signUp(username, email, password);
732
134
  toast.success('Account created successfully! Welcome to Oxy!');
733
135
 
734
- // Instead of finalizing immediately, route to post-signup welcome & avatar setup
136
+ // Navigate to welcome screen or handle authentication
735
137
  navigate('WelcomeNewUser', {
736
138
  newUser: user
737
139
  });
738
- resetForm(); // Clear the form for potential future use
739
140
  } catch (error) {
740
141
  toast.error(error.message || 'Sign up failed');
142
+ } finally {
143
+ setIsLoading(false);
741
144
  }
742
- }, [formData, isIdentityStepValid, isSecurityStepValid, signUp, onAuthenticated, resetForm]);
145
+ }, [username, email, password, confirmPassword, validateEmail, validatePassword, signUp, navigate]);
146
+
147
+ // Cleanup cache on unmount
148
+ useEffect(() => {
149
+ return () => {
150
+ usernameCache.current.clear();
151
+ };
152
+ }, []);
743
153
 
744
- // Memoized step components
745
- const updateFieldString = (field, value) => updateField(field, value);
746
- const validatePasswordsMatchNoArgs = () => validatePasswordsMatch(formData.password, formData.confirmPassword);
747
- const togglePasswordVisibilityNoArgs = () => togglePasswordVisibility('password');
748
- const renderWelcomeStep = useMemo(() => /*#__PURE__*/_jsx(SignUpWelcomeStep, {
749
- styles: styles,
750
- fadeAnim: fadeAnim,
751
- slideAnim: slideAnim,
752
- colors: colors,
753
- nextStep: nextStep,
754
- navigate: navigate
755
- }), [styles, fadeAnim, slideAnim, colors, nextStep, navigate]);
756
- const renderIdentityStep = useMemo(() => /*#__PURE__*/_jsx(SignUpIdentityStep, {
757
- styles: styles,
758
- fadeAnim: fadeAnim,
759
- slideAnim: slideAnim,
760
- colors: colors,
761
- formData: formData,
762
- validationState: validationState,
763
- updateField: updateFieldString,
764
- setErrorMessage: setErrorMessage,
765
- prevStep: prevStep,
766
- handleIdentityNext: handleIdentityNext,
767
- ValidationMessage: ValidationMessage,
768
- validateEmail: validateEmail,
769
- navigate: navigate
770
- }), [styles, fadeAnim, slideAnim, colors, formData, validationState, updateFieldString, setErrorMessage, prevStep, handleIdentityNext, ValidationMessage, validateEmail, navigate]);
771
- const renderSecurityStep = useMemo(() => /*#__PURE__*/_jsx(SignUpSecurityStep, {
772
- styles: styles,
773
- fadeAnim: fadeAnim,
774
- slideAnim: slideAnim,
775
- colors: colors,
776
- formData: formData,
777
- passwordVisibility: passwordVisibility,
778
- updateField: updateFieldString,
779
- validatePassword: validatePassword,
780
- validatePasswordsMatch: validatePasswordsMatchNoArgs,
781
- prevStep: prevStep,
782
- handleSecurityNext: handleSecurityNext,
783
- setErrorMessage: setErrorMessage,
784
- togglePasswordVisibility: togglePasswordVisibilityNoArgs,
785
- PASSWORD_MIN_LENGTH: PASSWORD_MIN_LENGTH
786
- }), [styles, fadeAnim, slideAnim, colors, formData, passwordVisibility, updateFieldString, validatePassword, validatePasswordsMatchNoArgs, prevStep, handleSecurityNext, setErrorMessage, togglePasswordVisibilityNoArgs, PASSWORD_MIN_LENGTH]);
787
- const renderSummaryStep = useMemo(() => /*#__PURE__*/_jsx(SignUpSummaryStep, {
788
- styles: styles,
789
- fadeAnim: fadeAnim,
790
- slideAnim: slideAnim,
791
- colors: colors,
792
- formData: formData,
793
- isLoading: isLoading,
794
- handleSignUp: handleSignUp,
795
- prevStep: prevStep
796
- }), [styles, fadeAnim, slideAnim, colors, formData, isLoading, handleSignUp, prevStep]);
797
- const renderCurrentStep = useCallback(() => {
798
- switch (currentStep) {
799
- case 0:
800
- return renderWelcomeStep;
801
- case 1:
802
- return renderIdentityStep;
803
- case 2:
804
- return renderSecurityStep;
805
- case 3:
806
- return renderSummaryStep;
807
- default:
808
- return renderWelcomeStep;
154
+ // Step configurations
155
+ const steps = useMemo(() => [{
156
+ id: 'welcome',
157
+ component: SignUpWelcomeStep,
158
+ canProceed: () => true
159
+ }, {
160
+ id: 'identity',
161
+ component: SignUpIdentityStep,
162
+ canProceed: () => !!(username.trim() && email.trim() && validateEmail(email) && validationState.status === 'valid'),
163
+ onEnter: () => {
164
+ // Auto-validate username when entering this step
165
+ if (username && validationState.status === 'idle') {
166
+ validateUsername(username);
167
+ }
809
168
  }
810
- }, [currentStep, renderWelcomeStep, renderIdentityStep, renderSecurityStep, renderSummaryStep]);
811
- return /*#__PURE__*/_jsxs(KeyboardAvoidingView, {
812
- style: [styles.container, {
813
- backgroundColor: colors.background
814
- }],
815
- behavior: Platform.OS === 'ios' ? 'padding' : 'height',
816
- children: [/*#__PURE__*/_jsx(StatusBar, {
817
- barStyle: theme === 'dark' ? 'light-content' : 'dark-content',
818
- backgroundColor: colors.background
819
- }), /*#__PURE__*/_jsx(ScrollView, {
820
- contentContainerStyle: styles.scrollContent,
821
- showsVerticalScrollIndicator: false,
822
- keyboardShouldPersistTaps: "handled",
823
- children: renderCurrentStep()
824
- })]
169
+ }, {
170
+ id: 'security',
171
+ component: SignUpSecurityStep,
172
+ canProceed: () => !!(password && validatePassword(password) && password === confirmPassword)
173
+ }, {
174
+ id: 'summary',
175
+ component: SignUpSummaryStep,
176
+ canProceed: () => true
177
+ }], [username, email, password, confirmPassword, validationState.status, validateEmail, validatePassword, validateUsername]);
178
+
179
+ // Step data for the reusable component
180
+ const stepData = useMemo(() => [
181
+ // Welcome step - no data needed
182
+ {},
183
+ // Identity step
184
+ {
185
+ username,
186
+ email,
187
+ setUsername,
188
+ setEmail,
189
+ validationState,
190
+ setValidationState,
191
+ setErrorMessage,
192
+ validateEmail,
193
+ validateUsername
194
+ },
195
+ // Security step
196
+ {
197
+ password,
198
+ confirmPassword,
199
+ setPassword,
200
+ setConfirmPassword,
201
+ showPassword,
202
+ showConfirmPassword,
203
+ setShowPassword,
204
+ setShowConfirmPassword,
205
+ setErrorMessage,
206
+ validatePassword
207
+ },
208
+ // Summary step
209
+ {
210
+ isLoading
211
+ }], [username, email, password, confirmPassword, showPassword, showConfirmPassword, validationState, errorMessage, validateEmail, validatePassword, isLoading]);
212
+ return /*#__PURE__*/_jsx(StepBasedScreen, {
213
+ steps: steps,
214
+ stepData: stepData,
215
+ onComplete: handleComplete,
216
+ navigate: navigate,
217
+ goBack: goBack,
218
+ onAuthenticated: onAuthenticated,
219
+ theme: theme,
220
+ showProgressIndicator: true,
221
+ enableAnimations: true,
222
+ oxyServices: oxyServices
825
223
  });
826
224
  };
827
225
  export default SignUpScreen;