@oxyhq/services 5.4.3 → 5.4.5

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 (233) hide show
  1. package/README.md +14 -0
  2. package/lib/commonjs/assets/assets/illustrations/HighFive.tsx +41 -0
  3. package/lib/commonjs/assets/icons/OxyServices.js +1 -1
  4. package/lib/commonjs/assets/illustrations/HighFive.js +61 -0
  5. package/lib/commonjs/assets/illustrations/HighFive.js.map +1 -0
  6. package/lib/commonjs/core/index.js +24 -5
  7. package/lib/commonjs/core/index.js.map +1 -1
  8. package/lib/commonjs/index.js +72 -23
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/node/createAuth.js +95 -0
  11. package/lib/commonjs/node/createAuth.js.map +1 -0
  12. package/lib/commonjs/node/index.js +15 -6
  13. package/lib/commonjs/node/index.js.map +1 -1
  14. package/lib/commonjs/package.json +1 -0
  15. package/lib/commonjs/ui/components/Avatar.js +3 -3
  16. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  17. package/lib/commonjs/ui/components/FollowButton.js +82 -34
  18. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  19. package/lib/commonjs/ui/components/GroupedSection.js +1 -1
  20. package/lib/commonjs/ui/components/OxyLogo.js +1 -1
  21. package/lib/commonjs/ui/components/OxyProvider.js +146 -141
  22. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  23. package/lib/commonjs/ui/components/OxySignInButton.js +4 -4
  24. package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
  25. package/lib/commonjs/ui/components/ProfileCard.js +2 -2
  26. package/lib/commonjs/ui/components/Section.js +1 -1
  27. package/lib/commonjs/ui/components/SectionTitle.js +1 -1
  28. package/lib/commonjs/ui/components/icon/index.js +1 -1
  29. package/lib/commonjs/ui/components/index.js +12 -12
  30. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +213 -0
  31. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -0
  32. package/lib/commonjs/ui/components/internal/TextField.js +576 -0
  33. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -0
  34. package/lib/commonjs/ui/context/OxyContext.js +12 -2
  35. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  36. package/lib/commonjs/ui/hooks/index.js +13 -0
  37. package/lib/commonjs/ui/hooks/index.js.map +1 -0
  38. package/lib/commonjs/ui/hooks/useFollow.js +184 -0
  39. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -0
  40. package/lib/commonjs/ui/index.js +44 -12
  41. package/lib/commonjs/ui/index.js.map +1 -1
  42. package/lib/commonjs/ui/navigation/OxyRouter.js +23 -18
  43. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  44. package/lib/commonjs/ui/screens/AccountCenterScreen.js +21 -20
  45. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  46. package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
  47. package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
  48. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +11 -10
  49. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  50. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +8 -7
  51. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  52. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +6 -5
  53. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  54. package/lib/commonjs/ui/screens/AppInfoScreen.js +12 -14
  55. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  56. package/lib/commonjs/ui/screens/BillingManagementScreen.js +3 -3
  57. package/lib/commonjs/ui/screens/FeedbackScreen.js +1169 -0
  58. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -0
  59. package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -3
  60. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +3 -3
  61. package/lib/commonjs/ui/screens/ProfileScreen.js +2 -2
  62. package/lib/commonjs/ui/screens/SessionManagementScreen.js +2 -2
  63. package/lib/commonjs/ui/screens/SignInScreen.js +183 -305
  64. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  65. package/lib/commonjs/ui/screens/SignUpScreen.js +811 -712
  66. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  67. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +8 -7
  68. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  69. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
  70. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
  71. package/lib/commonjs/ui/store/index.js +267 -0
  72. package/lib/commonjs/ui/store/index.js.map +1 -0
  73. package/lib/commonjs/ui/styles/index.js +2 -2
  74. package/lib/commonjs/ui/styles/theme.js +1 -1
  75. package/lib/commonjs/utils/index.js +1 -1
  76. package/lib/module/assets/assets/illustrations/HighFive.tsx +41 -0
  77. package/lib/module/assets/icons/OxyServices.js +1 -1
  78. package/lib/module/assets/icons/OxyServices.js.map +1 -1
  79. package/lib/module/assets/illustrations/HighFive.js +55 -0
  80. package/lib/module/assets/illustrations/HighFive.js.map +1 -0
  81. package/lib/module/core/index.js +24 -5
  82. package/lib/module/core/index.js.map +1 -1
  83. package/lib/module/index.js +15 -11
  84. package/lib/module/index.js.map +1 -1
  85. package/lib/module/node/createAuth.js +90 -0
  86. package/lib/module/node/createAuth.js.map +1 -0
  87. package/lib/module/node/index.js +8 -4
  88. package/lib/module/node/index.js.map +1 -1
  89. package/lib/module/package.json +1 -0
  90. package/lib/module/ui/components/Avatar.js +2 -2
  91. package/lib/module/ui/components/Avatar.js.map +1 -1
  92. package/lib/module/ui/components/FollowButton.js +83 -35
  93. package/lib/module/ui/components/FollowButton.js.map +1 -1
  94. package/lib/module/ui/components/GroupedSection.js +1 -1
  95. package/lib/module/ui/components/GroupedSection.js.map +1 -1
  96. package/lib/module/ui/components/OxyLogo.js +1 -1
  97. package/lib/module/ui/components/OxyLogo.js.map +1 -1
  98. package/lib/module/ui/components/OxyProvider.js +143 -138
  99. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  100. package/lib/module/ui/components/OxySignInButton.js +4 -4
  101. package/lib/module/ui/components/OxySignInButton.js.map +1 -1
  102. package/lib/module/ui/components/ProfileCard.js +2 -2
  103. package/lib/module/ui/components/ProfileCard.js.map +1 -1
  104. package/lib/module/ui/components/Section.js +1 -1
  105. package/lib/module/ui/components/Section.js.map +1 -1
  106. package/lib/module/ui/components/SectionTitle.js +1 -1
  107. package/lib/module/ui/components/SectionTitle.js.map +1 -1
  108. package/lib/module/ui/components/icon/index.js +1 -1
  109. package/lib/module/ui/components/icon/index.js.map +1 -1
  110. package/lib/module/ui/components/index.js +12 -12
  111. package/lib/module/ui/components/index.js.map +1 -1
  112. package/lib/module/ui/components/internal/GroupedPillButtons.js +208 -0
  113. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -0
  114. package/lib/module/ui/components/internal/TextField.js +571 -0
  115. package/lib/module/ui/components/internal/TextField.js.map +1 -0
  116. package/lib/module/ui/context/OxyContext.js +12 -2
  117. package/lib/module/ui/context/OxyContext.js.map +1 -1
  118. package/lib/module/ui/hooks/index.js +4 -0
  119. package/lib/module/ui/hooks/index.js.map +1 -0
  120. package/lib/module/ui/hooks/useFollow.js +180 -0
  121. package/lib/module/ui/hooks/useFollow.js.map +1 -0
  122. package/lib/module/ui/index.js +21 -10
  123. package/lib/module/ui/index.js.map +1 -1
  124. package/lib/module/ui/navigation/OxyRouter.js +23 -18
  125. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  126. package/lib/module/ui/screens/AccountCenterScreen.js +9 -8
  127. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  128. package/lib/module/ui/screens/AccountManagementDemo.js +2 -2
  129. package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
  130. package/lib/module/ui/screens/AccountOverviewScreen.js +11 -10
  131. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  132. package/lib/module/ui/screens/AccountSettingsScreen.js +8 -7
  133. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  134. package/lib/module/ui/screens/AccountSwitcherScreen.js +6 -5
  135. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  136. package/lib/module/ui/screens/AppInfoScreen.js +12 -14
  137. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  138. package/lib/module/ui/screens/BillingManagementScreen.js +3 -3
  139. package/lib/module/ui/screens/BillingManagementScreen.js.map +1 -1
  140. package/lib/module/ui/screens/FeedbackScreen.js +1164 -0
  141. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -0
  142. package/lib/module/ui/screens/FileManagementScreen.js +3 -3
  143. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  144. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +3 -3
  145. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  146. package/lib/module/ui/screens/ProfileScreen.js +2 -2
  147. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  148. package/lib/module/ui/screens/SessionManagementScreen.js +2 -2
  149. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  150. package/lib/module/ui/screens/SignInScreen.js +183 -305
  151. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  152. package/lib/module/ui/screens/SignUpScreen.js +810 -712
  153. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  154. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +8 -7
  155. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  156. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
  157. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  158. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
  159. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  160. package/lib/module/ui/store/index.js +255 -0
  161. package/lib/module/ui/store/index.js.map +1 -0
  162. package/lib/module/ui/styles/index.js +2 -2
  163. package/lib/module/ui/styles/index.js.map +1 -1
  164. package/lib/module/ui/styles/theme.js +1 -1
  165. package/lib/module/ui/styles/theme.js.map +1 -1
  166. package/lib/module/utils/index.js +1 -1
  167. package/lib/module/utils/index.js.map +1 -1
  168. package/lib/typescript/assets/illustrations/HighFive.d.ts +9 -0
  169. package/lib/typescript/assets/illustrations/HighFive.d.ts.map +1 -0
  170. package/lib/typescript/core/index.d.ts +16 -3
  171. package/lib/typescript/core/index.d.ts.map +1 -1
  172. package/lib/typescript/index.d.ts +4 -2
  173. package/lib/typescript/index.d.ts.map +1 -1
  174. package/lib/typescript/node/createAuth.d.ts +7 -0
  175. package/lib/typescript/node/createAuth.d.ts.map +1 -0
  176. package/lib/typescript/node/index.d.ts +2 -0
  177. package/lib/typescript/node/index.d.ts.map +1 -1
  178. package/lib/typescript/types/expo-vector-icons.d.ts +3 -0
  179. package/lib/typescript/types/express.d.ts +5 -0
  180. package/lib/typescript/types/react-redux.d.ts +5 -0
  181. package/lib/typescript/ui/components/FollowButton.d.ts +1 -0
  182. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  183. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  184. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts +18 -0
  185. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -0
  186. package/lib/typescript/ui/components/internal/TextField.d.ts +25 -0
  187. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -0
  188. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  189. package/lib/typescript/ui/hooks/index.d.ts +2 -0
  190. package/lib/typescript/ui/hooks/index.d.ts.map +1 -0
  191. package/lib/typescript/ui/hooks/useFollow.d.ts +43 -0
  192. package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -0
  193. package/lib/typescript/ui/index.d.ts +5 -0
  194. package/lib/typescript/ui/index.d.ts.map +1 -1
  195. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  196. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  197. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  198. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  199. package/lib/typescript/ui/screens/FeedbackScreen.d.ts +5 -0
  200. package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -0
  201. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  202. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  203. package/lib/typescript/ui/store/index.d.ts +66 -0
  204. package/lib/typescript/ui/store/index.d.ts.map +1 -0
  205. package/package.json +10 -25
  206. package/src/assets/illustrations/HighFive.tsx +41 -0
  207. package/src/core/index.ts +88 -3
  208. package/src/index.ts +19 -3
  209. package/src/node/createAuth.ts +116 -0
  210. package/src/node/index.ts +4 -0
  211. package/src/types/expo-vector-icons.d.ts +3 -0
  212. package/src/types/express.d.ts +5 -0
  213. package/src/types/react-redux.d.ts +5 -0
  214. package/src/ui/components/FollowButton.tsx +114 -56
  215. package/src/ui/components/OxyProvider.tsx +136 -135
  216. package/src/ui/components/OxySignInButton.tsx +2 -2
  217. package/src/ui/components/internal/GroupedPillButtons.tsx +253 -0
  218. package/src/ui/components/internal/TextField.tsx +694 -0
  219. package/src/ui/context/OxyContext.tsx +12 -2
  220. package/src/ui/hooks/index.ts +1 -0
  221. package/src/ui/hooks/useFollow.ts +173 -0
  222. package/src/ui/index.ts +15 -2
  223. package/src/ui/navigation/OxyRouter.tsx +8 -3
  224. package/src/ui/screens/AccountCenterScreen.tsx +17 -15
  225. package/src/ui/screens/AccountOverviewScreen.tsx +25 -25
  226. package/src/ui/screens/AccountSettingsScreen.tsx +30 -30
  227. package/src/ui/screens/AccountSwitcherScreen.tsx +34 -33
  228. package/src/ui/screens/AppInfoScreen.tsx +153 -155
  229. package/src/ui/screens/FeedbackScreen.tsx +1042 -0
  230. package/src/ui/screens/SignInScreen.tsx +181 -224
  231. package/src/ui/screens/SignUpScreen.tsx +772 -608
  232. package/src/ui/screens/karma/KarmaCenterScreen.tsx +4 -4
  233. package/src/ui/store/index.ts +245 -0
