@oxyhq/services 5.4.1 → 5.4.3
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.
- package/lib/commonjs/assets/icons/OxyServices.js +1 -1
- package/lib/commonjs/core/index.js +84 -2
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +22 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/node/index.js +6 -6
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +3 -3
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +3 -3
- package/lib/commonjs/ui/components/GroupedSection.js +1 -1
- package/lib/commonjs/ui/components/OxyLogo.js +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +13 -13
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +2 -2
- package/lib/commonjs/ui/components/ProfileCard.js +2 -2
- package/lib/commonjs/ui/components/Section.js +1 -1
- package/lib/commonjs/ui/components/SectionTitle.js +1 -1
- package/lib/commonjs/ui/components/icon/index.js +1 -1
- package/lib/commonjs/ui/components/index.js +12 -12
- package/lib/commonjs/ui/context/OxyContext.js +20 -4
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/index.js +11 -11
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js +18 -18
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +18 -18
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +45 -27
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +29 -22
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/commonjs/ui/screens/AppInfoScreen.js +6 -6
- package/lib/commonjs/ui/screens/BillingManagementScreen.js +3 -3
- package/lib/commonjs/ui/screens/FileManagementScreen.js +324 -306
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +3 -3
- package/lib/commonjs/ui/screens/ProfileScreen.js +2 -2
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +2 -2
- package/lib/commonjs/ui/screens/SignInScreen.js +358 -310
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +483 -308
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +51 -26
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/commonjs/ui/styles/index.js +2 -2
- package/lib/commonjs/ui/styles/theme.js +1 -1
- package/lib/commonjs/utils/index.js +1 -1
- package/lib/module/assets/icons/OxyServices.js +1 -1
- package/lib/module/assets/icons/OxyServices.js.map +1 -1
- package/lib/module/core/index.js +84 -2
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +10 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/node/index.js +4 -4
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +2 -2
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +3 -3
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +1 -1
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/OxyLogo.js +1 -1
- package/lib/module/ui/components/OxyLogo.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +10 -10
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +2 -2
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +2 -2
- package/lib/module/ui/components/ProfileCard.js.map +1 -1
- package/lib/module/ui/components/Section.js +1 -1
- package/lib/module/ui/components/Section.js.map +1 -1
- package/lib/module/ui/components/SectionTitle.js +1 -1
- package/lib/module/ui/components/SectionTitle.js.map +1 -1
- package/lib/module/ui/components/icon/index.js +1 -1
- package/lib/module/ui/components/icon/index.js.map +1 -1
- package/lib/module/ui/components/index.js +12 -12
- package/lib/module/ui/components/index.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +20 -4
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/index.js +10 -10
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/OxyRouter.js +18 -18
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +5 -5
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountManagementDemo.js +2 -2
- package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +46 -28
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +30 -23
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +6 -6
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/BillingManagementScreen.js +3 -3
- package/lib/module/ui/screens/BillingManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +325 -307
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +3 -3
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +2 -2
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +2 -2
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +358 -310
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +486 -309
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js +52 -27
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/styles/index.js +2 -2
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/module/ui/styles/theme.js +1 -1
- package/lib/module/ui/styles/theme.js.map +1 -1
- package/lib/module/utils/index.js +1 -1
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/core/index.d.ts +24 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
- package/package.json +21 -5
- package/src/core/index.ts +68 -0
- package/src/ui/components/OxyProvider.tsx +5 -5
- package/src/ui/context/OxyContext.tsx +61 -41
- package/src/ui/screens/AccountOverviewScreen.tsx +44 -26
- package/src/ui/screens/AccountSettingsScreen.tsx +24 -18
- package/src/ui/screens/FileManagementScreen.tsx +246 -211
- package/src/ui/screens/SignInScreen.tsx +382 -326
- package/src/ui/screens/SignUpScreen.tsx +443 -273
- package/src/ui/screens/karma/KarmaFAQScreen.tsx +50 -29
- package/lib/commonjs/package.json +0 -1
- package/lib/module/package.json +0 -1
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useState, useRef } from 'react';
|
|
4
|
-
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Platform, Animated } from 'react-native';
|
|
5
|
-
import { useOxy } from
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
// Add icon import
|
|
3
|
+
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
|
4
|
+
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Platform, KeyboardAvoidingView, ScrollView, Animated, StatusBar } from 'react-native';
|
|
5
|
+
import { useOxy } from "../context/OxyContext.js";
|
|
6
|
+
import { useThemeColors, createCommonStyles } from "../styles/index.js";
|
|
7
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
9
8
|
import Svg, { Path, Circle } from 'react-native-svg';
|
|
10
|
-
import { toast } from
|
|
11
|
-
import {
|
|
9
|
+
import { toast } from "../../lib/sonner.js";
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
11
|
const SignUpScreen = ({
|
|
13
12
|
navigate,
|
|
14
13
|
goBack,
|
|
@@ -19,44 +18,143 @@ const SignUpScreen = ({
|
|
|
19
18
|
const [email, setEmail] = useState('');
|
|
20
19
|
const [password, setPassword] = useState('');
|
|
21
20
|
const [confirmPassword, setConfirmPassword] = useState('');
|
|
21
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
22
|
+
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
|
22
23
|
const [errorMessage, setErrorMessage] = useState('');
|
|
23
24
|
|
|
24
25
|
// Multi-step form states
|
|
25
26
|
const [currentStep, setCurrentStep] = useState(0);
|
|
27
|
+
const [isInputFocused, setIsInputFocused] = useState(false);
|
|
28
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
29
|
+
const [validationStatus, setValidationStatus] = useState('idle');
|
|
30
|
+
|
|
31
|
+
// Cache for validation results
|
|
32
|
+
const validationCache = useRef(new Map());
|
|
26
33
|
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
27
34
|
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
28
|
-
const heightAnim = useRef(new Animated.Value(400)).current;
|
|
29
|
-
const [containerHeight, setContainerHeight] = useState(400);
|
|
30
|
-
|
|
35
|
+
const heightAnim = useRef(new Animated.Value(400)).current;
|
|
36
|
+
const [containerHeight, setContainerHeight] = useState(400);
|
|
31
37
|
const {
|
|
32
38
|
signUp,
|
|
33
39
|
isLoading,
|
|
34
40
|
user,
|
|
35
|
-
isAuthenticated
|
|
41
|
+
isAuthenticated,
|
|
42
|
+
oxyServices
|
|
36
43
|
} = useOxy();
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
const colors = useThemeColors(theme);
|
|
45
|
+
const commonStyles = createCommonStyles(theme);
|
|
46
|
+
|
|
47
|
+
// Memoized styles to prevent rerenders
|
|
48
|
+
const styles = useMemo(() => createStyles(colors, theme), [colors, theme]);
|
|
49
|
+
|
|
50
|
+
// Input focus animations
|
|
51
|
+
const handleInputFocus = useCallback(() => {
|
|
52
|
+
setIsInputFocused(true);
|
|
53
|
+
}, []);
|
|
54
|
+
const handleInputBlur = useCallback(() => {
|
|
55
|
+
setIsInputFocused(false);
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
// Memoized input change handlers
|
|
59
|
+
const handleUsernameChange = useCallback(text => {
|
|
60
|
+
setUsername(text);
|
|
61
|
+
if (validationStatus === 'invalid') {
|
|
62
|
+
setErrorMessage('');
|
|
63
|
+
setValidationStatus('idle');
|
|
64
|
+
}
|
|
65
|
+
}, [validationStatus]);
|
|
66
|
+
const handleEmailChange = useCallback(text => {
|
|
67
|
+
setEmail(text);
|
|
68
|
+
setErrorMessage('');
|
|
69
|
+
}, []);
|
|
70
|
+
const handlePasswordChange = useCallback(text => {
|
|
71
|
+
setPassword(text);
|
|
72
|
+
setErrorMessage('');
|
|
73
|
+
}, []);
|
|
74
|
+
const handleConfirmPasswordChange = useCallback(text => {
|
|
75
|
+
setConfirmPassword(text);
|
|
76
|
+
setErrorMessage('');
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
// Username availability validation using core services
|
|
80
|
+
const validateUsername = useCallback(async usernameToValidate => {
|
|
81
|
+
if (!usernameToValidate || usernameToValidate.length < 3) {
|
|
82
|
+
setValidationStatus('invalid');
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Check cache first (cache valid for 5 minutes)
|
|
87
|
+
const cached = validationCache.current.get(usernameToValidate);
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
if (cached && now - cached.timestamp < 5 * 60 * 1000) {
|
|
90
|
+
setValidationStatus(cached.available ? 'valid' : 'invalid');
|
|
91
|
+
setErrorMessage(cached.available ? '' : 'Username is already taken');
|
|
92
|
+
return cached.available;
|
|
93
|
+
}
|
|
94
|
+
setIsValidating(true);
|
|
95
|
+
setValidationStatus('validating');
|
|
96
|
+
try {
|
|
97
|
+
const result = await oxyServices.checkUsernameAvailability(usernameToValidate);
|
|
98
|
+
if (result.available) {
|
|
99
|
+
setValidationStatus('valid');
|
|
100
|
+
setErrorMessage('');
|
|
101
|
+
|
|
102
|
+
// Cache the result
|
|
103
|
+
validationCache.current.set(usernameToValidate, {
|
|
104
|
+
available: true,
|
|
105
|
+
timestamp: now
|
|
106
|
+
});
|
|
107
|
+
return true;
|
|
108
|
+
} else {
|
|
109
|
+
setValidationStatus('invalid');
|
|
110
|
+
setErrorMessage(result.message || 'Username is already taken');
|
|
111
|
+
|
|
112
|
+
// Cache the result
|
|
113
|
+
validationCache.current.set(usernameToValidate, {
|
|
114
|
+
available: false,
|
|
115
|
+
timestamp: now
|
|
116
|
+
});
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('Username validation error:', error);
|
|
121
|
+
setValidationStatus('invalid');
|
|
122
|
+
setErrorMessage('Unable to validate username. Please try again.');
|
|
123
|
+
return false;
|
|
124
|
+
} finally {
|
|
125
|
+
setIsValidating(false);
|
|
126
|
+
}
|
|
127
|
+
}, [oxyServices]);
|
|
128
|
+
|
|
129
|
+
// Debounced username validation
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!username || username.length < 3) {
|
|
132
|
+
setValidationStatus('idle');
|
|
133
|
+
setErrorMessage('');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const timeoutId = setTimeout(() => {
|
|
137
|
+
validateUsername(username);
|
|
138
|
+
}, 800);
|
|
139
|
+
return () => clearTimeout(timeoutId);
|
|
140
|
+
}, [username, validateUsername]);
|
|
141
|
+
|
|
142
|
+
// Cleanup cache on unmount
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
return () => {
|
|
145
|
+
validationCache.current.clear();
|
|
146
|
+
};
|
|
147
|
+
}, []);
|
|
44
148
|
|
|
45
|
-
// If user is already authenticated, show user info and account center option
|
|
46
149
|
// Animation functions
|
|
47
|
-
const animateTransition = nextStep => {
|
|
48
|
-
// Fade out
|
|
150
|
+
const animateTransition = useCallback(nextStep => {
|
|
49
151
|
Animated.timing(fadeAnim, {
|
|
50
152
|
toValue: 0,
|
|
51
153
|
duration: 250,
|
|
52
154
|
useNativeDriver: true
|
|
53
155
|
}).start(() => {
|
|
54
156
|
setCurrentStep(nextStep);
|
|
55
|
-
|
|
56
|
-
// Reset slide position
|
|
57
157
|
slideAnim.setValue(-100);
|
|
58
|
-
|
|
59
|
-
// Fade in and slide
|
|
60
158
|
Animated.parallel([Animated.timing(fadeAnim, {
|
|
61
159
|
toValue: 1,
|
|
62
160
|
duration: 250,
|
|
@@ -67,63 +165,22 @@ const SignUpScreen = ({
|
|
|
67
165
|
useNativeDriver: true
|
|
68
166
|
})]).start();
|
|
69
167
|
});
|
|
70
|
-
};
|
|
71
|
-
const nextStep = () => {
|
|
168
|
+
}, [fadeAnim, slideAnim]);
|
|
169
|
+
const nextStep = useCallback(() => {
|
|
72
170
|
if (currentStep < 3) {
|
|
73
171
|
animateTransition(currentStep + 1);
|
|
74
172
|
}
|
|
75
|
-
};
|
|
76
|
-
const prevStep = () => {
|
|
173
|
+
}, [currentStep, animateTransition]);
|
|
174
|
+
const prevStep = useCallback(() => {
|
|
77
175
|
if (currentStep > 0) {
|
|
78
176
|
animateTransition(currentStep - 1);
|
|
79
177
|
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return /*#__PURE__*/_jsxs(BottomSheetScrollView, {
|
|
83
|
-
style: [styles.scrollContainer, {
|
|
84
|
-
backgroundColor,
|
|
85
|
-
padding: 20
|
|
86
|
-
}],
|
|
87
|
-
children: [/*#__PURE__*/_jsxs(Text, {
|
|
88
|
-
style: [styles.welcomeTitle, {
|
|
89
|
-
color: textColor,
|
|
90
|
-
textAlign: 'center'
|
|
91
|
-
}],
|
|
92
|
-
children: ["Welcome, ", user.username, "!"]
|
|
93
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
94
|
-
style: styles.userInfoContainer,
|
|
95
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
96
|
-
style: [styles.userInfoText, {
|
|
97
|
-
color: textColor
|
|
98
|
-
}],
|
|
99
|
-
children: "You are already signed in."
|
|
100
|
-
}), user.email && /*#__PURE__*/_jsxs(Text, {
|
|
101
|
-
style: [styles.userInfoText, {
|
|
102
|
-
color: isDarkTheme ? '#BBBBBB' : '#666666'
|
|
103
|
-
}],
|
|
104
|
-
children: ["Email: ", user.email]
|
|
105
|
-
})]
|
|
106
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
107
|
-
style: styles.actionButtonsContainer,
|
|
108
|
-
children: /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
109
|
-
style: [styles.button, {
|
|
110
|
-
backgroundColor: primaryColor
|
|
111
|
-
}],
|
|
112
|
-
onPress: () => navigate('AccountCenter'),
|
|
113
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
114
|
-
style: styles.buttonText,
|
|
115
|
-
children: "Go to Account Center"
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
})]
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
const validateEmail = email => {
|
|
178
|
+
}, [currentStep, animateTransition]);
|
|
179
|
+
const validateEmail = useCallback(email => {
|
|
122
180
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
123
181
|
return emailRegex.test(email);
|
|
124
|
-
};
|
|
125
|
-
const handleSignUp = async () => {
|
|
126
|
-
// Validate inputs
|
|
182
|
+
}, []);
|
|
183
|
+
const handleSignUp = useCallback(async () => {
|
|
127
184
|
if (!username || !email || !password || !confirmPassword) {
|
|
128
185
|
toast.error('Please fill in all fields');
|
|
129
186
|
return;
|
|
@@ -132,6 +189,10 @@ const SignUpScreen = ({
|
|
|
132
189
|
toast.error('Please enter a valid email address');
|
|
133
190
|
return;
|
|
134
191
|
}
|
|
192
|
+
if (validationStatus !== 'valid') {
|
|
193
|
+
toast.error('Please enter a valid username');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
135
196
|
if (password !== confirmPassword) {
|
|
136
197
|
toast.error('Passwords do not match');
|
|
137
198
|
return;
|
|
@@ -144,14 +205,13 @@ const SignUpScreen = ({
|
|
|
144
205
|
setErrorMessage('');
|
|
145
206
|
await signUp(username, email, password);
|
|
146
207
|
toast.success('Account created successfully! Welcome to Oxy!');
|
|
147
|
-
// The authentication state change will be handled through context
|
|
148
208
|
} catch (error) {
|
|
149
209
|
toast.error(error.message || 'Sign up failed');
|
|
150
210
|
}
|
|
151
|
-
};
|
|
211
|
+
}, [username, email, password, confirmPassword, validationStatus, validateEmail, signUp]);
|
|
152
212
|
|
|
153
213
|
// Step components
|
|
154
|
-
const renderWelcomeStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
214
|
+
const renderWelcomeStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
155
215
|
style: [styles.stepContainer, {
|
|
156
216
|
opacity: fadeAnim,
|
|
157
217
|
transform: [{
|
|
@@ -166,26 +226,26 @@ const SignUpScreen = ({
|
|
|
166
226
|
viewBox: "0 0 220 120",
|
|
167
227
|
children: [/*#__PURE__*/_jsx(Path, {
|
|
168
228
|
d: "M30 100 Q60 20 110 60 Q160 100 190 40",
|
|
169
|
-
stroke:
|
|
229
|
+
stroke: colors.primary,
|
|
170
230
|
strokeWidth: "8",
|
|
171
231
|
fill: "none"
|
|
172
232
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
173
233
|
cx: "60",
|
|
174
234
|
cy: "60",
|
|
175
235
|
r: "18",
|
|
176
|
-
fill:
|
|
236
|
+
fill: colors.primary,
|
|
177
237
|
opacity: "0.18"
|
|
178
238
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
179
239
|
cx: "110",
|
|
180
240
|
cy: "60",
|
|
181
241
|
r: "24",
|
|
182
|
-
fill:
|
|
242
|
+
fill: colors.primary,
|
|
183
243
|
opacity: "0.25"
|
|
184
244
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
185
245
|
cx: "170",
|
|
186
246
|
cy: "50",
|
|
187
247
|
r: "14",
|
|
188
|
-
fill:
|
|
248
|
+
fill: colors.primary,
|
|
189
249
|
opacity: "0.15"
|
|
190
250
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
191
251
|
cx: "110",
|
|
@@ -197,36 +257,28 @@ const SignUpScreen = ({
|
|
|
197
257
|
cx: "100",
|
|
198
258
|
cy: "55",
|
|
199
259
|
r: "4",
|
|
200
|
-
fill:
|
|
260
|
+
fill: colors.primary
|
|
201
261
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
202
262
|
cx: "120",
|
|
203
263
|
cy: "55",
|
|
204
264
|
r: "4",
|
|
205
|
-
fill:
|
|
265
|
+
fill: colors.primary
|
|
206
266
|
}), /*#__PURE__*/_jsx(Path, {
|
|
207
267
|
d: "M104 68 Q110 75 116 68",
|
|
208
|
-
stroke:
|
|
268
|
+
stroke: colors.primary,
|
|
209
269
|
strokeWidth: "2",
|
|
210
270
|
fill: "none",
|
|
211
271
|
strokeLinecap: "round"
|
|
212
272
|
})]
|
|
213
273
|
})
|
|
214
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
215
|
-
style: styles.header,
|
|
216
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
217
|
-
style: [styles.welcomeTitle],
|
|
218
|
-
children: "Create a Oxy Account"
|
|
219
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
220
|
-
style: styles.placeholder
|
|
221
|
-
})]
|
|
222
274
|
}), /*#__PURE__*/_jsx(Text, {
|
|
223
275
|
style: [styles.welcomeText, {
|
|
224
|
-
color:
|
|
276
|
+
color: colors.text
|
|
225
277
|
}],
|
|
226
278
|
children: "We're excited to have you join us. Let's get your account set up in just a few easy steps."
|
|
227
279
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
228
280
|
style: [styles.button, {
|
|
229
|
-
backgroundColor:
|
|
281
|
+
backgroundColor: colors.primary
|
|
230
282
|
}],
|
|
231
283
|
onPress: nextStep,
|
|
232
284
|
testID: "welcome-next-button",
|
|
@@ -238,21 +290,21 @@ const SignUpScreen = ({
|
|
|
238
290
|
style: styles.footerTextContainer,
|
|
239
291
|
children: [/*#__PURE__*/_jsxs(Text, {
|
|
240
292
|
style: [styles.footerText, {
|
|
241
|
-
color:
|
|
293
|
+
color: colors.text
|
|
242
294
|
}],
|
|
243
295
|
children: ["Already have an account?", ' ']
|
|
244
296
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
245
297
|
onPress: () => navigate('SignIn'),
|
|
246
298
|
children: /*#__PURE__*/_jsx(Text, {
|
|
247
299
|
style: [styles.linkText, {
|
|
248
|
-
color:
|
|
300
|
+
color: colors.primary
|
|
249
301
|
}],
|
|
250
302
|
children: "Sign In"
|
|
251
303
|
})
|
|
252
304
|
})]
|
|
253
305
|
})]
|
|
254
|
-
});
|
|
255
|
-
const renderIdentityStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
306
|
+
}), [fadeAnim, slideAnim, colors, nextStep, navigate, styles]);
|
|
307
|
+
const renderIdentityStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
256
308
|
style: [styles.stepContainer, {
|
|
257
309
|
opacity: fadeAnim,
|
|
258
310
|
transform: [{
|
|
@@ -261,46 +313,93 @@ const SignUpScreen = ({
|
|
|
261
313
|
}],
|
|
262
314
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
263
315
|
style: [styles.stepTitle, {
|
|
264
|
-
color:
|
|
316
|
+
color: colors.text
|
|
265
317
|
}],
|
|
266
318
|
children: "Who are you?"
|
|
267
319
|
}), /*#__PURE__*/_jsxs(View, {
|
|
268
320
|
style: styles.inputContainer,
|
|
269
321
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
270
322
|
style: [styles.label, {
|
|
271
|
-
color:
|
|
323
|
+
color: colors.text
|
|
272
324
|
}],
|
|
273
325
|
children: "Username"
|
|
274
|
-
}), /*#__PURE__*/
|
|
275
|
-
style:
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
326
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
327
|
+
style: {
|
|
328
|
+
position: 'relative'
|
|
329
|
+
},
|
|
330
|
+
children: [/*#__PURE__*/_jsx(TextInput, {
|
|
331
|
+
style: [styles.input, {
|
|
332
|
+
backgroundColor: colors.inputBackground,
|
|
333
|
+
borderColor: colors.border,
|
|
334
|
+
color: colors.text
|
|
335
|
+
}],
|
|
336
|
+
placeholder: "Choose a username",
|
|
337
|
+
placeholderTextColor: colors.placeholder,
|
|
338
|
+
value: username,
|
|
339
|
+
onChangeText: handleUsernameChange,
|
|
340
|
+
autoCapitalize: "none",
|
|
341
|
+
testID: "username-input"
|
|
342
|
+
}), validationStatus === 'validating' && /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
343
|
+
size: "small",
|
|
344
|
+
color: colors.primary,
|
|
345
|
+
style: styles.validationIndicator
|
|
346
|
+
}), validationStatus === 'valid' && /*#__PURE__*/_jsx(Ionicons, {
|
|
347
|
+
name: "checkmark-circle",
|
|
348
|
+
size: 20,
|
|
349
|
+
color: colors.success,
|
|
350
|
+
style: styles.validationIndicator
|
|
351
|
+
}), validationStatus === 'invalid' && username.length >= 3 && /*#__PURE__*/_jsx(Ionicons, {
|
|
352
|
+
name: "close-circle",
|
|
353
|
+
size: 20,
|
|
354
|
+
color: colors.error,
|
|
355
|
+
style: styles.validationIndicator
|
|
356
|
+
})]
|
|
357
|
+
}), validationStatus === 'valid' && /*#__PURE__*/_jsxs(View, {
|
|
358
|
+
style: [styles.validationSuccessCard, {
|
|
359
|
+
backgroundColor: colors.success + '15'
|
|
279
360
|
}],
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
361
|
+
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
362
|
+
name: "checkmark-circle",
|
|
363
|
+
size: 16,
|
|
364
|
+
color: colors.success
|
|
365
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
366
|
+
style: [styles.validationText, {
|
|
367
|
+
color: colors.success
|
|
368
|
+
}],
|
|
369
|
+
children: "Username is available"
|
|
370
|
+
})]
|
|
371
|
+
}), validationStatus === 'invalid' && username.length >= 3 && /*#__PURE__*/_jsxs(View, {
|
|
372
|
+
style: [styles.validationErrorCard, {
|
|
373
|
+
backgroundColor: colors.error + '15'
|
|
374
|
+
}],
|
|
375
|
+
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
376
|
+
name: "alert-circle",
|
|
377
|
+
size: 16,
|
|
378
|
+
color: colors.error
|
|
379
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
380
|
+
style: [styles.validationText, {
|
|
381
|
+
color: colors.error
|
|
382
|
+
}],
|
|
383
|
+
children: errorMessage || 'Username is already taken'
|
|
384
|
+
})]
|
|
286
385
|
})]
|
|
287
386
|
}), /*#__PURE__*/_jsxs(View, {
|
|
288
387
|
style: styles.inputContainer,
|
|
289
388
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
290
389
|
style: [styles.label, {
|
|
291
|
-
color:
|
|
390
|
+
color: colors.text
|
|
292
391
|
}],
|
|
293
392
|
children: "Email"
|
|
294
393
|
}), /*#__PURE__*/_jsx(TextInput, {
|
|
295
394
|
style: [styles.input, {
|
|
296
|
-
backgroundColor:
|
|
297
|
-
borderColor,
|
|
298
|
-
color:
|
|
395
|
+
backgroundColor: colors.inputBackground,
|
|
396
|
+
borderColor: colors.border,
|
|
397
|
+
color: colors.text
|
|
299
398
|
}],
|
|
300
399
|
placeholder: "Enter your email",
|
|
301
|
-
placeholderTextColor:
|
|
400
|
+
placeholderTextColor: colors.placeholder,
|
|
302
401
|
value: email,
|
|
303
|
-
onChangeText:
|
|
402
|
+
onChangeText: handleEmailChange,
|
|
304
403
|
autoCapitalize: "none",
|
|
305
404
|
keyboardType: "email-address",
|
|
306
405
|
testID: "email-input"
|
|
@@ -308,28 +407,32 @@ const SignUpScreen = ({
|
|
|
308
407
|
}), /*#__PURE__*/_jsxs(View, {
|
|
309
408
|
style: styles.navigationButtons,
|
|
310
409
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
311
|
-
style: [styles.navButton, styles.backButton
|
|
410
|
+
style: [styles.navButton, styles.backButton, {
|
|
411
|
+
borderColor: colors.border
|
|
412
|
+
}],
|
|
312
413
|
onPress: prevStep,
|
|
313
414
|
children: /*#__PURE__*/_jsx(Text, {
|
|
314
415
|
style: [styles.navButtonText, {
|
|
315
|
-
color:
|
|
416
|
+
color: colors.text
|
|
316
417
|
}],
|
|
317
418
|
children: "Back"
|
|
318
419
|
})
|
|
319
420
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
320
421
|
style: [styles.navButton, styles.nextButton, {
|
|
321
|
-
backgroundColor:
|
|
422
|
+
backgroundColor: colors.primary
|
|
322
423
|
}],
|
|
323
424
|
onPress: nextStep,
|
|
324
|
-
disabled: !username || !email || !validateEmail(email),
|
|
425
|
+
disabled: !username || !email || !validateEmail(email) || validationStatus !== 'valid',
|
|
325
426
|
children: /*#__PURE__*/_jsx(Text, {
|
|
326
|
-
style: styles.navButtonText,
|
|
427
|
+
style: [styles.navButtonText, {
|
|
428
|
+
color: '#FFFFFF'
|
|
429
|
+
}],
|
|
327
430
|
children: "Next"
|
|
328
431
|
})
|
|
329
432
|
})]
|
|
330
433
|
})]
|
|
331
|
-
});
|
|
332
|
-
const renderSecurityStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
434
|
+
}), [fadeAnim, slideAnim, colors, username, email, validationStatus, errorMessage, handleUsernameChange, handleEmailChange, validateEmail, prevStep, nextStep, styles]);
|
|
435
|
+
const renderSecurityStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
333
436
|
style: [styles.stepContainer, {
|
|
334
437
|
opacity: fadeAnim,
|
|
335
438
|
transform: [{
|
|
@@ -338,31 +441,44 @@ const SignUpScreen = ({
|
|
|
338
441
|
}],
|
|
339
442
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
340
443
|
style: [styles.stepTitle, {
|
|
341
|
-
color:
|
|
444
|
+
color: colors.text
|
|
342
445
|
}],
|
|
343
446
|
children: "Secure your account"
|
|
344
447
|
}), /*#__PURE__*/_jsxs(View, {
|
|
345
448
|
style: styles.inputContainer,
|
|
346
449
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
347
450
|
style: [styles.label, {
|
|
348
|
-
color:
|
|
451
|
+
color: colors.text
|
|
349
452
|
}],
|
|
350
453
|
children: "Password"
|
|
351
|
-
}), /*#__PURE__*/
|
|
352
|
-
style:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
454
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
455
|
+
style: {
|
|
456
|
+
position: 'relative'
|
|
457
|
+
},
|
|
458
|
+
children: [/*#__PURE__*/_jsx(TextInput, {
|
|
459
|
+
style: [styles.input, {
|
|
460
|
+
backgroundColor: colors.inputBackground,
|
|
461
|
+
borderColor: colors.border,
|
|
462
|
+
color: colors.text
|
|
463
|
+
}],
|
|
464
|
+
placeholder: "Create a password",
|
|
465
|
+
placeholderTextColor: colors.placeholder,
|
|
466
|
+
value: password,
|
|
467
|
+
onChangeText: handlePasswordChange,
|
|
468
|
+
secureTextEntry: !showPassword,
|
|
469
|
+
testID: "password-input"
|
|
470
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
471
|
+
style: styles.passwordToggle,
|
|
472
|
+
onPress: () => setShowPassword(!showPassword),
|
|
473
|
+
children: /*#__PURE__*/_jsx(Ionicons, {
|
|
474
|
+
name: showPassword ? 'eye-off' : 'eye',
|
|
475
|
+
size: 20,
|
|
476
|
+
color: colors.placeholder
|
|
477
|
+
})
|
|
478
|
+
})]
|
|
363
479
|
}), /*#__PURE__*/_jsx(Text, {
|
|
364
480
|
style: [styles.passwordHint, {
|
|
365
|
-
color:
|
|
481
|
+
color: colors.secondaryText
|
|
366
482
|
}],
|
|
367
483
|
children: "Password must be at least 8 characters long"
|
|
368
484
|
})]
|
|
@@ -370,47 +486,64 @@ const SignUpScreen = ({
|
|
|
370
486
|
style: styles.inputContainer,
|
|
371
487
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
372
488
|
style: [styles.label, {
|
|
373
|
-
color:
|
|
489
|
+
color: colors.text
|
|
374
490
|
}],
|
|
375
491
|
children: "Confirm Password"
|
|
376
|
-
}), /*#__PURE__*/
|
|
377
|
-
style:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
492
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
493
|
+
style: {
|
|
494
|
+
position: 'relative'
|
|
495
|
+
},
|
|
496
|
+
children: [/*#__PURE__*/_jsx(TextInput, {
|
|
497
|
+
style: [styles.input, {
|
|
498
|
+
backgroundColor: colors.inputBackground,
|
|
499
|
+
borderColor: colors.border,
|
|
500
|
+
color: colors.text
|
|
501
|
+
}],
|
|
502
|
+
placeholder: "Confirm your password",
|
|
503
|
+
placeholderTextColor: colors.placeholder,
|
|
504
|
+
value: confirmPassword,
|
|
505
|
+
onChangeText: handleConfirmPasswordChange,
|
|
506
|
+
secureTextEntry: !showConfirmPassword,
|
|
507
|
+
testID: "confirm-password-input"
|
|
508
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
509
|
+
style: styles.passwordToggle,
|
|
510
|
+
onPress: () => setShowConfirmPassword(!showConfirmPassword),
|
|
511
|
+
children: /*#__PURE__*/_jsx(Ionicons, {
|
|
512
|
+
name: showConfirmPassword ? 'eye-off' : 'eye',
|
|
513
|
+
size: 20,
|
|
514
|
+
color: colors.placeholder
|
|
515
|
+
})
|
|
516
|
+
})]
|
|
388
517
|
})]
|
|
389
518
|
}), /*#__PURE__*/_jsxs(View, {
|
|
390
519
|
style: styles.navigationButtons,
|
|
391
520
|
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
392
|
-
style: [styles.navButton, styles.backButton
|
|
521
|
+
style: [styles.navButton, styles.backButton, {
|
|
522
|
+
borderColor: colors.border
|
|
523
|
+
}],
|
|
393
524
|
onPress: prevStep,
|
|
394
525
|
children: /*#__PURE__*/_jsx(Text, {
|
|
395
526
|
style: [styles.navButtonText, {
|
|
396
|
-
color:
|
|
527
|
+
color: colors.text
|
|
397
528
|
}],
|
|
398
529
|
children: "Back"
|
|
399
530
|
})
|
|
400
531
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
401
532
|
style: [styles.navButton, styles.nextButton, {
|
|
402
|
-
backgroundColor:
|
|
533
|
+
backgroundColor: colors.primary
|
|
403
534
|
}],
|
|
404
535
|
onPress: nextStep,
|
|
405
536
|
disabled: !password || password.length < 8 || password !== confirmPassword,
|
|
406
537
|
children: /*#__PURE__*/_jsx(Text, {
|
|
407
|
-
style: styles.navButtonText,
|
|
538
|
+
style: [styles.navButtonText, {
|
|
539
|
+
color: '#FFFFFF'
|
|
540
|
+
}],
|
|
408
541
|
children: "Next"
|
|
409
542
|
})
|
|
410
543
|
})]
|
|
411
544
|
})]
|
|
412
|
-
});
|
|
413
|
-
const renderSummaryStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
545
|
+
}), [fadeAnim, slideAnim, colors, password, confirmPassword, showPassword, showConfirmPassword, handlePasswordChange, handleConfirmPasswordChange, prevStep, nextStep, styles]);
|
|
546
|
+
const renderSummaryStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
414
547
|
style: [styles.stepContainer, {
|
|
415
548
|
opacity: fadeAnim,
|
|
416
549
|
transform: [{
|
|
@@ -419,7 +552,7 @@ const SignUpScreen = ({
|
|
|
419
552
|
}],
|
|
420
553
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
421
554
|
style: [styles.stepTitle, {
|
|
422
|
-
color:
|
|
555
|
+
color: colors.text
|
|
423
556
|
}],
|
|
424
557
|
children: "Ready to join"
|
|
425
558
|
}), /*#__PURE__*/_jsxs(View, {
|
|
@@ -428,12 +561,12 @@ const SignUpScreen = ({
|
|
|
428
561
|
style: styles.summaryRow,
|
|
429
562
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
430
563
|
style: [styles.summaryLabel, {
|
|
431
|
-
color:
|
|
564
|
+
color: colors.secondaryText
|
|
432
565
|
}],
|
|
433
566
|
children: "Username:"
|
|
434
567
|
}), /*#__PURE__*/_jsx(Text, {
|
|
435
568
|
style: [styles.summaryValue, {
|
|
436
|
-
color:
|
|
569
|
+
color: colors.text
|
|
437
570
|
}],
|
|
438
571
|
children: username
|
|
439
572
|
})]
|
|
@@ -441,118 +574,187 @@ const SignUpScreen = ({
|
|
|
441
574
|
style: styles.summaryRow,
|
|
442
575
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
443
576
|
style: [styles.summaryLabel, {
|
|
444
|
-
color:
|
|
577
|
+
color: colors.secondaryText
|
|
445
578
|
}],
|
|
446
579
|
children: "Email:"
|
|
447
580
|
}), /*#__PURE__*/_jsx(Text, {
|
|
448
581
|
style: [styles.summaryValue, {
|
|
449
|
-
color:
|
|
582
|
+
color: colors.text
|
|
450
583
|
}],
|
|
451
584
|
children: email
|
|
452
585
|
})]
|
|
453
586
|
})]
|
|
454
|
-
}),
|
|
455
|
-
style: styles.
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
587
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
588
|
+
style: [styles.button, {
|
|
589
|
+
backgroundColor: colors.primary
|
|
590
|
+
}],
|
|
591
|
+
onPress: handleSignUp,
|
|
592
|
+
disabled: isLoading,
|
|
593
|
+
testID: "signup-button",
|
|
594
|
+
children: isLoading ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
595
|
+
color: "#FFFFFF",
|
|
596
|
+
size: "small"
|
|
597
|
+
}) : /*#__PURE__*/_jsx(Text, {
|
|
598
|
+
style: styles.buttonText,
|
|
599
|
+
children: "Create Account"
|
|
459
600
|
})
|
|
460
|
-
})
|
|
601
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
461
602
|
style: styles.navigationButtons,
|
|
462
|
-
children:
|
|
463
|
-
style: [styles.navButton, styles.backButton
|
|
603
|
+
children: /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
604
|
+
style: [styles.navButton, styles.backButton, {
|
|
605
|
+
borderColor: colors.border
|
|
606
|
+
}],
|
|
464
607
|
onPress: prevStep,
|
|
465
608
|
children: /*#__PURE__*/_jsx(Text, {
|
|
466
609
|
style: [styles.navButtonText, {
|
|
467
|
-
color:
|
|
610
|
+
color: colors.text
|
|
468
611
|
}],
|
|
469
612
|
children: "Back"
|
|
470
613
|
})
|
|
471
|
-
})
|
|
472
|
-
style: [styles.button, {
|
|
473
|
-
opacity: isLoading ? 0.8 : 1
|
|
474
|
-
}],
|
|
475
|
-
onPress: handleSignUp,
|
|
476
|
-
disabled: isLoading,
|
|
477
|
-
testID: "signup-button",
|
|
478
|
-
children: isLoading ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
479
|
-
color: "#FFFFFF",
|
|
480
|
-
size: "small"
|
|
481
|
-
}) : /*#__PURE__*/_jsx(Text, {
|
|
482
|
-
style: styles.buttonText,
|
|
483
|
-
children: "Create Account"
|
|
484
|
-
})
|
|
485
|
-
})]
|
|
614
|
+
})
|
|
486
615
|
})]
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
// Progress indicators
|
|
490
|
-
const renderProgressIndicators = () => /*#__PURE__*/_jsx(View, {
|
|
616
|
+
}), [fadeAnim, slideAnim, colors, username, email, isLoading, handleSignUp, prevStep, styles]);
|
|
617
|
+
const renderProgressIndicators = useMemo(() => /*#__PURE__*/_jsx(View, {
|
|
491
618
|
style: styles.progressContainer,
|
|
492
619
|
children: [0, 1, 2, 3].map(step => /*#__PURE__*/_jsx(View, {
|
|
493
620
|
style: [styles.progressDot, currentStep === step ? {
|
|
494
|
-
backgroundColor:
|
|
621
|
+
backgroundColor: colors.primary,
|
|
495
622
|
width: 24
|
|
496
623
|
} : {
|
|
497
|
-
backgroundColor:
|
|
624
|
+
backgroundColor: colors.border
|
|
498
625
|
}]
|
|
499
626
|
}, step))
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
// Render step based on current step value
|
|
503
|
-
const renderCurrentStep = () => {
|
|
627
|
+
}), [currentStep, colors, styles]);
|
|
628
|
+
const renderCurrentStep = useCallback(() => {
|
|
504
629
|
switch (currentStep) {
|
|
505
630
|
case 0:
|
|
506
|
-
return renderWelcomeStep
|
|
631
|
+
return renderWelcomeStep;
|
|
507
632
|
case 1:
|
|
508
|
-
return renderIdentityStep
|
|
633
|
+
return renderIdentityStep;
|
|
509
634
|
case 2:
|
|
510
|
-
return renderSecurityStep
|
|
635
|
+
return renderSecurityStep;
|
|
511
636
|
case 3:
|
|
512
|
-
return renderSummaryStep
|
|
637
|
+
return renderSummaryStep;
|
|
513
638
|
default:
|
|
514
|
-
return
|
|
639
|
+
return renderWelcomeStep;
|
|
515
640
|
}
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
style: {
|
|
522
|
-
|
|
523
|
-
},
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
641
|
+
}, [currentStep, renderWelcomeStep, renderIdentityStep, renderSecurityStep, renderSummaryStep]);
|
|
642
|
+
|
|
643
|
+
// If user is already authenticated, show user info and account center option
|
|
644
|
+
if (user && isAuthenticated) {
|
|
645
|
+
return /*#__PURE__*/_jsxs(KeyboardAvoidingView, {
|
|
646
|
+
style: [styles.container, {
|
|
647
|
+
backgroundColor: colors.background
|
|
648
|
+
}],
|
|
649
|
+
behavior: Platform.OS === 'ios' ? 'padding' : 'height',
|
|
650
|
+
children: [/*#__PURE__*/_jsx(StatusBar, {
|
|
651
|
+
barStyle: theme === 'dark' ? 'light-content' : 'dark-content',
|
|
652
|
+
backgroundColor: colors.background
|
|
653
|
+
}), /*#__PURE__*/_jsxs(ScrollView, {
|
|
654
|
+
contentContainerStyle: styles.scrollContent,
|
|
655
|
+
showsVerticalScrollIndicator: false,
|
|
656
|
+
children: [/*#__PURE__*/_jsxs(Text, {
|
|
657
|
+
style: [styles.welcomeTitle, {
|
|
658
|
+
color: colors.text
|
|
659
|
+
}],
|
|
660
|
+
children: ["Welcome, ", user.username, "!"]
|
|
661
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
662
|
+
style: [styles.userInfoContainer, {
|
|
663
|
+
backgroundColor: colors.inputBackground
|
|
664
|
+
}],
|
|
665
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
666
|
+
style: [styles.userInfoText, {
|
|
667
|
+
color: colors.text
|
|
668
|
+
}],
|
|
669
|
+
children: "You are already signed in."
|
|
670
|
+
}), user.email && /*#__PURE__*/_jsxs(Text, {
|
|
671
|
+
style: [styles.userInfoText, {
|
|
672
|
+
color: colors.secondaryText
|
|
673
|
+
}],
|
|
674
|
+
children: ["Email: ", user.email]
|
|
675
|
+
})]
|
|
676
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
677
|
+
style: styles.actionButtonsContainer,
|
|
678
|
+
children: /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
679
|
+
style: [styles.button, {
|
|
680
|
+
backgroundColor: colors.primary
|
|
681
|
+
}],
|
|
682
|
+
onPress: () => navigate('AccountCenter'),
|
|
683
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
684
|
+
style: styles.buttonText,
|
|
685
|
+
children: "Go to Account Center"
|
|
686
|
+
})
|
|
687
|
+
})
|
|
688
|
+
})]
|
|
689
|
+
})]
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
return /*#__PURE__*/_jsxs(KeyboardAvoidingView, {
|
|
693
|
+
style: [styles.container, {
|
|
694
|
+
backgroundColor: colors.background
|
|
695
|
+
}],
|
|
696
|
+
behavior: Platform.OS === 'ios' ? 'padding' : 'height',
|
|
697
|
+
children: [/*#__PURE__*/_jsx(StatusBar, {
|
|
698
|
+
barStyle: theme === 'dark' ? 'light-content' : 'dark-content',
|
|
699
|
+
backgroundColor: colors.background
|
|
700
|
+
}), /*#__PURE__*/_jsxs(ScrollView, {
|
|
701
|
+
contentContainerStyle: styles.scrollContent,
|
|
702
|
+
showsVerticalScrollIndicator: false,
|
|
703
|
+
keyboardShouldPersistTaps: "handled",
|
|
704
|
+
children: [renderProgressIndicators, renderCurrentStep()]
|
|
705
|
+
})]
|
|
530
706
|
});
|
|
531
707
|
};
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
708
|
+
|
|
709
|
+
// Memoized styles creation
|
|
710
|
+
const createStyles = (colors, theme) => StyleSheet.create({
|
|
711
|
+
container: {
|
|
712
|
+
flex: 1
|
|
535
713
|
},
|
|
536
|
-
|
|
537
|
-
|
|
714
|
+
scrollContent: {
|
|
715
|
+
flexGrow: 1,
|
|
716
|
+
paddingHorizontal: 24,
|
|
717
|
+
paddingTop: 40,
|
|
718
|
+
paddingBottom: 40
|
|
719
|
+
},
|
|
720
|
+
stepContainer: {
|
|
721
|
+
flex: 1,
|
|
722
|
+
justifyContent: 'center',
|
|
538
723
|
alignItems: 'center',
|
|
539
|
-
|
|
724
|
+
minHeight: 500
|
|
540
725
|
},
|
|
541
|
-
|
|
542
|
-
|
|
726
|
+
welcomeImageContainer: {
|
|
727
|
+
alignItems: 'center',
|
|
728
|
+
justifyContent: 'center',
|
|
729
|
+
marginVertical: 30
|
|
543
730
|
},
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
731
|
+
welcomeTitle: {
|
|
732
|
+
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
733
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
734
|
+
fontSize: 42,
|
|
735
|
+
lineHeight: 48,
|
|
736
|
+
marginBottom: 24,
|
|
737
|
+
textAlign: 'left',
|
|
738
|
+
letterSpacing: -1
|
|
547
739
|
},
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
740
|
+
welcomeText: {
|
|
741
|
+
fontSize: 16,
|
|
742
|
+
textAlign: 'left',
|
|
743
|
+
marginBottom: 30,
|
|
744
|
+
lineHeight: 24
|
|
745
|
+
},
|
|
746
|
+
stepTitle: {
|
|
747
|
+
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
748
|
+
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
749
|
+
fontSize: 34,
|
|
750
|
+
marginBottom: 20,
|
|
751
|
+
color: colors.primary,
|
|
752
|
+
maxWidth: '90%',
|
|
753
|
+
textAlign: 'left'
|
|
553
754
|
},
|
|
554
755
|
inputContainer: {
|
|
555
|
-
marginBottom: 18
|
|
756
|
+
marginBottom: 18,
|
|
757
|
+
width: '100%'
|
|
556
758
|
},
|
|
557
759
|
label: {
|
|
558
760
|
fontSize: 15,
|
|
@@ -566,25 +768,58 @@ const styles = StyleSheet.create({
|
|
|
566
768
|
paddingHorizontal: 16,
|
|
567
769
|
borderWidth: 1,
|
|
568
770
|
fontSize: 16,
|
|
569
|
-
backgroundColor: '#F5F5F5',
|
|
570
|
-
borderColor: '#E0E0E0',
|
|
571
771
|
marginBottom: 2
|
|
572
772
|
},
|
|
773
|
+
validationIndicator: {
|
|
774
|
+
position: 'absolute',
|
|
775
|
+
right: 16,
|
|
776
|
+
top: 14
|
|
777
|
+
},
|
|
778
|
+
validationSuccessCard: {
|
|
779
|
+
flexDirection: 'row',
|
|
780
|
+
alignItems: 'center',
|
|
781
|
+
padding: 12,
|
|
782
|
+
borderRadius: 12,
|
|
783
|
+
marginTop: 8,
|
|
784
|
+
gap: 8
|
|
785
|
+
},
|
|
786
|
+
validationErrorCard: {
|
|
787
|
+
flexDirection: 'row',
|
|
788
|
+
alignItems: 'center',
|
|
789
|
+
padding: 12,
|
|
790
|
+
borderRadius: 12,
|
|
791
|
+
marginTop: 8,
|
|
792
|
+
gap: 8
|
|
793
|
+
},
|
|
794
|
+
validationText: {
|
|
795
|
+
fontSize: 12,
|
|
796
|
+
fontWeight: '500'
|
|
797
|
+
},
|
|
798
|
+
passwordToggle: {
|
|
799
|
+
position: 'absolute',
|
|
800
|
+
right: 16,
|
|
801
|
+
top: 14,
|
|
802
|
+
padding: 4
|
|
803
|
+
},
|
|
804
|
+
passwordHint: {
|
|
805
|
+
fontSize: 12,
|
|
806
|
+
marginTop: 4
|
|
807
|
+
},
|
|
573
808
|
button: {
|
|
574
|
-
backgroundColor: '#d169e5',
|
|
575
809
|
height: 48,
|
|
576
810
|
borderRadius: 24,
|
|
577
811
|
alignItems: 'center',
|
|
578
812
|
justifyContent: 'center',
|
|
579
813
|
marginTop: 24,
|
|
580
|
-
shadowColor:
|
|
814
|
+
shadowColor: colors.primary,
|
|
581
815
|
shadowOpacity: 0.12,
|
|
582
816
|
shadowOffset: {
|
|
583
817
|
width: 0,
|
|
584
818
|
height: 2
|
|
585
819
|
},
|
|
586
820
|
shadowRadius: 8,
|
|
587
|
-
elevation: 2
|
|
821
|
+
elevation: 2,
|
|
822
|
+
width: '100%'
|
|
588
823
|
},
|
|
589
824
|
buttonText: {
|
|
590
825
|
color: '#FFFFFF',
|
|
@@ -598,31 +833,15 @@ const styles = StyleSheet.create({
|
|
|
598
833
|
marginTop: 28
|
|
599
834
|
},
|
|
600
835
|
footerText: {
|
|
601
|
-
fontSize: 15
|
|
602
|
-
color: '#888'
|
|
836
|
+
fontSize: 15
|
|
603
837
|
},
|
|
604
838
|
linkText: {
|
|
605
839
|
fontSize: 15,
|
|
606
|
-
fontWeight: '700'
|
|
607
|
-
color: '#d169e5'
|
|
608
|
-
},
|
|
609
|
-
errorContainer: {
|
|
610
|
-
backgroundColor: '#FFE4EC',
|
|
611
|
-
padding: 14,
|
|
612
|
-
borderRadius: 18,
|
|
613
|
-
marginBottom: 16,
|
|
614
|
-
borderWidth: 1,
|
|
615
|
-
borderColor: '#F8BBD0'
|
|
616
|
-
},
|
|
617
|
-
errorText: {
|
|
618
|
-
color: '#D32F2F',
|
|
619
|
-
fontSize: 15,
|
|
620
|
-
fontWeight: '500'
|
|
840
|
+
fontWeight: '700'
|
|
621
841
|
},
|
|
622
842
|
userInfoContainer: {
|
|
623
843
|
padding: 20,
|
|
624
844
|
marginVertical: 20,
|
|
625
|
-
backgroundColor: '#F5F5F5',
|
|
626
845
|
borderRadius: 24,
|
|
627
846
|
alignItems: 'center',
|
|
628
847
|
shadowColor: '#000',
|
|
@@ -642,44 +861,12 @@ const styles = StyleSheet.create({
|
|
|
642
861
|
actionButtonsContainer: {
|
|
643
862
|
marginTop: 24
|
|
644
863
|
},
|
|
645
|
-
// Multi-step form styles
|
|
646
|
-
welcomeTitle: {
|
|
647
|
-
fontFamily: Platform.OS === 'web' ? 'Phudu' // Use CSS font name directly for web
|
|
648
|
-
: 'Phudu-Bold',
|
|
649
|
-
// Use exact font name as registered with Font.loadAsync
|
|
650
|
-
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
651
|
-
// Only apply fontWeight on web
|
|
652
|
-
fontSize: 54,
|
|
653
|
-
marginBottom: 24
|
|
654
|
-
},
|
|
655
|
-
welcomeText: {
|
|
656
|
-
fontSize: 16,
|
|
657
|
-
textAlign: 'left',
|
|
658
|
-
marginBottom: 30,
|
|
659
|
-
lineHeight: 24,
|
|
660
|
-
color: '#444'
|
|
661
|
-
},
|
|
662
|
-
welcomeImageContainer: {
|
|
663
|
-
alignItems: 'center',
|
|
664
|
-
justifyContent: 'center',
|
|
665
|
-
marginVertical: 30
|
|
666
|
-
},
|
|
667
|
-
stepTitle: {
|
|
668
|
-
fontFamily: Platform.OS === 'web' ? 'Phudu' // Use CSS font name directly for web
|
|
669
|
-
: 'Phudu-Bold',
|
|
670
|
-
// Use exact font name as registered with Font.loadAsync
|
|
671
|
-
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
672
|
-
// Only apply fontWeight on web
|
|
673
|
-
fontSize: 34,
|
|
674
|
-
marginBottom: 20,
|
|
675
|
-
color: '#d169e5',
|
|
676
|
-
maxWidth: '90%'
|
|
677
|
-
},
|
|
678
864
|
navigationButtons: {
|
|
679
865
|
flexDirection: 'row',
|
|
680
866
|
justifyContent: 'space-between',
|
|
681
867
|
alignItems: 'center',
|
|
682
|
-
marginTop: 28
|
|
868
|
+
marginTop: 28,
|
|
869
|
+
width: '100%'
|
|
683
870
|
},
|
|
684
871
|
navButton: {
|
|
685
872
|
borderRadius: 24,
|
|
@@ -691,22 +878,14 @@ const styles = StyleSheet.create({
|
|
|
691
878
|
},
|
|
692
879
|
backButton: {
|
|
693
880
|
backgroundColor: 'transparent',
|
|
694
|
-
borderWidth: 1
|
|
695
|
-
borderColor: '#E0E0E0'
|
|
881
|
+
borderWidth: 1
|
|
696
882
|
},
|
|
697
883
|
nextButton: {
|
|
698
|
-
minWidth: 100
|
|
699
|
-
backgroundColor: '#d169e5'
|
|
884
|
+
minWidth: 100
|
|
700
885
|
},
|
|
701
886
|
navButtonText: {
|
|
702
887
|
fontSize: 16,
|
|
703
|
-
fontWeight: '700'
|
|
704
|
-
color: '#d169e5'
|
|
705
|
-
},
|
|
706
|
-
passwordHint: {
|
|
707
|
-
fontSize: 12,
|
|
708
|
-
marginTop: 4,
|
|
709
|
-
color: '#888'
|
|
888
|
+
fontWeight: '700'
|
|
710
889
|
},
|
|
711
890
|
progressContainer: {
|
|
712
891
|
flexDirection: 'row',
|
|
@@ -719,10 +898,9 @@ const styles = StyleSheet.create({
|
|
|
719
898
|
width: 10,
|
|
720
899
|
borderRadius: 5,
|
|
721
900
|
marginHorizontal: 6,
|
|
722
|
-
backgroundColor: '#E0E0E0',
|
|
723
901
|
borderWidth: 2,
|
|
724
902
|
borderColor: '#fff',
|
|
725
|
-
shadowColor:
|
|
903
|
+
shadowColor: colors.primary,
|
|
726
904
|
shadowOpacity: 0.08,
|
|
727
905
|
shadowOffset: {
|
|
728
906
|
width: 0,
|
|
@@ -733,7 +911,8 @@ const styles = StyleSheet.create({
|
|
|
733
911
|
},
|
|
734
912
|
summaryContainer: {
|
|
735
913
|
padding: 0,
|
|
736
|
-
marginBottom: 24
|
|
914
|
+
marginBottom: 24,
|
|
915
|
+
width: '100%'
|
|
737
916
|
},
|
|
738
917
|
summaryRow: {
|
|
739
918
|
flexDirection: 'row',
|
|
@@ -741,14 +920,12 @@ const styles = StyleSheet.create({
|
|
|
741
920
|
},
|
|
742
921
|
summaryLabel: {
|
|
743
922
|
fontSize: 15,
|
|
744
|
-
width: 90
|
|
745
|
-
color: '#888'
|
|
923
|
+
width: 90
|
|
746
924
|
},
|
|
747
925
|
summaryValue: {
|
|
748
926
|
fontSize: 15,
|
|
749
927
|
fontWeight: '600',
|
|
750
|
-
flex: 1
|
|
751
|
-
color: '#222'
|
|
928
|
+
flex: 1
|
|
752
929
|
}
|
|
753
930
|
});
|
|
754
931
|
export default SignUpScreen;
|