Untitled
unknown
plain_text
2 years ago
4.6 kB
7
Indexable
'use client';
import { useEffect, useReducer, useCallback, useMemo } from 'react';
// utils
import axios, { endpoints } from 'src/utils/axios';
//
import { AuthContext } from './auth-context';
import { isValidToken, setSession } from './utils';
import { ActionMapType, AuthStateType } from '../../types';
import { IUserItem } from '../../../types/user';
// ----------------------------------------------------------------------
// NOTE:
// We only build demo at basic level.
// Customer will need to do some extra handling yourself if you want to extend the logic and other features...
// ----------------------------------------------------------------------
enum Types {
INITIAL = 'INITIAL',
LOGIN = 'LOGIN',
REGISTER = 'REGISTER',
LOGOUT = 'LOGOUT',
}
type Payload = {
[Types.INITIAL]: {
user: IUserItem | null;
};
[Types.LOGIN]: {
user: IUserItem;
};
[Types.REGISTER]: {
user: IUserItem;
};
[Types.LOGOUT]: undefined;
};
type ActionsType = ActionMapType<Payload>[keyof ActionMapType<Payload>];
// ----------------------------------------------------------------------
const initialState: AuthStateType = {
user: null,
loading: true,
};
const reducer = (state: AuthStateType, action: ActionsType) => {
if (action.type === Types.INITIAL) {
return {
loading: false,
user: action.payload.user,
};
}
if (action.type === Types.LOGIN) {
return {
...state,
user: action.payload.user,
};
}
if (action.type === Types.REGISTER) {
return {
...state,
user: action.payload.user,
};
}
if (action.type === Types.LOGOUT) {
return {
...state,
user: null,
};
}
return state;
};
// ----------------------------------------------------------------------
const STORAGE_KEY = 'accessToken';
type Props = {
children: React.ReactNode;
};
export function AuthProvider({ children }: Props) {
const [state, dispatch] = useReducer(reducer, initialState);
const initialize = useCallback(async () => {
try {
const accessToken = sessionStorage.getItem(STORAGE_KEY);
if (accessToken && isValidToken(accessToken)) {
setSession(accessToken);
const response = await axios.get(endpoints.auth.me);
const { user } = response.data;
dispatch({
type: Types.INITIAL,
payload: {
user,
},
});
} else {
dispatch({
type: Types.INITIAL,
payload: {
user: null,
},
});
}
} catch (error) {
console.error(error);
dispatch({
type: Types.INITIAL,
payload: {
user: null,
},
});
}
}, []);
useEffect(() => {
initialize();
}, [initialize]);
// LOGIN
const login = useCallback(async (email: string, password: string) => {
const data = {
email,
password,
};
const response = await axios.post(endpoints.auth.login, data);
const { accessToken, user } = response.data;
console.log('SLAT logging in response', user);
setSession(accessToken);
dispatch({
type: Types.LOGIN,
payload: {
user,
},
});
}, []);
// REGISTER
const register = useCallback(
async (email: string, password: string, firstName: string, lastName: string) => {
const data = {
email,
password,
firstName,
lastName,
};
const response = await axios.post(endpoints.auth.register, data);
const { accessToken, user } = response.data;
sessionStorage.setItem(STORAGE_KEY, accessToken);
dispatch({
type: Types.REGISTER,
payload: {
user,
},
});
},
[]
);
// LOGOUT
const logout = useCallback(async () => {
setSession(null);
dispatch({
type: Types.LOGOUT,
});
}, []);
// ----------------------------------------------------------------------
const checkAuthenticated = state.user ? 'authenticated' : 'unauthenticated';
const status = state.loading ? 'loading' : checkAuthenticated;
const memoizedValue = useMemo(
() => ({
user: state.user,
method: 'jwt',
loading: status === 'loading',
authenticated: status === 'authenticated',
unauthenticated: status === 'unauthenticated',
//
login,
register,
logout,
}),
[login, logout, register, state.user, status]
);
return <AuthContext.Provider value={memoizedValue}>{children}</AuthContext.Provider>;
}
Editor is loading...