@@ -6,143 +6,368 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _OxyContext = require("../context/OxyContext.js");
10
- var _index = require("../styles/index.js");
9
+ var _OxyContext = require("../context/OxyContext");
10
+ var _styles = require("../styles");
11
11
  var _vectorIcons = require("@expo/vector-icons");
12
- var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
13
- var _sonner = require("../../lib/sonner.js");
12
+ var _sonner = require("../../lib/sonner");
13
+ var _HighFive = _interopRequireDefault(require("../../assets/illustrations/HighFive"));
14
+ var _GroupedPillButtons = _interopRequireDefault(require("../components/internal/GroupedPillButtons"));
15
+ var _TextField = _interopRequireDefault(require("../components/internal/TextField"));
14
16
  var _jsxRuntime = require("react/jsx-runtime");
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
18
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
- const SignUpScreen = ({
17
- navigate,
18
- goBack,
19
- theme
20
- }) => {
21
- // Form data states
22
- const [username, setUsername] = (0, _react.useState)('');
23
- const [email, setEmail] = (0, _react.useState)('');
24
- const [password, setPassword] = (0, _react.useState)('');
25
- const [confirmPassword, setConfirmPassword] = (0, _react.useState)('');
26
- const [showPassword, setShowPassword] = (0, _react.useState)(false);
27
- const [showConfirmPassword, setShowConfirmPassword] = (0, _react.useState)(false);
28
- const [errorMessage, setErrorMessage] = (0, _react.useState)('');
19
+ // Types for better type safety
29
20
 
30
- // Multi-step form states
31
- const [currentStep, setCurrentStep] = (0, _react.useState)(0);
32
- const [isInputFocused, setIsInputFocused] = (0, _react.useState)(false);
33
- const [isValidating, setIsValidating] = (0, _react.useState)(false);
34
- const [validationStatus, setValidationStatus] = (0, _react.useState)('idle');
21
+ // Constants
22
+ const USERNAME_MIN_LENGTH = 3;
23
+ const PASSWORD_MIN_LENGTH = 8;
24
+ const VALIDATION_DEBOUNCE_MS = 800;
25
+ const CACHE_DURATION_MS = 5 * 60 * 1000; // 5 minutes
35
26
 
36
- // Cache for validation results
37
- const validationCache = (0, _react.useRef)(new Map());
38
- const fadeAnim = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
39
- const slideAnim = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
40
- const heightAnim = (0, _react.useRef)(new _reactNative.Animated.Value(400)).current;
41
- const [containerHeight, setContainerHeight] = (0, _react.useState)(400);
42
- const {
43
- signUp,
44
- isLoading,
45
- user,
46
- isAuthenticated,
47
- oxyServices
48
- } = (0, _OxyContext.useOxy)();
49
- const colors = (0, _index.useThemeColors)(theme);
50
- const commonStyles = (0, _index.createCommonStyles)(theme);
51
-
52
- // Memoized styles to prevent rerenders
53
- const styles = (0, _react.useMemo)(() => createStyles(colors, theme), [colors, theme]);
27
+ // Email validation regex
28
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
54
29
 
55
- // Input focus animations
56
- const handleInputFocus = (0, _react.useCallback)(() => {
57
- setIsInputFocused(true);
58
- }, []);
59
- const handleInputBlur = (0, _react.useCallback)(() => {
60
- setIsInputFocused(false);
61
- }, []);
62
-
63
- // Memoized input change handlers
64
- const handleUsernameChange = (0, _react.useCallback)(text => {
65
- setUsername(text);
66
- if (validationStatus === 'invalid') {
67
- setErrorMessage('');
68
- setValidationStatus('idle');
69
- }
70
- }, [validationStatus]);
71
- const handleEmailChange = (0, _react.useCallback)(text => {
72
- setEmail(text);
73
- setErrorMessage('');
74
- }, []);
75
- const handlePasswordChange = (0, _react.useCallback)(text => {
76
- setPassword(text);
77
- setErrorMessage('');
78
- }, []);
79
- const handleConfirmPasswordChange = (0, _react.useCallback)(text => {
80
- setConfirmPassword(text);
81
- setErrorMessage('');
82
- }, []);
30
+ // Styles factory function
31
+ const createStyles = (colors, theme) => _reactNative.StyleSheet.create({
32
+ container: {
33
+ flex: 1
34
+ },
35
+ scrollContent: {
36
+ flexGrow: 1,
37
+ paddingHorizontal: 24,
38
+ paddingTop: 4,
39
+ paddingBottom: 20
40
+ },
41
+ stepContainer: {
42
+ flex: 1,
43
+ justifyContent: 'flex-start',
44
+ alignItems: 'flex-start'
45
+ },
46
+ modernHeader: {
47
+ alignItems: 'flex-start',
48
+ width: '100%',
49
+ marginBottom: 24
50
+ },
51
+ modernTitle: {
52
+ fontFamily: _reactNative.Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
53
+ fontWeight: _reactNative.Platform.OS === 'web' ? 'bold' : undefined,
54
+ fontSize: 42,
55
+ lineHeight: 48,
56
+ marginBottom: 12,
57
+ textAlign: 'left',
58
+ letterSpacing: -1
59
+ },
60
+ modernSubtitle: {
61
+ fontSize: 18,
62
+ lineHeight: 24,
63
+ textAlign: 'left',
64
+ opacity: 0.8,
65
+ marginBottom: 24
66
+ },
67
+ welcomeImageContainer: {
68
+ alignItems: 'center',
69
+ justifyContent: 'center',
70
+ marginVertical: 20
71
+ },
72
+ welcomeTitle: {
73
+ fontFamily: _reactNative.Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
74
+ fontWeight: _reactNative.Platform.OS === 'web' ? 'bold' : undefined,
75
+ fontSize: 42,
76
+ lineHeight: 48,
77
+ marginBottom: 12,
78
+ textAlign: 'left',
79
+ letterSpacing: -1
80
+ },
81
+ welcomeText: {
82
+ fontSize: 18,
83
+ lineHeight: 24,
84
+ textAlign: 'left',
85
+ opacity: 0.8,
86
+ marginBottom: 24
87
+ },
88
+ stepTitle: {
89
+ fontFamily: _reactNative.Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
90
+ fontWeight: _reactNative.Platform.OS === 'web' ? 'bold' : undefined,
91
+ fontSize: 42,
92
+ lineHeight: 48,
93
+ marginBottom: 12,
94
+ textAlign: 'left',
95
+ letterSpacing: -1
96
+ },
97
+ inputContainer: {
98
+ width: '100%',
99
+ marginBottom: 24
100
+ },
101
+ premiumInputWrapper: {
102
+ flexDirection: 'row',
103
+ alignItems: 'center',
104
+ height: 56,
105
+ borderRadius: 16,
106
+ paddingHorizontal: 20,
107
+ borderWidth: 2,
108
+ backgroundColor: colors.inputBackground
109
+ },
110
+ inputIcon: {
111
+ marginRight: 12
112
+ },
113
+ inputContent: {
114
+ flex: 1
115
+ },
116
+ modernLabel: {
117
+ fontSize: 12,
118
+ fontWeight: '500',
119
+ marginBottom: 2
120
+ },
121
+ modernInput: {
122
+ flex: 1,
123
+ fontSize: 16,
124
+ height: '100%'
125
+ },
126
+ validationIndicator: {
127
+ marginLeft: 8
128
+ },
129
+ validationCard: {
130
+ flexDirection: 'row',
131
+ alignItems: 'center',
132
+ padding: 12,
133
+ borderRadius: 12,
134
+ marginTop: 8,
135
+ gap: 8
136
+ },
137
+ validationIconContainer: {
138
+ width: 32,
139
+ height: 32,
140
+ borderRadius: 16,
141
+ justifyContent: 'center',
142
+ alignItems: 'center',
143
+ marginRight: 12
144
+ },
145
+ validationTextContainer: {
146
+ flex: 1
147
+ },
148
+ validationTitle: {
149
+ fontSize: 12,
150
+ fontWeight: '600',
151
+ marginBottom: 2
152
+ },
153
+ validationSubtitle: {
154
+ fontSize: 11,
155
+ opacity: 0.8
156
+ },
157
+ passwordToggle: {
158
+ padding: 4
159
+ },
160
+ passwordHint: {
161
+ fontSize: 12,
162
+ marginTop: 4
163
+ },
164
+ button: {
165
+ flexDirection: 'row',
166
+ alignItems: 'center',
167
+ justifyContent: 'center',
168
+ paddingVertical: 18,
169
+ paddingHorizontal: 32,
170
+ borderRadius: 16,
171
+ marginVertical: 8,
172
+ shadowOffset: {
173
+ width: 0,
174
+ height: 4
175
+ },
176
+ shadowOpacity: 0.3,
177
+ shadowRadius: 8,
178
+ elevation: 6,
179
+ gap: 8,
180
+ width: '100%'
181
+ },
182
+ buttonText: {
183
+ color: '#FFFFFF',
184
+ fontSize: 16,
185
+ fontWeight: '600',
186
+ letterSpacing: 0.5
187
+ },
188
+ footerTextContainer: {
189
+ flexDirection: 'row',
190
+ justifyContent: 'center',
191
+ marginTop: 16
192
+ },
193
+ footerText: {
194
+ fontSize: 15
195
+ },
196
+ linkText: {
197
+ fontSize: 14,
198
+ lineHeight: 20,
199
+ fontWeight: '600',
200
+ textDecorationLine: 'underline'
201
+ },
202
+ userInfoContainer: {
203
+ padding: 20,
204
+ marginVertical: 20,
205
+ borderRadius: 24,
206
+ alignItems: 'center',
207
+ shadowColor: '#000',
208
+ shadowOpacity: 0.04,
209
+ shadowOffset: {
210
+ width: 0,
211
+ height: 1
212
+ },
213
+ shadowRadius: 4,
214
+ elevation: 1
215
+ },
216
+ userInfoText: {
217
+ fontSize: 16,
218
+ marginBottom: 8,
219
+ textAlign: 'center'
220
+ },
221
+ actionButtonsContainer: {
222
+ marginTop: 24
223
+ },
224
+ navigationButtons: {
225
+ flexDirection: 'row',
226
+ justifyContent: 'center',
227
+ marginTop: 16,
228
+ marginBottom: 8,
229
+ width: '100%',
230
+ gap: 8
231
+ },
232
+ navButton: {
233
+ flexDirection: 'row',
234
+ alignItems: 'center',
235
+ paddingVertical: 6,
236
+ paddingHorizontal: 12,
237
+ gap: 6,
238
+ minWidth: 70,
239
+ borderWidth: 1,
240
+ shadowOffset: {
241
+ width: 0,
242
+ height: 2
243
+ },
244
+ shadowOpacity: 0.1,
245
+ shadowRadius: 4,
246
+ elevation: 2
247
+ },
248
+ backButton: {
249
+ backgroundColor: 'transparent',
250
+ borderTopLeftRadius: 35,
251
+ borderBottomLeftRadius: 35,
252
+ borderTopRightRadius: 12,
253
+ borderBottomRightRadius: 12
254
+ },
255
+ nextButton: {
256
+ backgroundColor: 'transparent',
257
+ borderTopRightRadius: 35,
258
+ borderBottomRightRadius: 35,
259
+ borderTopLeftRadius: 12,
260
+ borderBottomLeftRadius: 12
261
+ },
262
+ navButtonText: {
263
+ fontSize: 13,
264
+ fontWeight: '500'
265
+ },
266
+ progressContainer: {
267
+ flexDirection: 'row',
268
+ justifyContent: 'center',
269
+ marginBottom: 20,
270
+ marginTop: 8
271
+ },
272
+ progressDot: {
273
+ height: 10,
274
+ width: 10,
275
+ borderRadius: 5,
276
+ marginHorizontal: 6,
277
+ borderWidth: 2,
278
+ borderColor: '#fff',
279
+ shadowColor: colors.primary,
280
+ shadowOpacity: 0.08,
281
+ shadowOffset: {
282
+ width: 0,
283
+ height: 1
284
+ },
285
+ shadowRadius: 2,
286
+ elevation: 1
287
+ },
288
+ summaryContainer: {
289
+ padding: 0,
290
+ marginBottom: 24,
291
+ width: '100%'
292
+ },
293
+ summaryRow: {
294
+ flexDirection: 'row',
295
+ marginBottom: 10
296
+ },
297
+ summaryLabel: {
298
+ fontSize: 15,
299
+ width: 90
300
+ },
301
+ summaryValue: {
302
+ fontSize: 15,
303
+ fontWeight: '600',
304
+ flex: 1
305
+ }
306
+ });
83
307
 
84
- // Username availability validation using core services
85
- const validateUsername = (0, _react.useCallback)(async usernameToValidate => {
86
- if (!usernameToValidate || usernameToValidate.length < 3) {
87
- setValidationStatus('invalid');
308
+ // Custom hooks for better separation of concerns
309
+ const useFormValidation = oxyServices => {
310
+ const [validationState, setValidationState] = (0, _react.useState)({
311
+ status: 'idle',
312
+ message: ''
313
+ });
314
+ const validationCache = (0, _react.useRef)(new Map());
315
+ const validateUsername = (0, _react.useCallback)(async username => {
316
+ if (!username || username.length < USERNAME_MIN_LENGTH) {
317
+ setValidationState({
318
+ status: 'invalid',
319
+ message: ''
320
+ });
88
321
  return false;
89
322
  }
90
323
 
91
- // Check cache first (cache valid for 5 minutes)
92
- const cached = validationCache.current.get(usernameToValidate);
324
+ // Check cache first
325
+ const cached = validationCache.current.get(username);
93
326
  const now = Date.now();
94
- if (cached && now - cached.timestamp < 5 * 60 * 1000) {
95
- setValidationStatus(cached.available ? 'valid' : 'invalid');
96
- setErrorMessage(cached.available ? '' : 'Username is already taken');
97
- return cached.available;
327
+ if (cached && now - cached.timestamp < CACHE_DURATION_MS) {
328
+ const isValid = cached.available;
329
+ setValidationState({
330
+ status: isValid ? 'valid' : 'invalid',
331
+ message: isValid ? '' : 'Username is already taken'
332
+ });
333
+ return isValid;
98
334
  }
99
- setIsValidating(true);
100
- setValidationStatus('validating');
335
+ setValidationState({
336
+ status: 'validating',
337
+ message: ''
338
+ });
101
339
  try {
102
- const result = await oxyServices.checkUsernameAvailability(usernameToValidate);
103
- if (result.available) {
104
- setValidationStatus('valid');
105
- setErrorMessage('');
106
-
107
- // Cache the result
108
- validationCache.current.set(usernameToValidate, {
109
- available: true,
110
- timestamp: now
111
- });
112
- return true;
113
- } else {
114
- setValidationStatus('invalid');
115
- setErrorMessage(result.message || 'Username is already taken');
340
+ const result = await oxyServices.checkUsernameAvailability(username);
341
+ const isValid = result.available;
116
342
 
117
- // Cache the result
118
- validationCache.current.set(usernameToValidate, {
119
- available: false,
120
- timestamp: now
121
- });
122
- return false;
123
- }
343
+ // Cache the result
344
+ validationCache.current.set(username, {
345
+ available: isValid,
346
+ timestamp: now
347
+ });
348
+ setValidationState({
349
+ status: isValid ? 'valid' : 'invalid',
350
+ message: isValid ? '' : result.message || 'Username is already taken'
351
+ });
352
+ return isValid;
124
353
  } catch (error) {
125
354
  console.error('Username validation error:', error);
126
- setValidationStatus('invalid');
127
- setErrorMessage('Unable to validate username. Please try again.');
355
+ setValidationState({
356
+ status: 'invalid',
357
+ message: 'Unable to validate username. Please try again.'
358
+ });
128
359
  return false;
129
- } finally {
130
- setIsValidating(false);
131
360
  }
132
361
  }, [oxyServices]);
133
-
134
- // Debounced username validation
135
- (0, _react.useEffect)(() => {
136
- if (!username || username.length < 3) {
137
- setValidationStatus('idle');
138
- setErrorMessage('');
139
- return;
140
- }
141
- const timeoutId = setTimeout(() => {
142
- validateUsername(username);
143
- }, 800);
144
- return () => clearTimeout(timeoutId);
145
- }, [username, validateUsername]);
362
+ const validateEmail = (0, _react.useCallback)(email => {
363
+ return EMAIL_REGEX.test(email);
364
+ }, []);
365
+ const validatePassword = (0, _react.useCallback)(password => {
366
+ return password.length >= PASSWORD_MIN_LENGTH;
367
+ }, []);
368
+ const validatePasswordsMatch = (0, _react.useCallback)((password, confirmPassword) => {
369
+ return password === confirmPassword;
370
+ }, []);
146
371
 
147
372
  // Cleanup cache on unmount
148
373
  (0, _react.useEffect)(() => {
@@ -150,6 +375,261 @@ const SignUpScreen = ({
150
375
  validationCache.current.clear();
151
376
  };
152
377
  }, []);
378
+ return {
379
+ validationState,
380
+ validateUsername,
381
+ validateEmail,
382
+ validatePassword,
383
+ validatePasswordsMatch
384
+ };
385
+ };
386
+ const useFormData = () => {
387
+ const [formData, setFormData] = (0, _react.useState)({
388
+ username: '',
389
+ email: '',
390
+ password: '',
391
+ confirmPassword: ''
392
+ });
393
+ const [passwordVisibility, setPasswordVisibility] = (0, _react.useState)({
394
+ password: false,
395
+ confirmPassword: false
396
+ });
397
+ const updateField = (0, _react.useCallback)((field, value) => {
398
+ setFormData(prev => ({
399
+ ...prev,
400
+ [field]: value
401
+ }));
402
+ }, []);
403
+ const togglePasswordVisibility = (0, _react.useCallback)(field => {
404
+ setPasswordVisibility(prev => ({
405
+ ...prev,
406
+ [field]: !prev[field]
407
+ }));
408
+ }, []);
409
+ const resetForm = (0, _react.useCallback)(() => {
410
+ setFormData({
411
+ username: '',
412
+ email: '',
413
+ password: '',
414
+ confirmPassword: ''
415
+ });
416
+ setPasswordVisibility({
417
+ password: false,
418
+ confirmPassword: false
419
+ });
420
+ }, []);
421
+ return {
422
+ formData,
423
+ passwordVisibility,
424
+ updateField,
425
+ togglePasswordVisibility,
426
+ resetForm
427
+ };
428
+ };
429
+
430
+ // Reusable components
431
+ const ValidationIndicator = /*#__PURE__*/_react.default.memo(({
432
+ status,
433
+ colors,
434
+ styles
435
+ }) => {
436
+ if (status === 'validating') {
437
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
438
+ size: "small",
439
+ color: colors.primary,
440
+ style: styles.validationIndicator
441
+ });
442
+ }
443
+ if (status === 'valid') {
444
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
445
+ name: "checkmark-circle",
446
+ size: 22,
447
+ color: colors.success,
448
+ style: styles.validationIndicator
449
+ });
450
+ }
451
+ if (status === 'invalid') {
452
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
453
+ name: "close-circle",
454
+ size: 22,
455
+ color: colors.error,
456
+ style: styles.validationIndicator
457
+ });
458
+ }
459
+ return null;
460
+ });
461
+ const ValidationMessage = /*#__PURE__*/_react.default.memo(({
462
+ validationState,
463
+ colors,
464
+ styles
465
+ }) => {
466
+ if (validationState.status === 'idle' || !validationState.message) return null;
467
+ const isSuccess = validationState.status === 'valid';
468
+ const backgroundColor = isSuccess ? colors.success + '10' : colors.error + '10';
469
+ const borderColor = isSuccess ? colors.success + '30' : colors.error + '30';
470
+ const iconColor = isSuccess ? colors.success : colors.error;
471
+ const iconName = isSuccess ? 'checkmark-circle' : 'alert-circle';
472
+ const title = isSuccess ? 'Username Available' : 'Username Taken';
473
+ const subtitle = isSuccess ? 'Good choice! This username is available' : validationState.message;
474
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
475
+ style: [styles.validationCard, {
476
+ backgroundColor,
477
+ borderColor
478
+ }],
479
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
480
+ style: [styles.validationIconContainer, {
481
+ backgroundColor: iconColor + '20'
482
+ }],
483
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
484
+ name: iconName,
485
+ size: 16,
486
+ color: iconColor
487
+ })
488
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
489
+ style: styles.validationTextContainer,
490
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
491
+ style: [styles.validationTitle, {
492
+ color: iconColor
493
+ }],
494
+ children: title
495
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
496
+ style: [styles.validationSubtitle, {
497
+ color: colors.secondaryText
498
+ }],
499
+ children: subtitle
500
+ })]
501
+ })]
502
+ });
503
+ });
504
+ const FormInput = /*#__PURE__*/_react.default.memo(({
505
+ icon,
506
+ label,
507
+ value,
508
+ onChangeText,
509
+ secureTextEntry = false,
510
+ keyboardType = 'default',
511
+ autoCapitalize = 'sentences',
512
+ autoCorrect = true,
513
+ testID,
514
+ colors,
515
+ styles,
516
+ borderColor,
517
+ rightComponent
518
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
519
+ style: styles.inputContainer,
520
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
521
+ style: [styles.premiumInputWrapper, {
522
+ borderColor: borderColor || colors.border,
523
+ backgroundColor: colors.inputBackground,
524
+ shadowColor: colors.primary,
525
+ shadowOffset: {
526
+ width: 0,
527
+ height: 4
528
+ },
529
+ shadowOpacity: 0.1,
530
+ shadowRadius: 12,
531
+ elevation: 3
532
+ }],
533
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
534
+ name: icon,
535
+ size: 22,
536
+ color: colors.secondaryText,
537
+ style: styles.inputIcon
538
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
539
+ style: styles.inputContent,
540
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
541
+ style: [styles.modernLabel, {
542
+ color: colors.secondaryText
543
+ }],
544
+ children: label
545
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
546
+ style: [styles.modernInput, {
547
+ color: colors.text
548
+ }],
549
+ value: value,
550
+ onChangeText: onChangeText,
551
+ secureTextEntry: secureTextEntry,
552
+ keyboardType: keyboardType,
553
+ autoCapitalize: autoCapitalize,
554
+ autoCorrect: autoCorrect,
555
+ testID: testID,
556
+ placeholderTextColor: "transparent"
557
+ })]
558
+ }), rightComponent]
559
+ })
560
+ }));
561
+ const ProgressIndicator = /*#__PURE__*/_react.default.memo(({
562
+ currentStep,
563
+ totalSteps,
564
+ colors,
565
+ styles
566
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
567
+ style: styles.progressContainer,
568
+ children: Array.from({
569
+ length: totalSteps
570
+ }, (_, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
571
+ style: [styles.progressDot, currentStep === index ? {
572
+ backgroundColor: colors.primary,
573
+ width: 24
574
+ } : {
575
+ backgroundColor: colors.border
576
+ }]
577
+ }, index))
578
+ }));
579
+
580
+ // Main component
581
+ const SignUpScreen = ({
582
+ navigate,
583
+ goBack,
584
+ onAuthenticated,
585
+ theme
586
+ }) => {
587
+ const {
588
+ signUp,
589
+ isLoading,
590
+ user,
591
+ isAuthenticated,
592
+ oxyServices
593
+ } = (0, _OxyContext.useOxy)();
594
+ const colors = (0, _styles.useThemeColors)(theme);
595
+
596
+ // Form state
597
+ const {
598
+ formData,
599
+ passwordVisibility,
600
+ updateField,
601
+ togglePasswordVisibility,
602
+ resetForm
603
+ } = useFormData();
604
+ const {
605
+ validationState,
606
+ validateUsername,
607
+ validateEmail,
608
+ validatePassword,
609
+ validatePasswordsMatch
610
+ } = useFormValidation(oxyServices);
611
+
612
+ // UI state
613
+ const [currentStep, setCurrentStep] = (0, _react.useState)(0);
614
+ const [errorMessage, setErrorMessage] = (0, _react.useState)('');
615
+
616
+ // Animation refs
617
+ const fadeAnim = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
618
+ const slideAnim = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
619
+
620
+ // Memoized styles
621
+ const styles = (0, _react.useMemo)(() => createStyles(colors, theme), [colors, theme]);
622
+
623
+ // Debounced username validation
624
+ (0, _react.useEffect)(() => {
625
+ if (!formData.username || formData.username.length < USERNAME_MIN_LENGTH) {
626
+ return;
627
+ }
628
+ const timeoutId = setTimeout(() => {
629
+ validateUsername(formData.username);
630
+ }, VALIDATION_DEBOUNCE_MS);
631
+ return () => clearTimeout(timeoutId);
632
+ }, [formData.username, validateUsername]);
153
633
 
154
634
  // Animation functions
155
635
  const animateTransition = (0, _react.useCallback)(nextStep => {
@@ -181,116 +661,83 @@ const SignUpScreen = ({
181
661
  animateTransition(currentStep - 1);
182
662
  }
183
663
  }, [currentStep, animateTransition]);
184
- const validateEmail = (0, _react.useCallback)(email => {
185
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
186
- return emailRegex.test(email);
187
- }, []);
188
- const handleSignUp = (0, _react.useCallback)(async () => {
189
- if (!username || !email || !password || !confirmPassword) {
190
- _sonner.toast.error('Please fill in all fields');
191
- return;
192
- }
193
- if (!validateEmail(email)) {
194
- _sonner.toast.error('Please enter a valid email address');
195
- return;
196
- }
197
- if (validationStatus !== 'valid') {
198
- _sonner.toast.error('Please enter a valid username');
664
+
665
+ // Form validation helpers
666
+ const isIdentityStepValid = (0, _react.useCallback)(() => {
667
+ return formData.username && formData.email && validateEmail(formData.email) && validationState.status === 'valid';
668
+ }, [formData.username, formData.email, validateEmail, validationState.status]);
669
+ const isSecurityStepValid = (0, _react.useCallback)(() => {
670
+ return formData.password && validatePassword(formData.password) && validatePasswordsMatch(formData.password, formData.confirmPassword);
671
+ }, [formData.password, formData.confirmPassword, validatePassword, validatePasswordsMatch]);
672
+
673
+ // Custom next handlers for validation
674
+ const handleIdentityNext = (0, _react.useCallback)(() => {
675
+ if (!isIdentityStepValid()) {
676
+ _sonner.toast.error('Please enter a valid username and email.');
199
677
  return;
200
678
  }
201
- if (password !== confirmPassword) {
202
- _sonner.toast.error('Passwords do not match');
679
+ nextStep();
680
+ }, [isIdentityStepValid, nextStep]);
681
+ const handleSecurityNext = (0, _react.useCallback)(() => {
682
+ if (!isSecurityStepValid()) {
683
+ _sonner.toast.error('Please enter a valid password and confirm it.');
203
684
  return;
204
685
  }
205
- if (password.length < 8) {
206
- _sonner.toast.error('Password must be at least 8 characters long');
686
+ nextStep();
687
+ }, [isSecurityStepValid, nextStep]);
688
+
689
+ // Sign up handler
690
+ const handleSignUp = (0, _react.useCallback)(async () => {
691
+ if (!isIdentityStepValid() || !isSecurityStepValid()) {
692
+ _sonner.toast.error('Please fill in all fields correctly');
207
693
  return;
208
694
  }
209
695
  try {
210
696
  setErrorMessage('');
211
- await signUp(username, email, password);
697
+ const user = await signUp(formData.username, formData.email, formData.password);
212
698
  _sonner.toast.success('Account created successfully! Welcome to Oxy!');
699
+ if (onAuthenticated) {
700
+ onAuthenticated(user);
701
+ }
702
+ resetForm();
213
703
  } catch (error) {
214
704
  _sonner.toast.error(error.message || 'Sign up failed');
215
705
  }
216
- }, [username, email, password, confirmPassword, validationStatus, validateEmail, signUp]);
706
+ }, [formData, isIdentityStepValid, isSecurityStepValid, signUp, onAuthenticated, resetForm]);
217
707
 
218
708
  // Step components
219
- const renderWelcomeStep = (0, _react.useMemo)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
709
+ const renderWelcomeStep = (0, _react.useCallback)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
220
710
  style: [styles.stepContainer, {
221
711
  opacity: fadeAnim,
222
712
  transform: [{
223
713
  translateX: slideAnim
224
714
  }]
225
715
  }],
226
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
227
- style: styles.welcomeImageContainer,
228
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSvg.default, {
229
- width: 220,
230
- height: 120,
231
- viewBox: "0 0 220 120",
232
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
233
- d: "M30 100 Q60 20 110 60 Q160 100 190 40",
234
- stroke: colors.primary,
235
- strokeWidth: "8",
236
- fill: "none"
237
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
238
- cx: "60",
239
- cy: "60",
240
- r: "18",
241
- fill: colors.primary,
242
- opacity: "0.18"
243
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
244
- cx: "110",
245
- cy: "60",
246
- r: "24",
247
- fill: colors.primary,
248
- opacity: "0.25"
249
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
250
- cx: "170",
251
- cy: "50",
252
- r: "14",
253
- fill: colors.primary,
254
- opacity: "0.15"
255
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
256
- cx: "110",
257
- cy: "60",
258
- r: "32",
259
- fill: "#fff",
260
- opacity: "0.7"
261
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
262
- cx: "100",
263
- cy: "55",
264
- r: "4",
265
- fill: colors.primary
266
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
267
- cx: "120",
268
- cy: "55",
269
- r: "4",
270
- fill: colors.primary
271
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
272
- d: "M104 68 Q110 75 116 68",
273
- stroke: colors.primary,
274
- strokeWidth: "2",
275
- fill: "none",
276
- strokeLinecap: "round"
277
- })]
278
- })
279
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
280
- style: [styles.welcomeText, {
281
- color: colors.text
282
- }],
283
- children: "We're excited to have you join us. Let's get your account set up in just a few easy steps."
284
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
285
- style: [styles.button, {
286
- backgroundColor: colors.primary
716
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_HighFive.default, {
717
+ width: 100,
718
+ height: 100
719
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
720
+ style: styles.modernHeader,
721
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
722
+ style: [styles.modernTitle, {
723
+ color: colors.text
724
+ }],
725
+ children: "Welcome to Oxy"
726
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
727
+ style: [styles.modernSubtitle, {
728
+ color: colors.secondaryText
729
+ }],
730
+ children: "We're excited to have you join us. Let's get your account set up in just a few easy steps."
731
+ })]
732
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedPillButtons.default, {
733
+ buttons: [{
734
+ text: 'Get Started',
735
+ onPress: nextStep,
736
+ icon: 'arrow-forward',
737
+ variant: 'primary',
738
+ testID: 'welcome-next-button'
287
739
  }],
288
- onPress: nextStep,
289
- testID: "welcome-next-button",
290
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
291
- style: styles.buttonText,
292
- children: "Get Started"
293
- })
740
+ colors: colors
294
741
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
295
742
  style: styles.footerTextContainer,
