@onairos/react-native 3.1.15 → 3.1.17
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/README.md +404 -0
- package/lib/commonjs/assets/images/Checkbox.svg +3 -3
- package/lib/commonjs/assets/images/EnochE.svg +19 -19
- package/lib/commonjs/assets/images/Personalityprofile.svg +3 -3
- package/lib/commonjs/assets/images/Personalitytraits.svg +3 -3
- package/lib/commonjs/assets/images/Userpreferences.svg +3 -3
- package/lib/commonjs/assets/images/arrow.svg +20 -20
- package/lib/commonjs/assets/images/basicproficon.svg +43 -43
- package/lib/commonjs/assets/images/basicprofile.svg +3 -3
- package/lib/commonjs/assets/images/checkmark.svg +4 -4
- package/lib/commonjs/assets/images/contentanalysis.svg +3 -3
- package/lib/commonjs/assets/images/contenticon.svg +23 -23
- package/lib/commonjs/assets/images/personalityicon.svg +18 -18
- package/lib/commonjs/assets/images/x-close.svg +3 -3
- package/lib/commonjs/components/OnairosSignInButton.js +32 -74
- package/lib/commonjs/components/OnairosSignInButton.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +4 -4
- package/lib/commonjs/config/api.js +2 -2
- package/lib/commonjs/hooks/useConnections.js +6 -6
- package/lib/commonjs/hooks/useUserConnections.js +10 -10
- package/lib/commonjs/index.js +5 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/services/apiClient.js +35 -35
- package/lib/commonjs/services/apiKeyService.js +99 -99
- package/lib/commonjs/services/authService.js +82 -82
- package/lib/commonjs/services/biometricPinService.js +10 -10
- package/lib/commonjs/services/connectedAccountsService.js +32 -32
- package/lib/commonjs/services/googleAuthService.js +15 -15
- package/lib/commonjs/services/imageCompressionService.js +15 -15
- package/lib/commonjs/services/jwtStorageService.js +59 -59
- package/lib/commonjs/services/mobileTrainingService.js +14 -14
- package/lib/commonjs/services/pinEncryptionService.js +10 -10
- package/lib/commonjs/services/pinStorageUtils.js +15 -15
- package/lib/commonjs/services/platformAuthService.js +47 -47
- package/lib/commonjs/services/storageService.js +31 -31
- package/lib/commonjs/services/trainingApiHelpers.js +33 -33
- package/lib/commonjs/services/userConnectionsService.js +24 -24
- package/lib/commonjs/utils/Portal.js +4 -4
- package/lib/commonjs/utils/api.js +24 -24
- package/lib/commonjs/utils/auth.js +18 -18
- package/lib/commonjs/utils/crypto.js +13 -13
- package/lib/commonjs/utils/encryption.js +12 -12
- package/lib/commonjs/utils/eventUtils.js +52 -52
- package/lib/commonjs/utils/programmaticFlow.js +16 -16
- package/lib/commonjs/utils/retryHelper.js +27 -27
- package/lib/module/assets/images/Checkbox.svg +3 -3
- package/lib/module/assets/images/EnochE.svg +19 -19
- package/lib/module/assets/images/Personalityprofile.svg +3 -3
- package/lib/module/assets/images/Personalitytraits.svg +3 -3
- package/lib/module/assets/images/Userpreferences.svg +3 -3
- package/lib/module/assets/images/arrow.svg +20 -20
- package/lib/module/assets/images/basicproficon.svg +43 -43
- package/lib/module/assets/images/basicprofile.svg +3 -3
- package/lib/module/assets/images/checkmark.svg +4 -4
- package/lib/module/assets/images/contentanalysis.svg +3 -3
- package/lib/module/assets/images/contenticon.svg +23 -23
- package/lib/module/assets/images/personalityicon.svg +18 -18
- package/lib/module/assets/images/x-close.svg +3 -3
- package/lib/module/components/OnairosSignInButton.js +32 -74
- package/lib/module/components/OnairosSignInButton.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +4 -4
- package/lib/module/config/api.js +2 -2
- package/lib/module/hooks/useConnections.js +6 -6
- package/lib/module/hooks/useUserConnections.js +10 -10
- package/lib/module/index.js +5 -6
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/apiClient.js +35 -35
- package/lib/module/services/apiKeyService.js +99 -99
- package/lib/module/services/authService.js +82 -82
- package/lib/module/services/biometricPinService.js +10 -10
- package/lib/module/services/connectedAccountsService.js +32 -32
- package/lib/module/services/googleAuthService.js +15 -15
- package/lib/module/services/imageCompressionService.js +15 -15
- package/lib/module/services/jwtStorageService.js +59 -59
- package/lib/module/services/mobileTrainingService.js +14 -14
- package/lib/module/services/pinEncryptionService.js +10 -10
- package/lib/module/services/pinStorageUtils.js +15 -15
- package/lib/module/services/platformAuthService.js +47 -47
- package/lib/module/services/storageService.js +31 -31
- package/lib/module/services/trainingApiHelpers.js +33 -33
- package/lib/module/services/userConnectionsService.js +24 -24
- package/lib/module/utils/Portal.js +4 -4
- package/lib/module/utils/api.js +24 -24
- package/lib/module/utils/auth.js +18 -18
- package/lib/module/utils/crypto.js +13 -13
- package/lib/module/utils/encryption.js +12 -12
- package/lib/module/utils/eventUtils.js +52 -52
- package/lib/module/utils/programmaticFlow.js +16 -16
- package/lib/module/utils/retryHelper.js +27 -27
- package/lib/typescript/components/OnairosSignInButton.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +0 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +163 -163
- package/src/api/index.ts +151 -151
- package/src/assets/images/Checkbox.svg +3 -3
- package/src/assets/images/EnochE.svg +19 -19
- package/src/assets/images/Personalityprofile.svg +3 -3
- package/src/assets/images/Personalitytraits.svg +3 -3
- package/src/assets/images/Userpreferences.svg +3 -3
- package/src/assets/images/arrow.svg +20 -20
- package/src/assets/images/basicproficon.svg +43 -43
- package/src/assets/images/basicprofile.svg +3 -3
- package/src/assets/images/checkmark.svg +4 -4
- package/src/assets/images/contentanalysis.svg +3 -3
- package/src/assets/images/contenticon.svg +23 -23
- package/src/assets/images/personalityicon.svg +18 -18
- package/src/assets/images/x-close.svg +3 -3
- package/src/components/BodyText.tsx +33 -33
- package/src/components/BrandMark.tsx +62 -62
- package/src/components/CodeInput.tsx +32 -32
- package/src/components/DataRequestScreen.tsx +355 -355
- package/src/components/EmailInput.tsx +31 -31
- package/src/components/EmailVerificationModal.tsx +363 -363
- package/src/components/ExistingUserDataConfirmation.tsx +506 -506
- package/src/components/GoogleButton.tsx +55 -55
- package/src/components/HeadingGroup.tsx +49 -49
- package/src/components/ModalHeader.tsx +125 -125
- package/src/components/ModalSheet.tsx +57 -57
- package/src/components/Onairos.tsx +422 -422
- package/src/components/OnairosButton.tsx +339 -339
- package/src/components/OnairosSignInButton.tsx +130 -166
- package/src/components/Overlay.tsx +506 -506
- package/src/components/PersonaImage.tsx +79 -79
- package/src/components/PersonaLoadingScreen.tsx +201 -201
- package/src/components/PersonalizationConsentScreen.tsx +410 -410
- package/src/components/PinCreationScreen.tsx +492 -492
- package/src/components/PinInput.tsx +555 -555
- package/src/components/PlatformConnectorsStep.tsx +891 -891
- package/src/components/PlatformList.tsx +144 -144
- package/src/components/PlatformToggle.tsx +226 -226
- package/src/components/PrimaryButton.tsx +213 -213
- package/src/components/SignInMatchAnimation.tsx +225 -225
- package/src/components/SignInStep.tsx +217 -217
- package/src/components/TrainingModal.tsx +1047 -1047
- package/src/components/UniversalOnboarding.tsx +2887 -2887
- package/src/components/VerificationStep.tsx +198 -198
- package/src/components/WelcomeScreen.tsx +473 -473
- package/src/components/icons/Basicproficon.tsx +30 -30
- package/src/components/icons/Basicprofile.tsx +17 -17
- package/src/components/icons/Checkbox.tsx +17 -17
- package/src/components/icons/Checkmark.tsx +24 -24
- package/src/components/icons/Contentanalysis.tsx +17 -17
- package/src/components/icons/Contenticon.tsx +30 -30
- package/src/components/icons/EnochE.tsx +39 -39
- package/src/components/icons/Personalityicon.tsx +22 -22
- package/src/components/icons/Personalityprofile.tsx +17 -17
- package/src/components/icons/Personalitytraits.tsx +17 -17
- package/src/components/icons/Userpreferences.tsx +17 -17
- package/src/components/icons/index.ts +12 -12
- package/src/components/onboarding/OAuthWebView.tsx +232 -232
- package/src/config/api.ts +25 -25
- package/src/context/AuthContext.tsx +393 -393
- package/src/hooks/useConnectedAccounts.ts +138 -138
- package/src/hooks/useConnections.ts +161 -161
- package/src/hooks/useCredentials.ts +174 -174
- package/src/hooks/useUserConnections.ts +165 -165
- package/src/index.js +14 -14
- package/src/index.ts +94 -95
- package/src/services/apiClient.ts +336 -336
- package/src/services/apiKeyService.ts +919 -919
- package/src/services/authService.ts +1008 -1008
- package/src/services/biometricPinService.ts +192 -192
- package/src/services/connectedAccountsService.ts +289 -289
- package/src/services/googleAuthService.ts +279 -279
- package/src/services/imageCompressionService.ts +302 -302
- package/src/services/jwtStorageService.ts +256 -256
- package/src/services/mobileTrainingService.ts +203 -203
- package/src/services/pinEncryptionService.ts +75 -75
- package/src/services/pinStorageUtils.ts +96 -96
- package/src/services/platformAuthService.ts +1346 -1346
- package/src/services/storageService.ts +451 -451
- package/src/services/trainingApiHelpers.ts +66 -66
- package/src/services/userConnectionsService.ts +556 -556
- package/src/services/youtubeMigrationService.ts +453 -453
- package/src/theme/index.ts +239 -239
- package/src/types/ambient.d.ts +28 -28
- package/src/types/index.ts +265 -265
- package/src/types/node-fix.d.ts +18 -18
- package/src/types/node-override.d.ts +23 -23
- package/src/types/opacity.d.ts +15 -15
- package/src/types/types.d.ts +17 -17
- package/src/utils/Portal.tsx +82 -82
- package/src/utils/api.js +111 -111
- package/src/utils/auth.js +103 -103
- package/src/utils/crypto.js +59 -59
- package/src/utils/encryption.ts +68 -68
- package/src/utils/eventUtils.ts +302 -302
- package/src/utils/haptics.ts +58 -58
- package/src/utils/imagePreloader.ts +2 -2
- package/src/utils/programmaticFlow.ts +112 -112
- package/src/utils/retryHelper.ts +274 -274
|
@@ -1,393 +1,393 @@
|
|
|
1
|
-
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
2
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
3
|
-
import { User } from '../types/index';
|
|
4
|
-
import {
|
|
5
|
-
saveAuthToken,
|
|
6
|
-
getAuthToken,
|
|
7
|
-
removeAuthToken,
|
|
8
|
-
verifyToken,
|
|
9
|
-
getUserProfile,
|
|
10
|
-
authenticateWithApple,
|
|
11
|
-
authenticateWithOnairos,
|
|
12
|
-
authenticateWithOnairosSignIn,
|
|
13
|
-
updateUserOnboardedStatus
|
|
14
|
-
} from '../services/authService';
|
|
15
|
-
import {
|
|
16
|
-
saveUserProgress,
|
|
17
|
-
saveAuthState,
|
|
18
|
-
getAuthState,
|
|
19
|
-
clearUserData,
|
|
20
|
-
getResumeTarget,
|
|
21
|
-
markStepCompleted,
|
|
22
|
-
updateLastScreen,
|
|
23
|
-
isReturningUser,
|
|
24
|
-
markEventPageReached,
|
|
25
|
-
hasEventAccessToken,
|
|
26
|
-
STORAGE_KEYS
|
|
27
|
-
} from '../services/storageService';
|
|
28
|
-
|
|
29
|
-
interface AuthContextType {
|
|
30
|
-
user: User | null;
|
|
31
|
-
isLoading: boolean;
|
|
32
|
-
hasCompletedOnboarding: boolean;
|
|
33
|
-
login: (userData: User) => void;
|
|
34
|
-
logout: () => void;
|
|
35
|
-
deleteAccount: () => Promise<void>;
|
|
36
|
-
completeOnboarding: (userData: Partial<User>) => void;
|
|
37
|
-
updateUser: (userData: Partial<User>) => void;
|
|
38
|
-
appleSignIn: (appleAuthData: any) => Promise<User>;
|
|
39
|
-
onairosSignIn: (onairosAuthData: { token: string; email: string }) => Promise<User>;
|
|
40
|
-
isAuthenticated: boolean;
|
|
41
|
-
updateOnboardedStatus: () => Promise<void>;
|
|
42
|
-
// New methods for progress tracking
|
|
43
|
-
getResumeTarget: () => Promise<{ screen: string; params?: any }>;
|
|
44
|
-
markStepCompleted: (step: string) => Promise<void>;
|
|
45
|
-
updateLastScreen: (screen: string, params?: any) => Promise<void>;
|
|
46
|
-
isReturningUser: () => Promise<boolean>;
|
|
47
|
-
// New methods for event access token
|
|
48
|
-
markEventPageReached: (eventData?: any) => Promise<void>;
|
|
49
|
-
hasEventAccessToken: () => Promise<boolean>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
53
|
-
|
|
54
|
-
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
55
|
-
const [user, setUser] = useState<User | null>(null);
|
|
56
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
57
|
-
const [hasCompletedOnboarding, setHasCompletedOnboarding] = useState(false);
|
|
58
|
-
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
// Check if user is already logged in
|
|
62
|
-
const loadStoredUser = async () => {
|
|
63
|
-
try {
|
|
64
|
-
// PRIORITY 1: Check if user has completed onboarding (for release mode reliability)
|
|
65
|
-
const hasEventToken = await hasEventAccessToken();
|
|
66
|
-
const storedUser = await AsyncStorage.getItem('user');
|
|
67
|
-
|
|
68
|
-
if (hasEventToken && storedUser) {
|
|
69
|
-
console.log('🎯 Found event access token - user has completed onboarding, authentication confirmed');
|
|
70
|
-
setUser(JSON.parse(storedUser));
|
|
71
|
-
setIsAuthenticated(true);
|
|
72
|
-
setHasCompletedOnboarding(true);
|
|
73
|
-
setIsLoading(false);
|
|
74
|
-
return; // Skip network verification for completed users
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// PRIORITY 2: Check if we have a JWT token for users still in onboarding
|
|
78
|
-
const token = await getAuthToken();
|
|
79
|
-
|
|
80
|
-
if (token) {
|
|
81
|
-
// For users with tokens but no completion token, try network verification
|
|
82
|
-
// but don't fail if network is unreachable (important for release mode)
|
|
83
|
-
let isValid = false;
|
|
84
|
-
try {
|
|
85
|
-
isValid = await verifyToken();
|
|
86
|
-
} catch (networkError) {
|
|
87
|
-
console.warn('🌐 Network verification failed, using local token validation:', networkError);
|
|
88
|
-
// In release mode, network might be slow/unreliable
|
|
89
|
-
// If we have a token and stored user, trust the local state
|
|
90
|
-
if (storedUser) {
|
|
91
|
-
console.log('💾 Network unreachable, trusting local authentication state');
|
|
92
|
-
isValid = true; // Trust local state when network fails
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (isValid) {
|
|
97
|
-
// Token is valid (or we're trusting local state), get user data
|
|
98
|
-
if (storedUser) {
|
|
99
|
-
setUser(JSON.parse(storedUser));
|
|
100
|
-
setIsAuthenticated(true);
|
|
101
|
-
} else {
|
|
102
|
-
// If user data is not in AsyncStorage, try to fetch it
|
|
103
|
-
try {
|
|
104
|
-
const userData = await getUserProfile();
|
|
105
|
-
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
106
|
-
setUser(userData);
|
|
107
|
-
setIsAuthenticated(true);
|
|
108
|
-
} catch (profileError) {
|
|
109
|
-
console.error('Failed to fetch user profile:', profileError);
|
|
110
|
-
// Only remove token if we're sure it's invalid (not just network issues)
|
|
111
|
-
const errorMessage = profileError instanceof Error ? profileError.message : String(profileError);
|
|
112
|
-
if (errorMessage.includes('401') || errorMessage.includes('403')) {
|
|
113
|
-
await removeAuthToken();
|
|
114
|
-
} else {
|
|
115
|
-
console.log('🌐 Profile fetch failed (likely network), keeping authentication state');
|
|
116
|
-
// Create fallback user for offline scenarios
|
|
117
|
-
if (token) {
|
|
118
|
-
const fallbackUser = {
|
|
119
|
-
id: 'offline_user',
|
|
120
|
-
name: 'Onairos User',
|
|
121
|
-
email: 'user@onairos.com',
|
|
122
|
-
onboarded: false
|
|
123
|
-
};
|
|
124
|
-
await AsyncStorage.setItem('user', JSON.stringify(fallbackUser));
|
|
125
|
-
setUser(fallbackUser);
|
|
126
|
-
setIsAuthenticated(true);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
// Token verification definitely failed - remove it
|
|
133
|
-
await removeAuthToken();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const onboardingCompleted = await AsyncStorage.getItem('onboardingCompleted');
|
|
138
|
-
if (onboardingCompleted === 'true') {
|
|
139
|
-
setHasCompletedOnboarding(true);
|
|
140
|
-
}
|
|
141
|
-
} catch (error) {
|
|
142
|
-
console.error('Failed to load authentication state:', error);
|
|
143
|
-
} finally {
|
|
144
|
-
setIsLoading(false);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
loadStoredUser();
|
|
149
|
-
}, []);
|
|
150
|
-
|
|
151
|
-
const login = async (userData: User) => {
|
|
152
|
-
try {
|
|
153
|
-
// Ensure onboarded is set to false for new users
|
|
154
|
-
const userWithOnboarded = {
|
|
155
|
-
...userData,
|
|
156
|
-
onboarded: false // Always force camera flow for new logins
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
await AsyncStorage.setItem('user', JSON.stringify(userWithOnboarded));
|
|
160
|
-
setUser(userWithOnboarded);
|
|
161
|
-
setIsAuthenticated(true);
|
|
162
|
-
|
|
163
|
-
// Save auth state and mark authentication step as completed
|
|
164
|
-
await saveAuthState({
|
|
165
|
-
isAuthenticated: true,
|
|
166
|
-
authMethod: userData.email?.includes('apple') ? 'apple' : 'onairos',
|
|
167
|
-
hasValidToken: true,
|
|
168
|
-
userEmail: userData.email,
|
|
169
|
-
userName: userData.name
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
await markStepCompleted('authentication');
|
|
173
|
-
|
|
174
|
-
console.log('User logged in with onboarded=false:', userWithOnboarded);
|
|
175
|
-
} catch (error) {
|
|
176
|
-
console.error('Failed to save user data:', error);
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// Handle Apple Sign-In
|
|
181
|
-
const appleSignIn = async (appleAuthData: any): Promise<User> => {
|
|
182
|
-
try {
|
|
183
|
-
setIsLoading(true);
|
|
184
|
-
|
|
185
|
-
// Call the API to authenticate with Apple
|
|
186
|
-
const authResponse = await authenticateWithApple(appleAuthData);
|
|
187
|
-
|
|
188
|
-
// Save the JWT token
|
|
189
|
-
await saveAuthToken(authResponse.token);
|
|
190
|
-
|
|
191
|
-
// CRITICAL: Save auth method as 'apple' for proper button logic
|
|
192
|
-
await AsyncStorage.setItem('auth_method', 'apple');
|
|
193
|
-
|
|
194
|
-
// Save Onairos connection status from backend response
|
|
195
|
-
if (authResponse.onairos) {
|
|
196
|
-
await AsyncStorage.setItem('hasConnectedOnairos', authResponse.onairos.hasConnectedOnairos.toString());
|
|
197
|
-
if (authResponse.onairos.onairosUserId) {
|
|
198
|
-
await AsyncStorage.setItem('onairosUserId', authResponse.onairos.onairosUserId);
|
|
199
|
-
}
|
|
200
|
-
if (authResponse.onairos.lastConnectedAt) {
|
|
201
|
-
await AsyncStorage.setItem('lastConnectedAt', authResponse.onairos.lastConnectedAt);
|
|
202
|
-
}
|
|
203
|
-
console.log('🔗 Stored Onairos connection status:', authResponse.onairos.hasConnectedOnairos);
|
|
204
|
-
} else {
|
|
205
|
-
// Default to false if no Onairos info provided
|
|
206
|
-
await AsyncStorage.setItem('hasConnectedOnairos', 'false');
|
|
207
|
-
console.log('🔗 No Onairos connection info from backend, defaulting to false');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Create user object from response
|
|
211
|
-
const userData: User = {
|
|
212
|
-
id: authResponse.user.id,
|
|
213
|
-
name: authResponse.user.name || 'Onairos User',
|
|
214
|
-
email: authResponse.user.email,
|
|
215
|
-
profilePicture: authResponse.user.profilePicture,
|
|
216
|
-
onboarded: false // Default to false for new Apple sign-ins
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
// Save user data to AsyncStorage and update state
|
|
220
|
-
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
221
|
-
setUser(userData);
|
|
222
|
-
setIsAuthenticated(true);
|
|
223
|
-
|
|
224
|
-
console.log('🍎 Apple sign-in completed - auth_method set to "apple"');
|
|
225
|
-
|
|
226
|
-
return userData;
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.error('Apple sign-in failed:', error);
|
|
229
|
-
throw error;
|
|
230
|
-
} finally {
|
|
231
|
-
setIsLoading(false);
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// Handle Onairos Sign-In (similar to Apple)
|
|
236
|
-
const onairosSignIn = async (onairosAuthData: { token: string; email: string }): Promise<User> => {
|
|
237
|
-
try {
|
|
238
|
-
setIsLoading(true);
|
|
239
|
-
|
|
240
|
-
// Call the API to authenticate with Onairos
|
|
241
|
-
const authResponse = await authenticateWithOnairos(onairosAuthData);
|
|
242
|
-
|
|
243
|
-
// Save the JWT token
|
|
244
|
-
await saveAuthToken(authResponse.token);
|
|
245
|
-
|
|
246
|
-
// CRITICAL: Save auth method as 'onairos' for proper button logic
|
|
247
|
-
await AsyncStorage.setItem('auth_method', 'onairos');
|
|
248
|
-
|
|
249
|
-
// Create user object from response
|
|
250
|
-
const userData: User = {
|
|
251
|
-
id: authResponse.user.id,
|
|
252
|
-
name: authResponse.user.name || 'Onairos User',
|
|
253
|
-
email: authResponse.user.email,
|
|
254
|
-
profilePicture: authResponse.user.profilePicture,
|
|
255
|
-
onboarded: false // Default to false for new Onairos sign-ins
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
// Save user data to AsyncStorage and update state
|
|
259
|
-
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
260
|
-
setUser(userData);
|
|
261
|
-
setIsAuthenticated(true);
|
|
262
|
-
|
|
263
|
-
console.log('🔑 Onairos sign-in completed - auth_method set to "onairos"');
|
|
264
|
-
|
|
265
|
-
return userData;
|
|
266
|
-
} catch (error) {
|
|
267
|
-
console.error('Onairos sign-in failed:', error);
|
|
268
|
-
throw error;
|
|
269
|
-
} finally {
|
|
270
|
-
setIsLoading(false);
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const logout = async () => {
|
|
275
|
-
try {
|
|
276
|
-
// Clear all user data using the new storage service
|
|
277
|
-
await clearUserData();
|
|
278
|
-
setUser(null);
|
|
279
|
-
setIsAuthenticated(false);
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.error('Failed to remove user data:', error);
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const completeOnboarding = async (userData: Partial<User>) => {
|
|
286
|
-
try {
|
|
287
|
-
// Update user data
|
|
288
|
-
const updatedUser = { ...user, ...userData };
|
|
289
|
-
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
290
|
-
setUser(updatedUser as User);
|
|
291
|
-
|
|
292
|
-
// Update onboarded status on backend
|
|
293
|
-
await updateOnboardedStatus();
|
|
294
|
-
} catch (error) {
|
|
295
|
-
console.error('Failed to complete onboarding:', error);
|
|
296
|
-
throw error;
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const updateUser = async (userData: Partial<User>) => {
|
|
301
|
-
try {
|
|
302
|
-
if (!user) return;
|
|
303
|
-
const updatedUser = { ...user, ...userData };
|
|
304
|
-
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
305
|
-
setUser(updatedUser);
|
|
306
|
-
} catch (error) {
|
|
307
|
-
console.error('Failed to update user data:', error);
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
// Update user onboarded status
|
|
312
|
-
const updateOnboardedStatus = async (): Promise<void> => {
|
|
313
|
-
try {
|
|
314
|
-
setIsLoading(true);
|
|
315
|
-
|
|
316
|
-
// Call the API to update onboarded status
|
|
317
|
-
await updateUserOnboardedStatus();
|
|
318
|
-
|
|
319
|
-
// Update local user data
|
|
320
|
-
if (user) {
|
|
321
|
-
const updatedUser = { ...user, onboarded: true };
|
|
322
|
-
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
323
|
-
setUser(updatedUser);
|
|
324
|
-
}
|
|
325
|
-
} catch (error) {
|
|
326
|
-
console.error('Failed to update onboarded status:', error);
|
|
327
|
-
throw error;
|
|
328
|
-
} finally {
|
|
329
|
-
setIsLoading(false);
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const deleteAccount = async () => {
|
|
334
|
-
try {
|
|
335
|
-
// In a real app, you would make an API call to delete the user account on the server
|
|
336
|
-
// For example: await api.deleteUser(user.id);
|
|
337
|
-
|
|
338
|
-
// Remove user data from AsyncStorage
|
|
339
|
-
await AsyncStorage.removeItem('user');
|
|
340
|
-
|
|
341
|
-
// Remove JWT token
|
|
342
|
-
await removeAuthToken();
|
|
343
|
-
|
|
344
|
-
// Clear any other user-related data from AsyncStorage
|
|
345
|
-
await AsyncStorage.removeItem('onboardingCompleted');
|
|
346
|
-
|
|
347
|
-
// Update state
|
|
348
|
-
setUser(null);
|
|
349
|
-
setIsAuthenticated(false);
|
|
350
|
-
setHasCompletedOnboarding(false);
|
|
351
|
-
|
|
352
|
-
console.log('Account deleted successfully');
|
|
353
|
-
} catch (error) {
|
|
354
|
-
console.error('Failed to delete account:', error);
|
|
355
|
-
throw error;
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
return (
|
|
360
|
-
<AuthContext.Provider value={{
|
|
361
|
-
user,
|
|
362
|
-
isLoading,
|
|
363
|
-
hasCompletedOnboarding,
|
|
364
|
-
login,
|
|
365
|
-
logout,
|
|
366
|
-
deleteAccount,
|
|
367
|
-
completeOnboarding,
|
|
368
|
-
updateUser,
|
|
369
|
-
appleSignIn,
|
|
370
|
-
onairosSignIn,
|
|
371
|
-
isAuthenticated,
|
|
372
|
-
updateOnboardedStatus,
|
|
373
|
-
// Progress tracking methods
|
|
374
|
-
getResumeTarget,
|
|
375
|
-
markStepCompleted,
|
|
376
|
-
updateLastScreen,
|
|
377
|
-
isReturningUser,
|
|
378
|
-
// Event access token methods
|
|
379
|
-
markEventPageReached,
|
|
380
|
-
hasEventAccessToken
|
|
381
|
-
}}>
|
|
382
|
-
{children}
|
|
383
|
-
</AuthContext.Provider>
|
|
384
|
-
);
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
export const useAuth = (): AuthContextType => {
|
|
388
|
-
const context = useContext(AuthContext);
|
|
389
|
-
if (context === undefined) {
|
|
390
|
-
throw new Error('useAuth must be used within an AuthProvider');
|
|
391
|
-
}
|
|
392
|
-
return context;
|
|
393
|
-
};
|
|
1
|
+
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
2
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
3
|
+
import { User } from '../types/index';
|
|
4
|
+
import {
|
|
5
|
+
saveAuthToken,
|
|
6
|
+
getAuthToken,
|
|
7
|
+
removeAuthToken,
|
|
8
|
+
verifyToken,
|
|
9
|
+
getUserProfile,
|
|
10
|
+
authenticateWithApple,
|
|
11
|
+
authenticateWithOnairos,
|
|
12
|
+
authenticateWithOnairosSignIn,
|
|
13
|
+
updateUserOnboardedStatus
|
|
14
|
+
} from '../services/authService';
|
|
15
|
+
import {
|
|
16
|
+
saveUserProgress,
|
|
17
|
+
saveAuthState,
|
|
18
|
+
getAuthState,
|
|
19
|
+
clearUserData,
|
|
20
|
+
getResumeTarget,
|
|
21
|
+
markStepCompleted,
|
|
22
|
+
updateLastScreen,
|
|
23
|
+
isReturningUser,
|
|
24
|
+
markEventPageReached,
|
|
25
|
+
hasEventAccessToken,
|
|
26
|
+
STORAGE_KEYS
|
|
27
|
+
} from '../services/storageService';
|
|
28
|
+
|
|
29
|
+
interface AuthContextType {
|
|
30
|
+
user: User | null;
|
|
31
|
+
isLoading: boolean;
|
|
32
|
+
hasCompletedOnboarding: boolean;
|
|
33
|
+
login: (userData: User) => void;
|
|
34
|
+
logout: () => void;
|
|
35
|
+
deleteAccount: () => Promise<void>;
|
|
36
|
+
completeOnboarding: (userData: Partial<User>) => void;
|
|
37
|
+
updateUser: (userData: Partial<User>) => void;
|
|
38
|
+
appleSignIn: (appleAuthData: any) => Promise<User>;
|
|
39
|
+
onairosSignIn: (onairosAuthData: { token: string; email: string }) => Promise<User>;
|
|
40
|
+
isAuthenticated: boolean;
|
|
41
|
+
updateOnboardedStatus: () => Promise<void>;
|
|
42
|
+
// New methods for progress tracking
|
|
43
|
+
getResumeTarget: () => Promise<{ screen: string; params?: any }>;
|
|
44
|
+
markStepCompleted: (step: string) => Promise<void>;
|
|
45
|
+
updateLastScreen: (screen: string, params?: any) => Promise<void>;
|
|
46
|
+
isReturningUser: () => Promise<boolean>;
|
|
47
|
+
// New methods for event access token
|
|
48
|
+
markEventPageReached: (eventData?: any) => Promise<void>;
|
|
49
|
+
hasEventAccessToken: () => Promise<boolean>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
53
|
+
|
|
54
|
+
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
55
|
+
const [user, setUser] = useState<User | null>(null);
|
|
56
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
57
|
+
const [hasCompletedOnboarding, setHasCompletedOnboarding] = useState(false);
|
|
58
|
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
// Check if user is already logged in
|
|
62
|
+
const loadStoredUser = async () => {
|
|
63
|
+
try {
|
|
64
|
+
// PRIORITY 1: Check if user has completed onboarding (for release mode reliability)
|
|
65
|
+
const hasEventToken = await hasEventAccessToken();
|
|
66
|
+
const storedUser = await AsyncStorage.getItem('user');
|
|
67
|
+
|
|
68
|
+
if (hasEventToken && storedUser) {
|
|
69
|
+
console.log('🎯 Found event access token - user has completed onboarding, authentication confirmed');
|
|
70
|
+
setUser(JSON.parse(storedUser));
|
|
71
|
+
setIsAuthenticated(true);
|
|
72
|
+
setHasCompletedOnboarding(true);
|
|
73
|
+
setIsLoading(false);
|
|
74
|
+
return; // Skip network verification for completed users
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// PRIORITY 2: Check if we have a JWT token for users still in onboarding
|
|
78
|
+
const token = await getAuthToken();
|
|
79
|
+
|
|
80
|
+
if (token) {
|
|
81
|
+
// For users with tokens but no completion token, try network verification
|
|
82
|
+
// but don't fail if network is unreachable (important for release mode)
|
|
83
|
+
let isValid = false;
|
|
84
|
+
try {
|
|
85
|
+
isValid = await verifyToken();
|
|
86
|
+
} catch (networkError) {
|
|
87
|
+
console.warn('🌐 Network verification failed, using local token validation:', networkError);
|
|
88
|
+
// In release mode, network might be slow/unreliable
|
|
89
|
+
// If we have a token and stored user, trust the local state
|
|
90
|
+
if (storedUser) {
|
|
91
|
+
console.log('💾 Network unreachable, trusting local authentication state');
|
|
92
|
+
isValid = true; // Trust local state when network fails
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (isValid) {
|
|
97
|
+
// Token is valid (or we're trusting local state), get user data
|
|
98
|
+
if (storedUser) {
|
|
99
|
+
setUser(JSON.parse(storedUser));
|
|
100
|
+
setIsAuthenticated(true);
|
|
101
|
+
} else {
|
|
102
|
+
// If user data is not in AsyncStorage, try to fetch it
|
|
103
|
+
try {
|
|
104
|
+
const userData = await getUserProfile();
|
|
105
|
+
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
106
|
+
setUser(userData);
|
|
107
|
+
setIsAuthenticated(true);
|
|
108
|
+
} catch (profileError) {
|
|
109
|
+
console.error('Failed to fetch user profile:', profileError);
|
|
110
|
+
// Only remove token if we're sure it's invalid (not just network issues)
|
|
111
|
+
const errorMessage = profileError instanceof Error ? profileError.message : String(profileError);
|
|
112
|
+
if (errorMessage.includes('401') || errorMessage.includes('403')) {
|
|
113
|
+
await removeAuthToken();
|
|
114
|
+
} else {
|
|
115
|
+
console.log('🌐 Profile fetch failed (likely network), keeping authentication state');
|
|
116
|
+
// Create fallback user for offline scenarios
|
|
117
|
+
if (token) {
|
|
118
|
+
const fallbackUser = {
|
|
119
|
+
id: 'offline_user',
|
|
120
|
+
name: 'Onairos User',
|
|
121
|
+
email: 'user@onairos.com',
|
|
122
|
+
onboarded: false
|
|
123
|
+
};
|
|
124
|
+
await AsyncStorage.setItem('user', JSON.stringify(fallbackUser));
|
|
125
|
+
setUser(fallbackUser);
|
|
126
|
+
setIsAuthenticated(true);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
// Token verification definitely failed - remove it
|
|
133
|
+
await removeAuthToken();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const onboardingCompleted = await AsyncStorage.getItem('onboardingCompleted');
|
|
138
|
+
if (onboardingCompleted === 'true') {
|
|
139
|
+
setHasCompletedOnboarding(true);
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error('Failed to load authentication state:', error);
|
|
143
|
+
} finally {
|
|
144
|
+
setIsLoading(false);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
loadStoredUser();
|
|
149
|
+
}, []);
|
|
150
|
+
|
|
151
|
+
const login = async (userData: User) => {
|
|
152
|
+
try {
|
|
153
|
+
// Ensure onboarded is set to false for new users
|
|
154
|
+
const userWithOnboarded = {
|
|
155
|
+
...userData,
|
|
156
|
+
onboarded: false // Always force camera flow for new logins
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
await AsyncStorage.setItem('user', JSON.stringify(userWithOnboarded));
|
|
160
|
+
setUser(userWithOnboarded);
|
|
161
|
+
setIsAuthenticated(true);
|
|
162
|
+
|
|
163
|
+
// Save auth state and mark authentication step as completed
|
|
164
|
+
await saveAuthState({
|
|
165
|
+
isAuthenticated: true,
|
|
166
|
+
authMethod: userData.email?.includes('apple') ? 'apple' : 'onairos',
|
|
167
|
+
hasValidToken: true,
|
|
168
|
+
userEmail: userData.email,
|
|
169
|
+
userName: userData.name
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await markStepCompleted('authentication');
|
|
173
|
+
|
|
174
|
+
console.log('User logged in with onboarded=false:', userWithOnboarded);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error('Failed to save user data:', error);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Handle Apple Sign-In
|
|
181
|
+
const appleSignIn = async (appleAuthData: any): Promise<User> => {
|
|
182
|
+
try {
|
|
183
|
+
setIsLoading(true);
|
|
184
|
+
|
|
185
|
+
// Call the API to authenticate with Apple
|
|
186
|
+
const authResponse = await authenticateWithApple(appleAuthData);
|
|
187
|
+
|
|
188
|
+
// Save the JWT token
|
|
189
|
+
await saveAuthToken(authResponse.token);
|
|
190
|
+
|
|
191
|
+
// CRITICAL: Save auth method as 'apple' for proper button logic
|
|
192
|
+
await AsyncStorage.setItem('auth_method', 'apple');
|
|
193
|
+
|
|
194
|
+
// Save Onairos connection status from backend response
|
|
195
|
+
if (authResponse.onairos) {
|
|
196
|
+
await AsyncStorage.setItem('hasConnectedOnairos', authResponse.onairos.hasConnectedOnairos.toString());
|
|
197
|
+
if (authResponse.onairos.onairosUserId) {
|
|
198
|
+
await AsyncStorage.setItem('onairosUserId', authResponse.onairos.onairosUserId);
|
|
199
|
+
}
|
|
200
|
+
if (authResponse.onairos.lastConnectedAt) {
|
|
201
|
+
await AsyncStorage.setItem('lastConnectedAt', authResponse.onairos.lastConnectedAt);
|
|
202
|
+
}
|
|
203
|
+
console.log('🔗 Stored Onairos connection status:', authResponse.onairos.hasConnectedOnairos);
|
|
204
|
+
} else {
|
|
205
|
+
// Default to false if no Onairos info provided
|
|
206
|
+
await AsyncStorage.setItem('hasConnectedOnairos', 'false');
|
|
207
|
+
console.log('🔗 No Onairos connection info from backend, defaulting to false');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Create user object from response
|
|
211
|
+
const userData: User = {
|
|
212
|
+
id: authResponse.user.id,
|
|
213
|
+
name: authResponse.user.name || 'Onairos User',
|
|
214
|
+
email: authResponse.user.email,
|
|
215
|
+
profilePicture: authResponse.user.profilePicture,
|
|
216
|
+
onboarded: false // Default to false for new Apple sign-ins
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Save user data to AsyncStorage and update state
|
|
220
|
+
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
221
|
+
setUser(userData);
|
|
222
|
+
setIsAuthenticated(true);
|
|
223
|
+
|
|
224
|
+
console.log('🍎 Apple sign-in completed - auth_method set to "apple"');
|
|
225
|
+
|
|
226
|
+
return userData;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('Apple sign-in failed:', error);
|
|
229
|
+
throw error;
|
|
230
|
+
} finally {
|
|
231
|
+
setIsLoading(false);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Handle Onairos Sign-In (similar to Apple)
|
|
236
|
+
const onairosSignIn = async (onairosAuthData: { token: string; email: string }): Promise<User> => {
|
|
237
|
+
try {
|
|
238
|
+
setIsLoading(true);
|
|
239
|
+
|
|
240
|
+
// Call the API to authenticate with Onairos
|
|
241
|
+
const authResponse = await authenticateWithOnairos(onairosAuthData);
|
|
242
|
+
|
|
243
|
+
// Save the JWT token
|
|
244
|
+
await saveAuthToken(authResponse.token);
|
|
245
|
+
|
|
246
|
+
// CRITICAL: Save auth method as 'onairos' for proper button logic
|
|
247
|
+
await AsyncStorage.setItem('auth_method', 'onairos');
|
|
248
|
+
|
|
249
|
+
// Create user object from response
|
|
250
|
+
const userData: User = {
|
|
251
|
+
id: authResponse.user.id,
|
|
252
|
+
name: authResponse.user.name || 'Onairos User',
|
|
253
|
+
email: authResponse.user.email,
|
|
254
|
+
profilePicture: authResponse.user.profilePicture,
|
|
255
|
+
onboarded: false // Default to false for new Onairos sign-ins
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Save user data to AsyncStorage and update state
|
|
259
|
+
await AsyncStorage.setItem('user', JSON.stringify(userData));
|
|
260
|
+
setUser(userData);
|
|
261
|
+
setIsAuthenticated(true);
|
|
262
|
+
|
|
263
|
+
console.log('🔑 Onairos sign-in completed - auth_method set to "onairos"');
|
|
264
|
+
|
|
265
|
+
return userData;
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error('Onairos sign-in failed:', error);
|
|
268
|
+
throw error;
|
|
269
|
+
} finally {
|
|
270
|
+
setIsLoading(false);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const logout = async () => {
|
|
275
|
+
try {
|
|
276
|
+
// Clear all user data using the new storage service
|
|
277
|
+
await clearUserData();
|
|
278
|
+
setUser(null);
|
|
279
|
+
setIsAuthenticated(false);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error('Failed to remove user data:', error);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const completeOnboarding = async (userData: Partial<User>) => {
|
|
286
|
+
try {
|
|
287
|
+
// Update user data
|
|
288
|
+
const updatedUser = { ...user, ...userData };
|
|
289
|
+
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
290
|
+
setUser(updatedUser as User);
|
|
291
|
+
|
|
292
|
+
// Update onboarded status on backend
|
|
293
|
+
await updateOnboardedStatus();
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.error('Failed to complete onboarding:', error);
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const updateUser = async (userData: Partial<User>) => {
|
|
301
|
+
try {
|
|
302
|
+
if (!user) return;
|
|
303
|
+
const updatedUser = { ...user, ...userData };
|
|
304
|
+
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
305
|
+
setUser(updatedUser);
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error('Failed to update user data:', error);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// Update user onboarded status
|
|
312
|
+
const updateOnboardedStatus = async (): Promise<void> => {
|
|
313
|
+
try {
|
|
314
|
+
setIsLoading(true);
|
|
315
|
+
|
|
316
|
+
// Call the API to update onboarded status
|
|
317
|
+
await updateUserOnboardedStatus();
|
|
318
|
+
|
|
319
|
+
// Update local user data
|
|
320
|
+
if (user) {
|
|
321
|
+
const updatedUser = { ...user, onboarded: true };
|
|
322
|
+
await AsyncStorage.setItem('user', JSON.stringify(updatedUser));
|
|
323
|
+
setUser(updatedUser);
|
|
324
|
+
}
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error('Failed to update onboarded status:', error);
|
|
327
|
+
throw error;
|
|
328
|
+
} finally {
|
|
329
|
+
setIsLoading(false);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const deleteAccount = async () => {
|
|
334
|
+
try {
|
|
335
|
+
// In a real app, you would make an API call to delete the user account on the server
|
|
336
|
+
// For example: await api.deleteUser(user.id);
|
|
337
|
+
|
|
338
|
+
// Remove user data from AsyncStorage
|
|
339
|
+
await AsyncStorage.removeItem('user');
|
|
340
|
+
|
|
341
|
+
// Remove JWT token
|
|
342
|
+
await removeAuthToken();
|
|
343
|
+
|
|
344
|
+
// Clear any other user-related data from AsyncStorage
|
|
345
|
+
await AsyncStorage.removeItem('onboardingCompleted');
|
|
346
|
+
|
|
347
|
+
// Update state
|
|
348
|
+
setUser(null);
|
|
349
|
+
setIsAuthenticated(false);
|
|
350
|
+
setHasCompletedOnboarding(false);
|
|
351
|
+
|
|
352
|
+
console.log('Account deleted successfully');
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error('Failed to delete account:', error);
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<AuthContext.Provider value={{
|
|
361
|
+
user,
|
|
362
|
+
isLoading,
|
|
363
|
+
hasCompletedOnboarding,
|
|
364
|
+
login,
|
|
365
|
+
logout,
|
|
366
|
+
deleteAccount,
|
|
367
|
+
completeOnboarding,
|
|
368
|
+
updateUser,
|
|
369
|
+
appleSignIn,
|
|
370
|
+
onairosSignIn,
|
|
371
|
+
isAuthenticated,
|
|
372
|
+
updateOnboardedStatus,
|
|
373
|
+
// Progress tracking methods
|
|
374
|
+
getResumeTarget,
|
|
375
|
+
markStepCompleted,
|
|
376
|
+
updateLastScreen,
|
|
377
|
+
isReturningUser,
|
|
378
|
+
// Event access token methods
|
|
379
|
+
markEventPageReached,
|
|
380
|
+
hasEventAccessToken
|
|
381
|
+
}}>
|
|
382
|
+
{children}
|
|
383
|
+
</AuthContext.Provider>
|
|
384
|
+
);
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
export const useAuth = (): AuthContextType => {
|
|
388
|
+
const context = useContext(AuthContext);
|
|
389
|
+
if (context === undefined) {
|
|
390
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
391
|
+
}
|
|
392
|
+
return context;
|
|
393
|
+
};
|