Files
mariani_mobile/utils/authContext.tsx
leonardo 7c8ef45e5a feat: Update assets and improve code comments across multiple components
- Updated favicon and various image assets.
- Enhanced comments.
- Adjusted styles and functionality in several components for improved user experience.
- Updated package-lock.json to reflect dependency updates.
2026-02-06 12:56:34 +01:00

130 lines
4.5 KiB
TypeScript

import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react';
import { SplashScreen, useRouter, useSegments } from 'expo-router';
import { UserData } from '@/types/types';
import * as SecureStore from 'expo-secure-store';
import api, { KEY_TOKEN } from './api';
type AuthState = {
isAuthenticated: boolean;
isReady: boolean;
user: UserData | null;
logIn: (token: string, userData: UserData) => void;
logOut: () => void;
};
SplashScreen.preventAutoHideAsync();
export const AuthContext = createContext<AuthState>({
isAuthenticated: false,
isReady: false,
user: null,
logIn: () => { },
logOut: () => { },
});
export const useAuth = () => useContext(AuthContext);
export function AuthProvider({ children }: PropsWithChildren) {
const [isReady, setIsReady] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [user, setUser] = useState<UserData | null>(null);
const router = useRouter();
const segments = useSegments();
const logIn = async (token: string, userData: UserData) => {
try {
await SecureStore.setItemAsync(KEY_TOKEN, token);
setIsAuthenticated(true);
setUser(userData);
router.replace('/');
} catch (error) {
console.error('Errore durante il login:', error);
}
};
const logOut = async () => {
try {
await SecureStore.deleteItemAsync(KEY_TOKEN);
setIsAuthenticated(false);
setUser(null);
router.replace('/login');
} catch (error) {
console.error('Errore durante il logout:', error);
}
};
useEffect(() => {
const initApp = async () => {
try {
// Get saved Token from SecureStore
const savedToken = await SecureStore.getItemAsync(KEY_TOKEN);
if (savedToken) {
console.log("Token trovato: ", savedToken);
// Call backend to verify token and fetch user data
// Note: api.ts already adds the Authorization header thanks to the interceptor (if configured to read from SecureStore)
// If your api.ts reads from AsyncStorage, make sure they are aligned, otherwise pass it manually here:
const response = await api.get("/user/info", {
headers: { Authorization: `Bearer ${savedToken}` }
});
const result = response.data;
const userData = result.user;
console.log("Sessione valida, dati utente caricati:", userData);
// Data mapping (Backend -> Frontend)
// The backend actionMe returns: { id, username, role }
const loadedUser: UserData = {
id: userData.id,
username: userData.username,
role: userData.role,
// Handle optional fields if the backend doesn't send them yet
name: userData.name,
surname: userData.surname || '',
email: userData.email || '',
};
setUser(loadedUser);
setIsAuthenticated(true);
} else {
console.log("Nessun token salvato.");
}
} catch (error: any) {
console.error('Errore inizializzazione (Token scaduto o Server down):', error.message);
// If the token is not valid, clear everything
await SecureStore.deleteItemAsync(KEY_TOKEN);
setIsAuthenticated(false);
setUser(null);
} finally {
setIsReady(true);
await SplashScreen.hideAsync();
}
};
initApp();
}, []);
// Route protection (optional, but recommended here or in the Layout)
useEffect(() => {
if (!isReady) return;
const inAuthGroup = segments[0] === '(protected)';
if (!isAuthenticated && inAuthGroup) {
router.replace('/login');
} else if (isAuthenticated && !inAuthGroup) {
router.replace('/');
}
}, [isReady, isAuthenticated, segments]);
return (
<AuthContext.Provider value={{ isReady, isAuthenticated, user, logIn, logOut }}>
{children}
</AuthContext.Provider>
);
}