296
743
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
@@ -309,257 +756,148 @@ const SignUpScreen = ({
309
756
  })]
310
757
  })]
311
758
  }), [fadeAnim, slideAnim, colors, nextStep, navigate, styles]);
312
- const renderIdentityStep = (0, _react.useMemo)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
759
+ const renderIdentityStep = (0, _react.useCallback)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
313
760
  style: [styles.stepContainer, {
314
761
  opacity: fadeAnim,
315
762
  transform: [{
316
763
  translateX: slideAnim
317
764
  }]
318
765
  }],
319
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
320
- style: [styles.stepTitle, {
321
- color: colors.text
322
- }],
323
- children: "Who are you?"
324
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
325
- style: styles.inputContainer,
326
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
327
- style: [styles.label, {
328
- color: colors.text
329
- }],
330
- children: "Username"
331
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
332
- style: {
333
- position: 'relative'
334
- },
335
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
336
- style: [styles.input, {
337
- backgroundColor: colors.inputBackground,
338
- borderColor: colors.border,
339
- color: colors.text
340
- }],
341
- placeholder: "Choose a username",
342
- placeholderTextColor: colors.placeholder,
343
- value: username,
344
- onChangeText: handleUsernameChange,
345
- autoCapitalize: "none",
346
- testID: "username-input"
347
- }), validationStatus === 'validating' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
348
- size: "small",
349
- color: colors.primary,
350
- style: styles.validationIndicator
351
- }), validationStatus === 'valid' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
352
- name: "checkmark-circle",
353
- size: 20,
354
- color: colors.success,
355
- style: styles.validationIndicator
356
- }), validationStatus === 'invalid' && username.length >= 3 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
357
- name: "close-circle",
358
- size: 20,
359
- color: colors.error,
360
- style: styles.validationIndicator
361
- })]
362
- }), validationStatus === 'valid' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
363
- style: [styles.validationSuccessCard, {
364
- backgroundColor: colors.success + '15'
365
- }],
366
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
367
- name: "checkmark-circle",
368
- size: 16,
369
- color: colors.success
370
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
371
- style: [styles.validationText, {
372
- color: colors.success
373
- }],
374
- children: "Username is available"
375
- })]
376
- }), validationStatus === 'invalid' && username.length >= 3 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
377
- style: [styles.validationErrorCard, {
378
- backgroundColor: colors.error + '15'
379
- }],
380
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
381
- name: "alert-circle",
382
- size: 16,
383
- color: colors.error
384
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
385
- style: [styles.validationText, {
386
- color: colors.error
387
- }],
388
- children: errorMessage || 'Username is already taken'
389
- })]
390
- })]
391
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
392
- style: styles.inputContainer,
393
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
394
- style: [styles.label, {
395
- color: colors.text
396
- }],
397
- children: "Email"
398
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
399
- style: [styles.input, {
400
- backgroundColor: colors.inputBackground,
401
- borderColor: colors.border,
766
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
767
+ style: styles.modernHeader,
768
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
769
+ style: [styles.stepTitle, {
402
770
  color: colors.text
403
771
  }],
404
- placeholder: "Enter your email",
405
- placeholderTextColor: colors.placeholder,
406
- value: email,
407
- onChangeText: handleEmailChange,
408
- autoCapitalize: "none",
409
- keyboardType: "email-address",
410
- testID: "email-input"
411
- })]
412
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
413
- style: styles.navigationButtons,
414
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
415
- style: [styles.navButton, styles.backButton, {
416
- borderColor: colors.border
417
- }],
772
+ children: "Who are you?"
773
+ })
774
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
775
+ icon: "person-outline",
776
+ label: "Username",
777
+ value: formData.username,
778
+ onChangeText: text => {
779
+ updateField('username', text);
780
+ setErrorMessage('');
781
+ },
782
+ autoCapitalize: "none",
783
+ autoCorrect: false,
784
+ testID: "username-input",
785
+ colors: colors,
786
+ variant: "filled",
787
+ error: validationState.status === 'invalid' ? validationState.message : undefined,
788
+ loading: validationState.status === 'validating',
789
+ success: validationState.status === 'valid'
790
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(ValidationMessage, {
791
+ validationState: validationState,
792
+ colors: colors,
793
+ styles: styles
794
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
795
+ icon: "mail-outline",
796
+ label: "Email",
797
+ value: formData.email,
798
+ onChangeText: text => {
799
+ updateField('email', text);
800
+ },
801
+ keyboardType: "email-address",
802
+ autoCapitalize: "none",
803
+ autoCorrect: false,
804
+ testID: "email-input",
805
+ colors: colors,
806
+ variant: "filled",
807
+ error: formData.email && !validateEmail(formData.email) ? 'Please enter a valid email address' : undefined
808
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedPillButtons.default, {
809
+ buttons: [{
810
+ text: 'Back',
418
811
  onPress: prevStep,
419
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
420
- style: [styles.navButtonText, {
421
- color: colors.text
422
- }],
423
- children: "Back"
424
- })
425
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
426
- style: [styles.navButton, styles.nextButton, {
427
- backgroundColor: colors.primary
428
- }],
429
- onPress: nextStep,
430
- disabled: !username || !email || !validateEmail(email) || validationStatus !== 'valid',
431
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
432
- style: [styles.navButtonText, {
433
- color: '#FFFFFF'
434
- }],
435
- children: "Next"
436
- })
437
- })]
812
+ icon: 'arrow-back',
813
+ variant: 'transparent'
814
+ }, {
815
+ text: 'Next',
816
+ onPress: handleIdentityNext,
817
+ icon: 'arrow-forward',
818
+ variant: 'primary'
819
+ }],
820
+ colors: colors
438
821
  })]
