import { createContext, ReactNode, useEffect, useReducer } from 'react'; // utils import axios from '../utils/axios'; import { setSession, getSession } from '../utils/token'; // @types import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth'; // ---------------------------------------------------------------------- enum Types { Initial = 'INITIALIZE', Login = 'LOGIN', ValidateOtp = 'VALIDATE-OTP', Logout = 'LOGOUT', } type JWTAuthPayload = { [Types.Initial]: { isAuthenticated: boolean; user: AuthUser; }; [Types.Login]: undefined; [Types.ValidateOtp]: { user: AuthUser; }; [Types.Logout]: undefined; }; export type JWTActions = ActionMap[keyof ActionMap]; const initialState: AuthState = { isAuthenticated: false, isInitialized: false, user: null, }; const JWTReducer = (state: AuthState, action: JWTActions) => { switch (action.type) { case 'INITIALIZE': return { isAuthenticated: action.payload.isAuthenticated, isInitialized: true, user: action.payload.user, }; case 'LOGIN': return { ...state, isAuthenticated: false, user: null, }; case 'VALIDATE-OTP': return { ...state, isAuthenticated: true, user: action.payload.user, }; case 'LOGOUT': return { ...state, isAuthenticated: false, user: null, }; default: return state; } }; const AuthContext = createContext(null); // ---------------------------------------------------------------------- type AuthProviderProps = { children: ReactNode; }; function AuthProvider({ children }: AuthProviderProps) { const [state, dispatch] = useReducer(JWTReducer, initialState); const accessToken = getSession(); useEffect(() => { (async () => { try { // const accessToken = getSession(); if (accessToken) { setSession(accessToken); const response = await axios.get('/user'); const user = response.data; dispatch({ type: Types.Initial, payload: { isAuthenticated: true, user, }, }); } else { dispatch({ type: Types.Initial, payload: { isAuthenticated: false, user: null, }, }); } } catch (err) { dispatch({ type: Types.Initial, payload: { isAuthenticated: false, user: null, }, }); } })(); }, [accessToken]); const login = async (phoneOrEmail: string) => axios .post('/login', { phoneOrEmail }) .then(() => { dispatch({ type: Types.Login, }); }) .catch((error) => { if (error.response.status !== 404) throw error.response; if (error.response.status !== 422) throw error.response; }); const validateOtp = async (phoneOrEmail: string, otp: string) => axios .post('/verify-code', { phoneOrEmail: phoneOrEmail, otp }) .then((response) => { const { token } = response.data.data; setSession(token); return response.data; }) .catch((error) => { if (error.response.status !== 404) throw error.response; if (error.response.status !== 422) throw error.response; }); const logout = () => { setSession(null); dispatch({ type: Types.Logout }); }; return ( {children} ); // if (state.isInitialized) { // return (!state.isAuthenticated && location.pathname !== '/auth/login') ? // () // : false && location.pathname == '/auth/login' ? // () // : ( // // {children} // // ); // } else { // return () // } } export { AuthContext, AuthProvider };