AuthProvider.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { ReactNode, createContext, useEffect, useState } from 'react';
  2. import { useContext } from 'react';
  3. import { router, useSegments } from 'expo-router';
  4. import AsyncStorage from '@react-native-async-storage/async-storage';
  5. import * as SecureStore from 'expo-secure-store';
  6. import { AuthService } from '../service/authService';
  7. type User = {
  8. id: string;
  9. username: string;
  10. };
  11. type AuthProvider = {
  12. user: User | null;
  13. login: (username: string, password: string) => Promise<boolean>;
  14. logout: () => void;
  15. };
  16. function useProtectedRoute(user: User | null) {
  17. const segments = useSegments();
  18. useEffect(() => {
  19. const inAuthGroup = segments[0] === '(auth)';
  20. if (!user && inAuthGroup) {
  21. router.replace('/login');
  22. } else if (user && !inAuthGroup) {
  23. router.replace('/(auth)/(tabs)/(home)/mainPage');
  24. }
  25. }, [user, segments]);
  26. }
  27. export const AuthContext = createContext<AuthProvider>({
  28. user: null,
  29. login: async () => false,
  30. logout: () => {}
  31. });
  32. export function useAuth() {
  33. const context = useContext(AuthContext);
  34. if (!context) {
  35. throw new Error('useAuth must be used within a <AuthProvider />');
  36. }
  37. return context;
  38. }
  39. export default function AuthProvider({ children }: { children: ReactNode }) {
  40. const [user, setUser] = useState<User | null>(null);
  41. useEffect(() => {
  42. // Load user from AsyncStorage if token exists
  43. const loadUser = async () => {
  44. const token = await SecureStore.getItemAsync('accessToken');
  45. const username = await AsyncStorage.getItem('username');
  46. if (token) {
  47. // Fetch user details from backend API using the secret stored in the SecureStore
  48. //But back end API has not been fully developed yet.
  49. // For now, I am just setting a dummy user
  50. setUser({
  51. id: '1',
  52. username: username || ''
  53. });
  54. }
  55. };
  56. loadUser();
  57. }, [user]);
  58. const login = async (username: string, password: string) => {
  59. try {
  60. const loggedInUser = await AuthService.login(username, password);
  61. if (loggedInUser) {
  62. //Logic: if user successfully logs in, front end client will obtain a secret that can be used to call the backend API in order to access user's info.
  63. //Then those information can be set to Zustand, thereby be accessible by the front end client.
  64. //But back end API has not been fully developed yet.
  65. //So for now I set a Dummy User
  66. setUser({
  67. id: '1',
  68. username: username || ''
  69. });
  70. return true;
  71. } else {
  72. return false;
  73. }
  74. } catch (error) {
  75. console.error('Login error:', error);
  76. return false;
  77. }
  78. };
  79. const logout = async () => {
  80. try {
  81. await AuthService.logout();
  82. setUser(null);
  83. router.replace('/login');
  84. } catch (error) {
  85. console.log('error during logout', error);
  86. }
  87. };
  88. useProtectedRoute(user);
  89. return (
  90. <AuthContext.Provider value={{ user, login, logout }}>
  91. {children}
  92. </AuthContext.Provider>
  93. );
  94. }