439
- }), [fadeAnim, slideAnim, colors, username, email, validationStatus, errorMessage, handleUsernameChange, handleEmailChange, validateEmail, prevStep, nextStep, styles]);
440
- const renderSecurityStep = (0, _react.useMemo)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
822
+ }), [fadeAnim, slideAnim, colors, formData, validationState, updateField, setErrorMessage, prevStep, handleIdentityNext, styles]);
823
+ const renderSecurityStep = (0, _react.useCallback)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
441
824
  style: [styles.stepContainer, {
442
825
  opacity: fadeAnim,
443
826
  transform: [{
444
827
  translateX: slideAnim
445
828
  }]
446
829
  }],
447
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
448
- style: [styles.stepTitle, {
449
- color: colors.text
450
- }],
451
- children: "Secure your account"
452
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
453
- style: styles.inputContainer,
454
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
455
- style: [styles.label, {
456
- color: colors.text
457
- }],
458
- children: "Password"
459
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
460
- style: {
461
- position: 'relative'
462
- },
463
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
464
- style: [styles.input, {
465
- backgroundColor: colors.inputBackground,
466
- borderColor: colors.border,
467
- color: colors.text
468
- }],
469
- placeholder: "Create a password",
470
- placeholderTextColor: colors.placeholder,
471
- value: password,
472
- onChangeText: handlePasswordChange,
473
- secureTextEntry: !showPassword,
474
- testID: "password-input"
475
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
476
- style: styles.passwordToggle,
477
- onPress: () => setShowPassword(!showPassword),
478
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
479
- name: showPassword ? 'eye-off' : 'eye',
480
- size: 20,
481
- color: colors.placeholder
482
- })
483
- })]
484
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
485
- style: [styles.passwordHint, {
486
- color: colors.secondaryText
487
- }],
488
- children: "Password must be at least 8 characters long"
489
- })]
490
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
491
- style: styles.inputContainer,
492
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
493
- style: [styles.label, {
830
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
831
+ style: styles.modernHeader,
832
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
833
+ style: [styles.stepTitle, {
494
834
  color: colors.text
495
835
  }],
496
- children: "Confirm Password"
497
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
498
- style: {
499
- position: 'relative'
500
- },
501
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
502
- style: [styles.input, {
503
- backgroundColor: colors.inputBackground,
504
- borderColor: colors.border,
505
- color: colors.text
506
- }],
507
- placeholder: "Confirm your password",
508
- placeholderTextColor: colors.placeholder,
509
- value: confirmPassword,
510
- onChangeText: handleConfirmPasswordChange,
511
- secureTextEntry: !showConfirmPassword,
512
- testID: "confirm-password-input"
513
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
514
- style: styles.passwordToggle,
515
- onPress: () => setShowConfirmPassword(!showConfirmPassword),
516
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
517
- name: showConfirmPassword ? 'eye-off' : 'eye',
518
- size: 20,
519
- color: colors.placeholder
520
- })
521
- })]
522
- })]
523
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
524
- style: styles.navigationButtons,
525
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
526
- style: [styles.navButton, styles.backButton, {
527
- borderColor: colors.border
528
- }],
836
+ children: "Secure your account"
837
+ })
838
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
839
+ icon: "lock-closed-outline",
840
+ label: "Password",
841
+ value: formData.password,
842
+ onChangeText: text => {
843
+ updateField('password', text);
844
+ },
845
+ secureTextEntry: !passwordVisibility.password,
846
+ autoCapitalize: "none",
847
+ autoCorrect: false,
848
+ testID: "password-input",
849
+ colors: colors,
850
+ variant: "filled",
851
+ error: formData.password && !validatePassword(formData.password) ? `Password must be at least ${PASSWORD_MIN_LENGTH} characters` : undefined
852
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
853
+ style: [styles.passwordHint, {
854
+ color: colors.secondaryText
855
+ }],
856
+ children: ["Password must be at least ", PASSWORD_MIN_LENGTH, " characters long"]
857
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
858
+ icon: "lock-closed-outline",
859
+ label: "Confirm Password",
860
+ value: formData.confirmPassword,
861
+ onChangeText: text => {
862
+ updateField('confirmPassword', text);
863
+ },
864
+ secureTextEntry: !passwordVisibility.confirmPassword,
865
+ autoCapitalize: "none",
866
+ autoCorrect: false,
867
+ testID: "confirm-password-input",
868
+ colors: colors,
869
+ variant: "filled",
870
+ error: formData.confirmPassword && !validatePasswordsMatch(formData.password, formData.confirmPassword) ? 'Passwords do not match' : undefined
871
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedPillButtons.default, {
872
+ buttons: [{
873
+ text: 'Back',
529
874
  onPress: prevStep,
530
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
531
- style: [styles.navButtonText, {
532
- color: colors.text
533
- }],
534
- children: "Back"
535
- })
536
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
537
- style: [styles.navButton, styles.nextButton, {
538
- backgroundColor: colors.primary
539
- }],
540
- onPress: nextStep,
541
- disabled: !password || password.length < 8 || password !== confirmPassword,
542
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
543
- style: [styles.navButtonText, {
544
- color: '#FFFFFF'
545
- }],
546
- children: "Next"
547
- })
548
- })]
875
+ icon: 'arrow-back',
876
+ variant: 'transparent'
877
+ }, {
878
+ text: 'Next',
879
+ onPress: handleSecurityNext,
880
+ icon: 'arrow-forward',
881
+ variant: 'primary'
882
+ }],
883
+ colors: colors
549
884
  })]
