AuthProvider.tsx 3.7 KB

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