import type { IuserInformations } from "@/utils/requests/Types"; import authenticateUser from "@/utils/requests/authenticateUser"; import getUserInformations from "@/utils/requests/userInformations"; import { LOG } from "@logger"; import AsyncStorage from "@react-native-async-storage/async-storage"; // import { type NavigationProp, useNavigation } from "@react-navigation/native"; import { useMutation } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { createContext, useCallback, useContext, useEffect, useState } from "react"; import type { IauthenticationData } from "./Types"; const log = LOG.extend("UserAuthenticationContext"); export interface UserAuthenticationContextProps { isAuthenticated: boolean; setIsAuthenticated: React.Dispatch>; setAuthenticationData: React.Dispatch>; userInformations: IuserInformations; setUserInformations: React.Dispatch>; login: (email: string, password: string) => void; isAuthenticating: boolean; logout: () => void; } export const UserAuthenticationContext = createContext({ isAuthenticated: false, setIsAuthenticated: () => {}, setAuthenticationData: () => {}, userInformations: { username: "", email: "", // biome-ignore lint/style/useNamingConvention: first_name: "", // biome-ignore lint/style/useNamingConvention: last_name: "", marchand: { // biome-ignore lint/style/useNamingConvention: marchand_id: "", nom: "", code: "", adresse: "", // biome-ignore lint/style/useNamingConvention: url_succes: "", // biome-ignore lint/style/useNamingConvention: url_echec: "", entreprise: 0, user: 0, }, }, setUserInformations: () => {}, login: () => {}, isAuthenticating: false, logout: () => {}, }); export const UserAuthenticationContextProvider = ({ children }: { children: React.ReactNode }) => { // States const [isAuthenticated, setIsAuthenticated] = useState(false); const [isAuthenticating, setIsAuthenticating] = useState(false); const [authenticationData, setAuthenticationData] = useState({ access: "", refresh: "", }); const [error, setError] = useState(""); const [userInformations, setUserInformations] = useState({ username: "JohnDoe", email: "JohnDoe@example.com", // biome-ignore lint/style/useNamingConvention: first_name: "John", // biome-ignore lint/style/useNamingConvention: last_name: "Doe", marchand: { // biome-ignore lint/style/useNamingConvention: marchand_id: "id123", nom: "Beasy", code: "BEASY-EXAMPLE-1", adresse: "Plateau 2, 1023, Immeuble Chardy", // biome-ignore lint/style/useNamingConvention: url_succes: "https://example.com/success", // biome-ignore lint/style/useNamingConvention: url_echec: "https://example.com/echec", entreprise: 0, user: 0, }, }); // Hoooks // const navigation = useNavigation>(); // Mutations const authenticationMutation = useMutation({ mutationFn: authenticateUser, onMutate: () => { setIsAuthenticating(true); setError(""); }, onSuccess: (data) => { setAuthenticationData(data); // navigation.popToTop(); // navigation.replace("bottomTabs"); // navigation.navigate("bottomTabs"); log.info("Receive data from authenticateUser, running getUserInformations..."); userInformationsMutation.mutate(data.access); // console.log("user informations", userInformations); }, // biome-ignore lint/suspicious/noExplicitAny: onError: (error: AxiosError) => { log.error("authenticationMutation", error); if (error.response) { log.error("error :: ", error.response.data); if (error.response.status === 400) { return setError("Bad request"); } const message: string = error.response.data.detail; return setError(message); } setError("Unknown error"); }, }); const userInformationsMutation = useMutation({ mutationFn: (userAccessToken: string) => getUserInformations(userAccessToken), onMutate: () => { setIsAuthenticating(true); setError(""); }, onSettled: () => { setIsAuthenticating(false); }, onSuccess: (userInformations) => { log.info("getUserInformations request was a success, navigating to homepage"); setUserInformations(userInformations); setIsAuthenticated(true); storeAuthenticationData(authenticationData); storeUserInformations(userInformations); // navigation.navigate("appBottomTabsNavigator"); }, onError: (error) => { log.error("userInformationsMutation", error); }, }); // Methods const login = useCallback( (email: string, password: string) => { authenticationMutation.mutate({ username: email, password: password, }); }, [authenticationMutation], ); const logout = useCallback(() => { (async () => { setIsAuthenticated(false); setAuthenticationData({ access: "", refresh: "", }); setUserInformations({ username: "", email: "", // biome-ignore lint/style/useNamingConvention: first_name: "", // biome-ignore lint/style/useNamingConvention: last_name: "", marchand: { // biome-ignore lint/style/useNamingConvention: marchand_id: "", nom: "", code: "", adresse: "", // biome-ignore lint/style/useNamingConvention: url_succes: "", // biome-ignore lint/style/useNamingConvention: url_echec: "", entreprise: 0, user: 0, }, }); await clearStorages(); })(); }, []); // Storages const storeAuthenticationData = async (authenticationData: IauthenticationData) => { try { await AsyncStorage.setItem("authenticationData", JSON.stringify(authenticationData)); } catch (e) { log.error("storeAuthenticationData |", e); // saving error } }; const storeUserInformations = async (userInformations: IuserInformations) => { try { await AsyncStorage.setItem("userInformations", JSON.stringify(userInformations)); } catch (e) { log.error("storeUserInformations |", e); // saving error } }; const clearStorages = async () => { try { await AsyncStorage.clear(); } catch (e) { log.error("clearStorages |", e); // saving error } }; const loadAuthenticationData = async () => { log.debug("loadAuthenticationData | Loading authentication data"); const jsonRepresentation = await AsyncStorage.getItem("authenticationData"); return jsonRepresentation ? JSON.parse(jsonRepresentation) : null; }; const loadUserInformations = async () => { log.debug("loadUserInformations | Loading user informations"); const jsonRepresentation = await AsyncStorage.getItem("userInformations"); return jsonRepresentation ? JSON.parse(jsonRepresentation) : null; }; // biome-ignore lint/correctness/useExhaustiveDependencies: useEffect(() => { log.debug("UserAuthenticationContext | App Startup | loading saved user data."); (async () => { try { const authenticationData = await loadAuthenticationData(); const userInformations = await loadUserInformations(); if (authenticationData && userInformations) { setAuthenticationData(authenticationData); setUserInformations(userInformations); setIsAuthenticated(true); // navigation.navigate("appBottomTabsNavigator"); } } catch (error) { } finally { } })(); }, []); return ( {children} ); }; export const useUserAuthenticationContext = () => { return useContext(UserAuthenticationContext); };