550
- }), [fadeAnim, slideAnim, colors, password, confirmPassword, showPassword, showConfirmPassword, handlePasswordChange, handleConfirmPasswordChange, prevStep, nextStep, styles]);
551
- const renderSummaryStep = (0, _react.useMemo)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
885
+ }), [fadeAnim, slideAnim, colors, formData, passwordVisibility, updateField, setErrorMessage, togglePasswordVisibility, prevStep, handleSecurityNext, styles]);
886
+ const renderSummaryStep = (0, _react.useCallback)(() => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Animated.View, {
552
887
  style: [styles.stepContainer, {
553
888
  opacity: fadeAnim,
554
889
  transform: [{
555
890
  translateX: slideAnim
556
891
  }]
557
892
  }],
558
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
559
- style: [styles.stepTitle, {
560
- color: colors.text
561
- }],
562
- children: "Ready to join"
893
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
894
+ style: styles.modernHeader,
895
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
896
+ style: [styles.stepTitle, {
897
+ color: colors.text
898
+ }],
899
+ children: "Ready to join"
900
+ })
563
901
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
564
902
  style: styles.summaryContainer,
565
903
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
@@ -573,7 +911,7 @@ const SignUpScreen = ({
573
911
  style: [styles.summaryValue, {
574
912
  color: colors.text
575
913
  }],
576
- children: username
914
+ children: formData.username
577
915
  })]
