import { createContext, ReactNode, useEffect, useReducer } from 'react'; // utils import axios from '../utils/axios'; import { setSession, getSession, setUser, getUser, getCookie } from '../utils/token'; // @types import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth'; // ---------------------------------------------------------------------- import { Navigate, useLocation } from 'react-router-dom'; enum Types { Initial = 'INITIALIZE', Login = 'LOGIN', ValidateOtp = 'VALIDATE-OTP', Logout = 'LOGOUT', } type JWTAuthPayload = { [Types.Initial]: { isAuthenticated: boolean; user: AuthUser; }; [Types.Login]: { user: AuthUser; }; [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: true, user: action.payload.user, }; 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); let location = useLocation(); 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]); 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 headers = { headers: { 'Accept': 'application/json', 'Content-Type' : 'application/json', 'Accept-Language': localStorage.getItem('currentLocale') ?? 'id-ID', }, }; const login = async (phoneOrEmail: string, password: string, remember:boolean) => axios .post('/login', { phoneOrEmail, password }, headers) .then((response) => { const { user, token } = response.data.data; setSession(token); setUser(user); dispatch({ type: Types.Login, payload: { user, } }); }) .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 };