Files
aso/frontend/client-portal/src/contexts/LaravelAuthContext.tsx
2023-07-03 11:39:08 +07:00

189 lines
4.4 KiB
TypeScript

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<JWTAuthPayload>[keyof ActionMap<JWTAuthPayload>];
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<JWTContextType | null>(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 (
<AuthContext.Provider
value={{
...state,
method: 'jwt',
login,
validateOtp,
logout,
}}
>
{children}
</AuthContext.Provider>
);
// if (state.isInitialized) {
// return (!state.isAuthenticated && location.pathname !== '/auth/login') ?
// (<Navigate to="/auth/login" replace={true} />)
// : false && location.pathname == '/auth/login' ?
// (<Navigate to="/dashboard" replace={true} />)
// : (
// <AuthContext.Provider
// value={{
// ...state,
// method: 'jwt',
// login,
// logout,
// register,
// }}
// >
// {children}
// </AuthContext.Provider>
// );
// } else {
// return (<Navigate to="/auth/login" replace={true} />)
// }
}
export { AuthContext, AuthProvider };