578
916
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
579
917
  style: styles.summaryRow,
@@ -586,66 +924,29 @@ const SignUpScreen = ({
586
924
  style: [styles.summaryValue, {
587
925
  color: colors.text
588
926
  }],
589
- children: email
927
+ children: formData.email
590
928
  })]
591
929
  })]
592
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
593
- style: [styles.button, {
594
- backgroundColor: colors.primary
595
- }],
596
- onPress: handleSignUp,
597
- disabled: isLoading,
598
- testID: "signup-button",
599
- children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
600
- color: "#FFFFFF",
601
- size: "small"
602
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
603
- style: styles.buttonText,
604
- children: "Create Account"
605
- })
606
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
607
- style: styles.navigationButtons,
608
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
609
- style: [styles.navButton, styles.backButton, {
610
- borderColor: colors.border
611
- }],
930
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedPillButtons.default, {
931
+ buttons: [{
932
+ text: 'Back',
612
933
  onPress: prevStep,
613
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
614
- style: [styles.navButtonText, {
615
- color: colors.text
616
- }],
617
- children: "Back"
618
- })
619
- })
934
+ icon: 'arrow-back',
935
+ variant: 'transparent'
936
+ }, {
937
+ text: 'Create Account',
938
+ onPress: handleSignUp,
939
+ icon: 'checkmark',
940
+ variant: 'primary',
941
+ disabled: isLoading,
942
+ loading: isLoading,
943
+ testID: 'signup-button'
944
+ }],
945
+ colors: colors
620
946
  })]
