AuthProvider.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import React, { 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 axios from 'axios';
  6. import { Alert } from 'react-native';
  7. import * as SecureStore from 'expo-secure-store';
  8. 1190
  9. type User = {
  10. id: string;
  11. username: string;
  12. };
  13. type AuthProvider = {
  14. user: User | null;
  15. login: (username: string, password: string) => Promise<boolean>;
  16. logout: () => void;
  17. };
  18. function useProtectedRoute(user: User | null) {
  19. const segments = useSegments();
  20. useEffect(() => {
  21. const inAuthGroup = segments[0] === '(auth)';
  22. if (!user && inAuthGroup) {
  23. router.replace('/login');
  24. } else if (user && !inAuthGroup) {
  25. router.replace('/(auth)/(tabs)/(home)/mainPage');
  26. }
  27. }, [user, segments]);
  28. }
  29. export const AuthContext = createContext<AuthProvider>({
  30. user: null,
  31. login: async () => false,
  32. logout: () => {}
  33. });
  34. export function useAuth() {
  35. const context = useContext(AuthContext);
  36. if (!context) {
  37. throw new Error('useAuth must be used within a <AuthProvider />');
  38. }
  39. return context;
  40. }
  41. export default function AuthProvider({ children }: { children: ReactNode }) {
  42. const [user, setUser] = useState<User | null>(null);
  43. useEffect(() => {
  44. // Load user from AsyncStorage if token exists
  45. const loadUser = async () => {
  46. const token = await SecureStore.getItemAsync('accessToken');
  47. const username = await AsyncStorage.getItem('username');
  48. if (token) {
  49. // Fetch user details from API by decoding the token
  50. // For now, I am just setting a dummy user
  51. setUser({
  52. id: '1',
  53. username: username || ''
  54. });
  55. }
  56. };
  57. loadUser();
  58. }, [user]);
  59. const login = async (username: string, password: string) => {
  60. try {
  61. const apiUrl = process.env.EXPO_PUBLIC_API_URL;
  62. if (!apiUrl) {
  63. throw new Error(
  64. 'API URL is not defined in environment variables'
  65. );
  66. }
  67. const response = await axios.post(
  68. `${apiUrl}/clients/customer/sign-in`,
  69. // 'http://192.168.1.33:12000/api/v1/clients/customer/sign-in',
  70. {
  71. email: username,
  72. password: password
  73. },
  74. {
  75. headers: {
  76. 'Content-Type': 'application/json',
  77. Accept: 'application/json'
  78. }
  79. }
  80. );
  81. if (response.status === 201) {
  82. const token = response.data.accessToken;
  83. await SecureStore.setItemAsync('accessToken', token);
  84. await AsyncStorage.setItem('username', username);
  85. //-- use jwt_decode to decode the accesstoken,
  86. //-- set the user according to decoded information
  87. setUser({ id: '9999', username: username });
  88. console.log('Login successful!');
  89. return true;
  90. } else {
  91. console.error('Login failed:', response.status);
  92. Alert.alert('Error', 'Invalid username or password');
  93. return false;
  94. }
  95. } catch (error) {
  96. console.error('Login error:', error);
  97. Alert.alert(
  98. 'Error',
  99. 'Something went wrong. Please try again later.'
  100. );
  101. return false;
  102. }
  103. };
  104. const logout = async () => {
  105. await SecureStore.deleteItemAsync('accessToken');
  106. setUser(null);
  107. router.replace('/login');
  108. };
  109. useProtectedRoute(user);
  110. return (
  111. <AuthContext.Provider value={{ user, login, logout }}>
  112. {children}
  113. </AuthContext.Provider>
  114. );
  115. }