import ErrorModal from "@components/modals/ErrorModal"; import { LOG } from "@logger"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { useMutation } from "@tanstack/react-query"; import * as SplashScreen from "expo-splash-screen"; import { createContext, useCallback, useContext, useState } from "react"; // import { type NavigationProp, useNavigation } from "@react-navigation/native"; import authenticateUser, { parseAuthicationErrors } from "@/utils/requests/authenticateUser"; import type { IuserInformations } from "@/utils/requests/types"; import getUserInformations, { parseUserInformationsErrors, } from "@/utils/requests/userInformations"; import { useModalsManagerContext } from "./ModalsManagerContext"; import type { IauthenticationData } from "./Types"; const log = LOG.extend("UserAuthenticationContext"); SplashScreen.preventAutoHideAsync(); 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 { showModal } = useModalsManagerContext(); // const navigation = useNavigation>(); // Mutations const authenticationMutation = useMutation({ mutationFn: authenticateUser, onMutate: () => { setIsAuthenticating(true); setError(""); }, onSuccess: (data) => { setAuthenticationData(data); log.info("Receive data from authenticateUser, running getUserInformations..."); userInformationsMutation.mutate(data.access); }, onError: (error: unknown) => { const errorString = parseAuthicationErrors(error); showModal(); }, onSettled: () => { setIsAuthenticating(false); }, }); const clearStorages = useCallback(async () => { try { await AsyncStorage.clear(); } catch (error) { log.error("clearStorages |", JSON.stringify(error, null, 2)); // saving 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); const errorString = parseUserInformationsErrors(error); showModal(); clearStorages(); }, }); // 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(); })(); }, [clearStorages]); // Storages const storeAuthenticationData = async (authenticationData: IauthenticationData) => { try { await AsyncStorage.setItem("authenticationData", JSON.stringify(authenticationData)); } catch (error) { log.error("storeAuthenticationData |", JSON.stringify(error, null, 2)); // saving error } }; const storeUserInformations = async (userInformations: IuserInformations) => { try { await AsyncStorage.setItem("userInformations", JSON.stringify(userInformations)); } catch (error) { log.error("storeUserInformations |", JSON.stringify(error, null, 2)); // 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 { // // await loadAssetsAsync(); // await cacheAssetsAsync({ // images: [ // "../assets/background_default.png", // "../assets/beasy_default.png", // "../assets/beasy_background.png", // "../assets/background_content_white2.png", // "../../assets/background.png", // ], // }); // const authenticationData = await loadAuthenticationData(); // const userInformations = await loadUserInformations(); // if (authenticationData && userInformations) { // setAuthenticationData(authenticationData); // setUserInformations(userInformations); // setIsAuthenticated(true); // } // } catch (error) { // log.error( // "UserAuthenticationContext | App Startup | error during retrieval of stored data |", // JSON.stringify(error, null, 2), // ); // } finally { // setTimeout(async () => await SplashScreen.hideAsync(), 500); // } // })(); // }, []); return ( {children} ); }; export const useUserAuthenticationContext = () => { return useContext(UserAuthenticationContext); };