Add profile and login screen + first api logic draft

This commit is contained in:
2025-12-09 18:29:24 +01:00
parent abe14f4c3f
commit 49b6ecadb2
19 changed files with 1046 additions and 810 deletions

176
utils/authContext.tsx Normal file
View File

@ -0,0 +1,176 @@
import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react';
import { SplashScreen, useRouter, useSegments } from 'expo-router';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { UserData } from '@/types/types';
import * as SecureStore from 'expo-secure-store';
import api, { GATEWAY_ENDPOINT, GATEWAY_TOKEN } from './api';
import axios from 'axios';
type AuthState = {
isAuthenticated: boolean;
isReady: boolean;
user: UserData | null;
logIn: (token: string, userData: UserData) => void;
logOut: () => void;
};
SplashScreen.preventAutoHideAsync();
const KEY_TOKEN = 'auth-token';
const KEY_URL = 'App_URL';
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 storeAuthState = async (newState: { isAuthenticated: boolean }) => {
try {
const jsonValue = JSON.stringify(newState);
await AsyncStorage.setItem(KEY_TOKEN, jsonValue);
} catch (error) {
console.error('Errore nel salvataggio dello stato di autenticazione:', error);
}
}
const logIn = async (token: string, userData: UserData) => {
try {
await SecureStore.setItemAsync(KEY_TOKEN, token);
setIsAuthenticated(true);
setUser(userData);
storeAuthState({ isAuthenticated: true }); // TODO: can be removed later
router.replace('/');
} catch (error) {
console.error('Errore durante il login:', error);
}
};
const logOut = async () => {
try {
await SecureStore.deleteItemAsync(KEY_TOKEN);
setIsAuthenticated(false);
setUser(null);
storeAuthState({ isAuthenticated: false });
router.replace('/login');
} catch (error) {
console.error('Errore durante il logout:', error);
}
};
useEffect(() => {
const initApp = async () => {
try {
// 1. Gestione URL Gateway (Logica "else" del vecchio snippet)
let currentApiUrl = await SecureStore.getItemAsync(KEY_URL);
if (!currentApiUrl) {
console.log("URL non trovato, contatto Gateway...");
try {
// Chiamata diretta al gateway (senza interceptor api.ts)
const gwResponse = await axios.get(GATEWAY_ENDPOINT, {
headers: { "x-access-tokens": GATEWAY_TOKEN }
});
// Supponiamo che il backend ritorni { url: "http://..." }
// Adatta questo parsing alla risposta reale del tuo backend
const newUrl = gwResponse.data.url + "/api/app_cantieri";
await SecureStore.setItemAsync(KEY_URL, newUrl);
currentApiUrl = newUrl;
console.log("URL acquisito:", newUrl);
} catch (gwError) {
console.error("Errore connessione Gateway:", gwError);
// Qui potresti decidere di non bloccare l'app o mostrare un errore
}
}
// 2. Controllo Token e Recupero User (Logica "if" del vecchio snippet)
const savedToken = await SecureStore.getItemAsync(KEY_TOKEN);
if (savedToken && currentApiUrl) {
// Verifichiamo il token chiamando /user
// Qui usiamo l'istanza 'api' importata che ora userà l'URL e il token
const userRes = await api.get("/user");
const result = userRes.data;
const loadedUser: UserData = {
name: result.nome,
surname: result.cognome,
username: result.username,
email: result.email,
role: result.role,
id: result.id,
};
setUser(loadedUser);
setIsAuthenticated(true);
}
} catch (error) {
console.error('Errore durante l\'inizializzazione dell\'app:', error);
// Se il token è scaduto o l'API fallisce, consideriamo l'utente non loggato
await SecureStore.deleteItemAsync(KEY_TOKEN);
setIsAuthenticated(false);
setUser(null);
} finally {
setIsReady(true);
await SplashScreen.hideAsync();
}
};
// TODO: can be removed later
// const getAuthFromStorage = async () => {
// try {
// const jsonValue = await AsyncStorage.getItem(KEY_TOKEN);
// if (jsonValue != null) {
// const auth = JSON.parse(jsonValue);
// setIsAuthenticated(auth.isAuthenticated);
// }
// } catch (error) {
// console.error('Errore nel recupero dello stato di autenticazione:', error);
// }
// setIsReady(true);
// };
// getAuthFromStorage();
initApp();
}, []);
// TODO: Can be removed later
// useEffect(() => {
// if (isReady) {
// SplashScreen.hideAsync();
// }
// }, [isReady]);
// Protezione rotte (opzionale, ma consigliata qui o nel Layout)
useEffect(() => {
if (!isReady) return;
const inAuthGroup = segments[0] === '(protected)';
if (!isAuthenticated && inAuthGroup) {
router.replace('/login');
} else if (isAuthenticated && !inAuthGroup) {
// router.replace('/(protected)/home'); // Decommenta se vuoi redirect automatico da login a home
}
}, [isReady, isAuthenticated, segments]);
return (
<AuthContext.Provider value={{ isReady, isAuthenticated, user, logIn, logOut }}>
{children}
</AuthContext.Provider>
);
}