621
- }), [fadeAnim, slideAnim, colors, username, email, isLoading, handleSignUp, prevStep, styles]);
622
- const renderProgressIndicators = (0, _react.useMemo)(() => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
623
- style: styles.progressContainer,
624
- children: [0, 1, 2, 3].map(step => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
625
- style: [styles.progressDot, currentStep === step ? {
626
- backgroundColor: colors.primary,
627
- width: 24
628
- } : {
629
- backgroundColor: colors.border
630
- }]
631
- }, step))
632
- }), [currentStep, colors, styles]);
633
- const renderCurrentStep = (0, _react.useCallback)(() => {
634
- switch (currentStep) {
635
- case 0:
636
- return renderWelcomeStep;
637
- case 1:
638
- return renderIdentityStep;
639
- case 2:
640
- return renderSecurityStep;
641
- case 3:
642
- return renderSummaryStep;
643
- default:
644
- return renderWelcomeStep;
645
- }
646
- }, [currentStep, renderWelcomeStep, renderIdentityStep, renderSecurityStep, renderSummaryStep]);
947
+ }), [fadeAnim, slideAnim, colors, formData, isLoading, handleSignUp, prevStep, styles]);
647
948
 
648
- // If user is already authenticated, show user info and account center option
949
+ // If user is already authenticated, show user info
649
950
  if (user && isAuthenticated) {
650
951
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.KeyboardAvoidingView, {
651
952
  style: [styles.container, {
@@ -694,6 +995,22 @@ const SignUpScreen = ({
694
995
  })]
695
996
  });
696
997
  }
