123 lines
3.1 KiB
TypeScript
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>
|
|
);
|
|
}
|