@phygitallabs/tapquest-core 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -0
- package/index.ts +1 -0
- package/package.json +43 -0
- package/src/constants/firebase.ts +36 -0
- package/src/constants/service.ts +30 -0
- package/src/helper/helpers.ts +3 -0
- package/src/helper/index.ts +1 -0
- package/src/index.ts +25 -0
- package/src/modules/achievement/helpers/index.ts +98 -0
- package/src/modules/achievement/hooks/index.ts +171 -0
- package/src/modules/achievement/index.ts +5 -0
- package/src/modules/achievement/types/index.ts +45 -0
- package/src/modules/achivementWithReward/hooks/achivementPlusRewardModel.ts +83 -0
- package/src/modules/achivementWithReward/hooks/index.ts +5 -0
- package/src/modules/achivementWithReward/index.ts +5 -0
- package/src/modules/auth/README.md +527 -0
- package/src/modules/auth/constants/index.ts +9 -0
- package/src/modules/auth/helpers/index.ts +161 -0
- package/src/modules/auth/helpers/refreshToken.ts +63 -0
- package/src/modules/auth/index.ts +20 -0
- package/src/modules/auth/providers/AuthProvider.tsx +207 -0
- package/src/modules/auth/providers/index.ts +1 -0
- package/src/modules/auth/services/FirebaseAuthService.ts +290 -0
- package/src/modules/auth/services/authServiceFactory.ts +22 -0
- package/src/modules/auth/services/index.ts +3 -0
- package/src/modules/auth/store/authSlice.ts +137 -0
- package/src/modules/auth/types/index.ts +109 -0
- package/src/modules/campaign/hooks/index.ts +6 -0
- package/src/modules/campaign/hooks/useCampaignService.ts +7 -0
- package/src/modules/campaign/index.tsx +7 -0
- package/src/modules/campaign/types/campaign.ts +51 -0
- package/src/modules/campaign/types/enums.ts +4 -0
- package/src/modules/campaign/types/index.ts +4 -0
- package/src/modules/campaign/types/requests.ts +46 -0
- package/src/modules/data-tracking/hooks/index.ts +67 -0
- package/src/modules/data-tracking/index.ts +1 -0
- package/src/modules/generate-certificate/hooks/index.ts +8 -0
- package/src/modules/generate-certificate/index.ts +3 -0
- package/src/modules/generate-certificate/types/generateCertificate.ts +7 -0
- package/src/modules/generate-certificate/types/index.ts +7 -0
- package/src/modules/location/hooks/index.ts +8 -0
- package/src/modules/location/hooks/useLocationService.ts +8 -0
- package/src/modules/location/index.tsx +11 -0
- package/src/modules/location/types/index.ts +18 -0
- package/src/modules/location/types/locationModel.ts +21 -0
- package/src/modules/location/utils/index.ts +5 -0
- package/src/modules/location/utils/locationHelpers.ts +13 -0
- package/src/modules/memory/hooks/index.ts +3 -0
- package/src/modules/memory/index.ts +3 -0
- package/src/modules/memory/types/index.ts +3 -0
- package/src/modules/notification/index.ts +2 -0
- package/src/modules/notification/providers/index.tsx +50 -0
- package/src/modules/notification/types/index.ts +3 -0
- package/src/modules/reward/hooks/index.ts +14 -0
- package/src/modules/reward/hooks/useRewardService.ts +14 -0
- package/src/modules/reward/index.tsx +16 -0
- package/src/modules/reward/types/enums.ts +13 -0
- package/src/modules/reward/types/index.ts +4 -0
- package/src/modules/reward/types/requests.ts +281 -0
- package/src/modules/reward/types/reward.ts +90 -0
- package/src/modules/scan-chip/hooks/index.tsx +67 -0
- package/src/modules/scan-chip/index.ts +2 -0
- package/src/modules/scan-chip/types/index.ts +25 -0
- package/src/modules/send-email/hooks/index.ts +2 -0
- package/src/modules/send-email/index.ts +1 -0
- package/src/modules/user-profile/hooks/index.ts +3 -0
- package/src/modules/user-profile/index.ts +3 -0
- package/src/modules/user-profile/types/index.ts +3 -0
- package/src/providers/ServicesProvider.tsx +173 -0
- package/src/providers/TapquestCoreProvider.tsx +64 -0
- package/src/providers/index.ts +1 -0
- package/src/store/hooks.ts +6 -0
- package/src/store/index.ts +45 -0
- package/src/types/common.d.ts +8 -0
- package/src/types/media.ts +26 -0
- package/src/types/service.d.ts +34 -0
- package/tsconfig.json +28 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deviceUIDKey,
|
|
3
|
+
chipAuthTokenKey,
|
|
4
|
+
retryAttemptsRefreshToken,
|
|
5
|
+
accessTokenKey,
|
|
6
|
+
refreshTokenKey,
|
|
7
|
+
userInfoKey,
|
|
8
|
+
} from "../constants";
|
|
9
|
+
|
|
10
|
+
import { v4 as uuidv4 } from "uuid";
|
|
11
|
+
|
|
12
|
+
export const generateDeviceId = async (): Promise<string> => {
|
|
13
|
+
try {
|
|
14
|
+
const deviceFingerprint = await generateDeviceFingerprint();
|
|
15
|
+
return deviceFingerprint;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error("Error generating device fingerprint:", error);
|
|
18
|
+
return uuidv4();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const generateDeviceFingerprint = async (): Promise<string> => {
|
|
23
|
+
const timestamp = new Date().toISOString(); // UTC timestamp
|
|
24
|
+
|
|
25
|
+
const fingerprintRaw = [
|
|
26
|
+
navigator.userAgent,
|
|
27
|
+
navigator.language,
|
|
28
|
+
screen.width,
|
|
29
|
+
screen.height,
|
|
30
|
+
screen.colorDepth,
|
|
31
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
32
|
+
navigator.platform,
|
|
33
|
+
navigator.hardwareConcurrency,
|
|
34
|
+
timestamp, // Include timestamp
|
|
35
|
+
].join("::");
|
|
36
|
+
|
|
37
|
+
const encoder = new TextEncoder();
|
|
38
|
+
const data = encoder.encode(fingerprintRaw);
|
|
39
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
40
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
41
|
+
const fingerprint = hashArray
|
|
42
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
43
|
+
.join("");
|
|
44
|
+
return fingerprint;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default generateDeviceFingerprint;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export const getDeviceUid = () => {
|
|
51
|
+
if (typeof window === "undefined") return null;
|
|
52
|
+
return localStorage.getItem(deviceUIDKey);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const setDeviceUid = (deviceId: string) => {
|
|
56
|
+
if (typeof window === "undefined") return;
|
|
57
|
+
localStorage.setItem(deviceUIDKey, deviceId);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const removeDeviceUid = () => {
|
|
61
|
+
if (typeof window === "undefined") return;
|
|
62
|
+
localStorage.removeItem(deviceUIDKey);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const checkDeviceUid = async (): Promise<string> => {
|
|
66
|
+
// if (typeof window === "undefined") return null;
|
|
67
|
+
|
|
68
|
+
let deviceUID = getDeviceUid();
|
|
69
|
+
|
|
70
|
+
if (!deviceUID) {
|
|
71
|
+
deviceUID = await generateDeviceId();
|
|
72
|
+
setDeviceUid(deviceUID);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return deviceUID;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// CHIP AUTH TOKEN
|
|
79
|
+
export const getChipAuthToken = () => {
|
|
80
|
+
if (typeof window === "undefined") return null;
|
|
81
|
+
return localStorage.getItem(chipAuthTokenKey);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const setChipAuthToken = (value: string) => {
|
|
85
|
+
if (typeof window === "undefined") return;
|
|
86
|
+
localStorage.setItem(chipAuthTokenKey, value);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const removeChipAuthToken = () => {
|
|
90
|
+
if (typeof window === "undefined") return;
|
|
91
|
+
localStorage.removeItem(chipAuthTokenKey);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// RETRY ATTEMPTS
|
|
95
|
+
export const getRetryAttemptsRefreshToken = () => {
|
|
96
|
+
if (typeof window === "undefined") return null;
|
|
97
|
+
return localStorage.getItem(retryAttemptsRefreshToken);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const setRetryAttemptsRefreshToken = (value: string) => {
|
|
101
|
+
if (typeof window === "undefined") return;
|
|
102
|
+
localStorage.setItem(retryAttemptsRefreshToken, value);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// ACCESS TOKEN
|
|
106
|
+
export const getAccessToken = () => {
|
|
107
|
+
if (typeof window === "undefined") return null;
|
|
108
|
+
return localStorage.getItem(accessTokenKey);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const setAccessToken = (value: string) => {
|
|
112
|
+
if (typeof window === "undefined") return;
|
|
113
|
+
localStorage.setItem(accessTokenKey, value);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const removeAccessToken = () => {
|
|
117
|
+
if (typeof window === "undefined") return;
|
|
118
|
+
localStorage.removeItem(accessTokenKey);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// REFRESH TOKEN
|
|
122
|
+
export const getRefreshToken = () => {
|
|
123
|
+
if (typeof window === "undefined") return null;
|
|
124
|
+
return localStorage.getItem(refreshTokenKey);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const setRefreshToken = (value: string) => {
|
|
128
|
+
if (typeof window === "undefined") return;
|
|
129
|
+
localStorage.setItem(refreshTokenKey, value);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const removeRefreshToken = () => {
|
|
133
|
+
if (typeof window === "undefined") return;
|
|
134
|
+
localStorage.removeItem(refreshTokenKey);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// USER INFO
|
|
138
|
+
export const getUserInfo = () => {
|
|
139
|
+
if (typeof window === "undefined") return null;
|
|
140
|
+
const userInfo = localStorage.getItem(userInfoKey);
|
|
141
|
+
if (!userInfo) return null;
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(userInfo);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("Failed to parse stored user data:", error);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const setUserInfo = (userData: any) => {
|
|
151
|
+
if (typeof window === "undefined") return;
|
|
152
|
+
localStorage.setItem(userInfoKey, JSON.stringify(userData));
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const removeUserInfo = () => {
|
|
156
|
+
if (typeof window === "undefined") return;
|
|
157
|
+
localStorage.removeItem(userInfoKey);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export { createRefreshTokenFunction } from "./refreshToken";
|
|
161
|
+
export type { RefreshTokenConfig } from "./refreshToken";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import mem from "mem";
|
|
2
|
+
import { setUserInfo, removeUserInfo, getUserInfo, getRefreshToken } from "./index";
|
|
3
|
+
|
|
4
|
+
// Internal configuration - managed by tapquest-core
|
|
5
|
+
const REFRESH_TOKEN_CONFIG = {
|
|
6
|
+
maxAge: 10000, // 10 seconds cache
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export interface RefreshTokenConfig {
|
|
10
|
+
firebaseApiKey: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const createRefreshTokenFunction = (config: RefreshTokenConfig) => {
|
|
14
|
+
const refreshTokenFn = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const session = getUserInfo();
|
|
17
|
+
const refreshToken = getRefreshToken();
|
|
18
|
+
|
|
19
|
+
if (!refreshToken) {
|
|
20
|
+
removeUserInfo();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const params = new URLSearchParams();
|
|
25
|
+
params.append("grant_type", "refresh_token");
|
|
26
|
+
params.append("refresh_token", refreshToken);
|
|
27
|
+
|
|
28
|
+
const fetchData = {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: new Headers({
|
|
31
|
+
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
32
|
+
}),
|
|
33
|
+
body: params,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const response = await fetch(
|
|
37
|
+
`https://securetoken.googleapis.com/v1/token?key=${config.firebaseApiKey}`,
|
|
38
|
+
fetchData
|
|
39
|
+
);
|
|
40
|
+
const data = await response.json();
|
|
41
|
+
|
|
42
|
+
if (data.error) {
|
|
43
|
+
removeUserInfo();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const newSession = {
|
|
48
|
+
...session,
|
|
49
|
+
accessToken: data.access_token,
|
|
50
|
+
refreshToken: data.refresh_token,
|
|
51
|
+
};
|
|
52
|
+
setUserInfo(newSession);
|
|
53
|
+
|
|
54
|
+
return newSession;
|
|
55
|
+
} catch {
|
|
56
|
+
removeUserInfo();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return mem(refreshTokenFn, { maxAge: REFRESH_TOKEN_CONFIG.maxAge });
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export { createRefreshTokenFunction };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Export types
|
|
2
|
+
export type {
|
|
3
|
+
UserData,
|
|
4
|
+
UserRole,
|
|
5
|
+
SignInProvider,
|
|
6
|
+
AuthResponse,
|
|
7
|
+
AuthService,
|
|
8
|
+
FirebaseConfig,
|
|
9
|
+
UseAuthReturn,
|
|
10
|
+
AuthProviderProps,
|
|
11
|
+
AuthCallbacks,
|
|
12
|
+
} from './types';
|
|
13
|
+
|
|
14
|
+
// Export hooks and providers
|
|
15
|
+
// export { useAuth } from './hooks';
|
|
16
|
+
export { useAuth, AuthProvider } from './providers';
|
|
17
|
+
|
|
18
|
+
// Export constants and helpers
|
|
19
|
+
export * from './constants';
|
|
20
|
+
export * from './helpers';
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { createContext, useEffect, ReactNode, useContext } from 'react';
|
|
2
|
+
import { AuthService, AuthCallbacks } from '../types';
|
|
3
|
+
|
|
4
|
+
import { useAppSelector, useAppDispatch } from '../../../store/hooks';
|
|
5
|
+
import {
|
|
6
|
+
selectUser,
|
|
7
|
+
selectIsSignedIn,
|
|
8
|
+
selectIsLoading,
|
|
9
|
+
signIn as signInAction,
|
|
10
|
+
signOut as signOutAction,
|
|
11
|
+
updateScanStatus as updateScanStatusAction,
|
|
12
|
+
refreshUser as refreshUserAction,
|
|
13
|
+
setPending,
|
|
14
|
+
initializeFromStorage,
|
|
15
|
+
} from '../store/authSlice';
|
|
16
|
+
|
|
17
|
+
import { AuthResponse, UserData } from '../types';
|
|
18
|
+
|
|
19
|
+
export interface AuthContextType {
|
|
20
|
+
authService: AuthService;
|
|
21
|
+
authCallbacks?: AuthCallbacks;
|
|
22
|
+
// User state
|
|
23
|
+
user: UserData;
|
|
24
|
+
isSignedIn: boolean;
|
|
25
|
+
isLoading: boolean;
|
|
26
|
+
|
|
27
|
+
// Auth actions
|
|
28
|
+
signInWithCredential: (email: string, password: string) => Promise<AuthResponse>;
|
|
29
|
+
signInWithGoogle: () => Promise<AuthResponse | null>;
|
|
30
|
+
signUp: (email: string, password: string) => Promise<AuthResponse>;
|
|
31
|
+
signOut: () => Promise<void>;
|
|
32
|
+
|
|
33
|
+
// Password actions
|
|
34
|
+
forgotPassword: (email: string) => Promise<void>;
|
|
35
|
+
sendEmailVerification: () => Promise<void>;
|
|
36
|
+
changePassword: (newPassword: string) => Promise<void>;
|
|
37
|
+
|
|
38
|
+
// User management
|
|
39
|
+
updateScanStatus: (status: boolean) => void;
|
|
40
|
+
refreshUser: (userData: UserData) => void;
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const AuthContext = createContext<AuthContextType | null>(null);
|
|
45
|
+
|
|
46
|
+
export interface AuthProviderProps {
|
|
47
|
+
children: ReactNode;
|
|
48
|
+
authService: AuthService;
|
|
49
|
+
authCallbacks?: AuthCallbacks;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function AuthProvider({ children, authService, authCallbacks }: AuthProviderProps) {
|
|
53
|
+
const dispatch = useAppDispatch();
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
// Initialize auth state from localStorage
|
|
57
|
+
dispatch(initializeFromStorage());
|
|
58
|
+
|
|
59
|
+
// Set up auth state listener
|
|
60
|
+
const unsubscribe = authService.onAuthStateChanged((user) => {
|
|
61
|
+
if (user) {
|
|
62
|
+
dispatch(signInAction(user));
|
|
63
|
+
|
|
64
|
+
// Use auth callback for user identification
|
|
65
|
+
if (authCallbacks?.onUserIdentify && user.email) {
|
|
66
|
+
authCallbacks.onUserIdentify({
|
|
67
|
+
email: user.email,
|
|
68
|
+
name: user.displayName,
|
|
69
|
+
avatar: user.avatar,
|
|
70
|
+
uid: user.uid,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Notify about successful sign in
|
|
75
|
+
if (authCallbacks?.onSignInSuccess) {
|
|
76
|
+
authCallbacks.onSignInSuccess(user);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
dispatch(signOutAction());
|
|
80
|
+
|
|
81
|
+
// Use auth callback for reset
|
|
82
|
+
if (authCallbacks?.onTrackingReset) {
|
|
83
|
+
authCallbacks.onTrackingReset();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
dispatch(setPending(false));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return () => {
|
|
90
|
+
unsubscribe();
|
|
91
|
+
};
|
|
92
|
+
}, [authService, dispatch, authCallbacks]);
|
|
93
|
+
|
|
94
|
+
// Redux selectors
|
|
95
|
+
const user = useAppSelector(selectUser);
|
|
96
|
+
const isSignedIn = useAppSelector(selectIsSignedIn);
|
|
97
|
+
const isLoading = useAppSelector(selectIsLoading);
|
|
98
|
+
|
|
99
|
+
// Auth actions with auth callbacks
|
|
100
|
+
const signInWithCredential = async (email: string, password: string): Promise<AuthResponse> => {
|
|
101
|
+
const result = await authService.signInWithEmailAndPassword(email, password);
|
|
102
|
+
|
|
103
|
+
if (result.data && authCallbacks?.onSignInSuccess) {
|
|
104
|
+
authCallbacks.onSignInSuccess(result.data);
|
|
105
|
+
} else if (result.errorCode && authCallbacks?.onSignInError) {
|
|
106
|
+
authCallbacks.onSignInError(result.errorCode);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return result;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const signInWithGoogle = async (): Promise<AuthResponse | null> => {
|
|
113
|
+
const result = await authService.signInWithGoogle();
|
|
114
|
+
|
|
115
|
+
if (result.data && authCallbacks?.onSignInSuccess) {
|
|
116
|
+
authCallbacks.onSignInSuccess(result.data);
|
|
117
|
+
return result;
|
|
118
|
+
|
|
119
|
+
} else if (result.errorCode && authCallbacks?.onSignInError) {
|
|
120
|
+
authCallbacks.onSignInError(result.errorCode);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const signUp = async (email: string, password: string): Promise<AuthResponse> => {
|
|
127
|
+
const result = await authService.signUp(email, password);
|
|
128
|
+
|
|
129
|
+
if (result.data && authCallbacks?.onSignUpSuccess) {
|
|
130
|
+
authCallbacks.onSignUpSuccess(result.data);
|
|
131
|
+
} else if (result.errorCode && authCallbacks?.onSignUpError) {
|
|
132
|
+
authCallbacks.onSignUpError(result.errorCode);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const signOut = async (): Promise<void> => {
|
|
139
|
+
await authService.signOut();
|
|
140
|
+
dispatch(signOutAction());
|
|
141
|
+
|
|
142
|
+
if (authCallbacks?.onSignOutSuccess) {
|
|
143
|
+
authCallbacks.onSignOutSuccess();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Password actions
|
|
148
|
+
const forgotPassword = async (email: string): Promise<void> => {
|
|
149
|
+
return await authService.sendPasswordResetEmail(email);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const sendEmailVerification = async (): Promise<void> => {
|
|
153
|
+
return await authService.sendEmailVerification();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const changePassword = async (newPassword: string): Promise<void> => {
|
|
157
|
+
return await authService.changePassword(newPassword);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// User management
|
|
161
|
+
const updateScanStatus = (status: boolean): void => {
|
|
162
|
+
dispatch(updateScanStatusAction(status));
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const refreshUser = (userData: UserData): void => {
|
|
166
|
+
dispatch(refreshUserAction(userData));
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const contextValue: AuthContextType = {
|
|
170
|
+
authService,
|
|
171
|
+
authCallbacks,
|
|
172
|
+
// User state
|
|
173
|
+
user,
|
|
174
|
+
isSignedIn,
|
|
175
|
+
isLoading,
|
|
176
|
+
|
|
177
|
+
// Auth actions
|
|
178
|
+
signInWithCredential,
|
|
179
|
+
signInWithGoogle,
|
|
180
|
+
signUp,
|
|
181
|
+
signOut,
|
|
182
|
+
|
|
183
|
+
// Password actions
|
|
184
|
+
forgotPassword,
|
|
185
|
+
sendEmailVerification,
|
|
186
|
+
changePassword,
|
|
187
|
+
|
|
188
|
+
// User management
|
|
189
|
+
updateScanStatus,
|
|
190
|
+
refreshUser,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<AuthContext.Provider value={contextValue}>
|
|
195
|
+
{children}
|
|
196
|
+
</AuthContext.Provider>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export const useAuth = () => {
|
|
201
|
+
const authContext = useContext(AuthContext);
|
|
202
|
+
if (!authContext) {
|
|
203
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return authContext;
|
|
207
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AuthProvider';
|