ignitegym/src/contexts/AuthContext.tsx

123 lines
3.1 KiB
TypeScript

import { createContext, useEffect, useState } from 'react';
import { UserDTO } from '@dtos/UserDTO';
import { api } from '@services/api';
import { storageUserGet, storageUserRemove, storageUserSave } from '@storage/storageUser';
import {
storageAuthTokenGet,
storageAuthTokenRemove,
storageAuthTokenSave,
} from '@storage/storageAuthToken';
type AuthContextData = {
user: UserDTO;
signIn: (email: string, password: string) => Promise<void>;
signOut: () => Promise<void>;
updateUserData: (userData: UserDTO) => Promise<void>;
isLoadingUserStorageData: boolean;
};
type AuthContextProviderProps = {
children: React.ReactNode;
};
export const AuthContext = createContext<AuthContextData>({} as AuthContextData);
export function AuthContextProvider({ children }: AuthContextProviderProps) {
const [user, setUser] = useState<UserDTO>({} as UserDTO);
const [isLoadingUserStorageData, setIsLoadingUserStorageData] = useState(true);
async function updateUserAndTokenData(userData: UserDTO, token: string) {
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
setUser(userData);
}
async function saveUserAndTokenStorageData(
userData: UserDTO,
token: string,
refresh_token: string,
) {
try {
setIsLoadingUserStorageData(true);
await storageUserSave(userData);
await storageAuthTokenSave({ token, refresh_token });
} catch (error) {
throw error;
} finally {
setIsLoadingUserStorageData(false);
}
}
async function signIn(email: string, password: string) {
try {
const { data } = await api.post('/sessions', { email, password });
if (data.user && data.token && data.refresh_token) {
saveUserAndTokenStorageData(data.user, data.token, data.refresh_token);
updateUserAndTokenData(data.user, data.token);
}
} catch (error) {
console.error(error);
throw error;
}
}
async function signOut() {
try {
setIsLoadingUserStorageData(true);
setUser({} as UserDTO);
await storageUserRemove();
await storageAuthTokenRemove();
} catch (error) {
console.error(error);
throw error;
} finally {
setIsLoadingUserStorageData(false);
}
}
async function updateUserData(userData: UserDTO) {
try {
setUser(userData);
await storageUserSave(userData);
} catch (error) {
throw error;
}
}
async function loadUserData() {
try {
setIsLoadingUserStorageData(true);
const loggedUser = await storageUserGet();
const { token } = await storageAuthTokenGet();
if (loggedUser && token) {
updateUserAndTokenData(loggedUser, token);
}
} catch (error) {
throw error;
} finally {
setIsLoadingUserStorageData(false);
}
}
useEffect(() => {
loadUserData();
}, []);
useEffect(() => {
const subscription = api.registerInterceptTokenManager(signOut);
return () => {
subscription();
};
}, []);
return (
<AuthContext.Provider
value={{ user, signIn, signOut, updateUserData, isLoadingUserStorageData }}>
{children}
</AuthContext.Provider>
);
}