998
+
999
+ // Render current step
1000
+ const renderCurrentStep = (0, _react.useCallback)(() => {
1001
+ switch (currentStep) {
1002
+ case 0:
1003
+ return renderWelcomeStep();
1004
+ case 1:
1005
+ return renderIdentityStep();
1006
+ case 2:
1007
+ return renderSecurityStep();
1008
+ case 3:
1009
+ return renderSummaryStep();
1010
+ default:
1011
+ return renderWelcomeStep();
1012
+ }
1013
+ }, [currentStep, renderWelcomeStep, renderIdentityStep, renderSecurityStep, renderSummaryStep]);
697
1014
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.KeyboardAvoidingView, {
698
1015
  style: [styles.container, {
699
1016
  backgroundColor: colors.background
@@ -706,232 +1023,14 @@ const SignUpScreen = ({
706
1023
  contentContainerStyle: styles.scrollContent,
707
1024
  showsVerticalScrollIndicator: false,
708
1025
  keyboardShouldPersistTaps: "handled",
709
- children: [renderProgressIndicators, renderCurrentStep()]
1026
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(ProgressIndicator, {
1027
+ currentStep: currentStep,
1028
+ totalSteps: 4,
1029
+ colors: colors,
1030
+ styles: styles
1031
+ }), renderCurrentStep()]
710
1032
  })]
711
1033
  });
712
1034
  };
713
-
714
- // Memoized styles creation
715
- const createStyles = (colors, theme) => _reactNative.StyleSheet.create({
716
- container: {
717
- flex: 1
718
- },
719
- scrollContent: {
720
- flexGrow: 1,
721
- paddingHorizontal: 24,
722
- paddingTop: 40,
723
- paddingBottom: 40
724
- },
725
- stepContainer: {
726
- flex: 1,
727
- justifyContent: 'center',
728
- alignItems: 'center',
729
- minHeight: 500
730
- },
731
- welcomeImageContainer: {
732
- alignItems: 'center',
733
- justifyContent: 'center',
734
- marginVertical: 30
735
- },
736
- welcomeTitle: {
737
- fontFamily: _reactNative.Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
738
- fontWeight: _reactNative.Platform.OS === 'web' ? 'bold' : undefined,
739
- fontSize: 42,
740
- lineHeight: 48,
741
- marginBottom: 24,
742
- textAlign: 'left',
743
- letterSpacing: -1
744
- },
745
- welcomeText: {
746
- fontSize: 16,
747
- textAlign: 'left',
748
- marginBottom: 30,
749
- lineHeight: 24
750
- },
751
- stepTitle: {
752
- fontFamily: _reactNative.Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
753
- fontWeight: _reactNative.Platform.OS === 'web' ? 'bold' : undefined,
754
- fontSize: 34,
755
- marginBottom: 20,
756
- color: colors.primary,
757
- maxWidth: '90%',
758
- textAlign: 'left'
759
- },
760
- inputContainer: {
761
- marginBottom: 18,
762
- width: '100%'
763
- },
764
- label: {
765
- fontSize: 15,
766
- marginBottom: 8,
767
- fontWeight: '500',
768
- letterSpacing: 0.1
769
- },
770
- input: {
771
- height: 48,
772
- borderRadius: 16,
773
- paddingHorizontal: 16,
774
- borderWidth: 1,
775
- fontSize: 16,
776
- marginBottom: 2
777
- },
778
- validationIndicator: {
779
- position: 'absolute',
780
- right: 16,
781
- top: 14
782
- },
783
- validationSuccessCard: {
784
- flexDirection: 'row',
785
- alignItems: 'center',
786
- padding: 12,
787
- borderRadius: 12,
788
- marginTop: 8,
789
- gap: 8
790
- },
791
- validationErrorCard: {
792
- flexDirection: 'row',
793
- alignItems: 'center',
794
- padding: 12,
795
- borderRadius: 12,
796
- marginTop: 8,
797
- gap: 8
798
- },
799
- validationText: {
800
- fontSize: 12,
801
- fontWeight: '500'
802
- },
803
- passwordToggle: {
804
- position: 'absolute',
805
- right: 16,
806
- top: 14,
807
- padding: 4
808
- },
809
- passwordHint: {
810
- fontSize: 12,
811
- marginTop: 4
812
- },
813
- button: {
814
- height: 48,
815
- borderRadius: 24,
816
- alignItems: 'center',
817
- justifyContent: 'center',
818
- marginTop: 24,
819
- shadowColor: colors.primary,
820
- shadowOpacity: 0.12,
821
- shadowOffset: {
822
- width: 0,
823
- height: 2
824
- },
825
- shadowRadius: 8,
826
- elevation: 2,
827
- width: '100%'
828
- },
829
- buttonText: {
830
- color: '#FFFFFF',
831
- fontSize: 17,
832
- fontWeight: '700',
833
- letterSpacing: 0.2
834
- },
835
- footerTextContainer: {
836
- flexDirection: 'row',
837
- justifyContent: 'center',
838
- marginTop: 28
839
- },
840
- footerText: {
841
- fontSize: 15
842
- },
843
- linkText: {
844
- fontSize: 15,
845
- fontWeight: '700'
846
- },
847
- userInfoContainer: {
848
- padding: 20,
849
- marginVertical: 20,
850
- borderRadius: 24,
851
- alignItems: 'center',
852
- shadowColor: '#000',
853
- shadowOpacity: 0.04,
854
- shadowOffset: {
855
- width: 0,
856
- height: 1
857
- },
858
- shadowRadius: 4,
859
- elevation: 1
860
- },
861
- userInfoText: {
862
- fontSize: 16,
863
- marginBottom: 8,
864
- textAlign: 'center'
865
- },
866
- actionButtonsContainer: {
867
- marginTop: 24
868
- },
869
- navigationButtons: {
870
- flexDirection: 'row',
871
- justifyContent: 'space-between',
872
- alignItems: 'center',
873
- marginTop: 28,
874
- width: '100%'
875
- },
876
- navButton: {
877
- borderRadius: 24,
878
- height: 44,
879
- alignItems: 'center',
880
- justifyContent: 'center',
881
- paddingHorizontal: 28,
882
- backgroundColor: '#F3E5F5'
883
- },
884
- backButton: {
885
- backgroundColor: 'transparent',
886
- borderWidth: 1
887
- },
888
- nextButton: {
889
- minWidth: 100
890
- },
891
- navButtonText: {
892
- fontSize: 16,
893
- fontWeight: '700'
894
- },
895
- progressContainer: {
896
- flexDirection: 'row',
897
- justifyContent: 'center',
898
- marginBottom: 20,
899
- marginTop: 8
900
- },
901
- progressDot: {
902
- height: 10,
903
- width: 10,
904
- borderRadius: 5,
905
- marginHorizontal: 6,
906
- borderWidth: 2,
907
- borderColor: '#fff',
908
- shadowColor: colors.primary,
909
- shadowOpacity: 0.08,
910
- shadowOffset: {
911
- width: 0,
912
- height: 1
913
- },
914
- shadowRadius: 2,
915
- elevation: 1
916
- },
917
- summaryContainer: {
918
- padding: 0,
919
- marginBottom: 24,
920
- width: '100%'
921
- },
922
- summaryRow: {
923
- flexDirection: 'row',
924
- marginBottom: 10
925
- },
926
- summaryLabel: {
927
- fontSize: 15,
928
- width: 90
929
- },
930
- summaryValue: {
931
- fontSize: 15,
932
- fontWeight: '600',
933
- flex: 1
934
- }
935
- });
936
1035
  var _default = exports.default = SignUpScreen;
937
1036
  //# sourceMappingURL=SignUpScreen.js.map