Separate Client Portal & Dashboard
This commit is contained in:
77
frontend/dashboard/src/contexts/CollapseDrawerContext.tsx
Normal file
77
frontend/dashboard/src/contexts/CollapseDrawerContext.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { ReactNode, createContext, useState, useEffect } from 'react';
|
||||
// hooks
|
||||
import useResponsive from '../hooks/useResponsive';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export type CollapseDrawerContextProps = {
|
||||
isCollapse?: boolean;
|
||||
collapseClick: boolean;
|
||||
collapseHover: boolean;
|
||||
onToggleCollapse: VoidFunction;
|
||||
onHoverEnter: VoidFunction;
|
||||
onHoverLeave: VoidFunction;
|
||||
};
|
||||
|
||||
const initialState: CollapseDrawerContextProps = {
|
||||
collapseClick: false,
|
||||
collapseHover: false,
|
||||
onToggleCollapse: () => {},
|
||||
onHoverEnter: () => {},
|
||||
onHoverLeave: () => {}
|
||||
};
|
||||
|
||||
const CollapseDrawerContext = createContext(initialState);
|
||||
|
||||
type CollapseDrawerProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function CollapseDrawerProvider({ children }: CollapseDrawerProviderProps) {
|
||||
const isDesktop = useResponsive('up', 'lg');
|
||||
|
||||
const [collapse, setCollapse] = useState({
|
||||
click: false,
|
||||
hover: false
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDesktop) {
|
||||
setCollapse({
|
||||
click: false,
|
||||
hover: false
|
||||
});
|
||||
}
|
||||
}, [isDesktop]);
|
||||
|
||||
const handleToggleCollapse = () => {
|
||||
setCollapse({ ...collapse, click: !collapse.click });
|
||||
};
|
||||
|
||||
const handleHoverEnter = () => {
|
||||
if (collapse.click) {
|
||||
setCollapse({ ...collapse, hover: true });
|
||||
}
|
||||
};
|
||||
|
||||
const handleHoverLeave = () => {
|
||||
setCollapse({ ...collapse, hover: false });
|
||||
};
|
||||
|
||||
return (
|
||||
<CollapseDrawerContext.Provider
|
||||
value={{
|
||||
isCollapse: collapse.click && !collapse.hover,
|
||||
collapseClick: collapse.click,
|
||||
collapseHover: collapse.hover,
|
||||
onToggleCollapse: handleToggleCollapse,
|
||||
onHoverEnter: handleHoverEnter,
|
||||
onHoverLeave: handleHoverLeave
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CollapseDrawerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export { CollapseDrawerProvider, CollapseDrawerContext };
|
||||
186
frontend/dashboard/src/contexts/LaravelAuthContext.tsx
Normal file
186
frontend/dashboard/src/contexts/LaravelAuthContext.tsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import { createContext, ReactNode, useEffect, useReducer } from 'react';
|
||||
// utils
|
||||
import axios from '../utils/axios';
|
||||
// import { isValidToken, setSession } from '../utils/jwt';
|
||||
import { setSession, getSession } from '../utils/token';
|
||||
// @types
|
||||
import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
enum Types {
|
||||
Initial = 'INITIALIZE',
|
||||
Login = 'LOGIN',
|
||||
Logout = 'LOGOUT',
|
||||
Register = 'REGISTER',
|
||||
}
|
||||
|
||||
type JWTAuthPayload = {
|
||||
[Types.Initial]: {
|
||||
isAuthenticated: boolean;
|
||||
user: AuthUser;
|
||||
};
|
||||
[Types.Login]: {
|
||||
user: AuthUser;
|
||||
};
|
||||
[Types.Logout]: undefined;
|
||||
[Types.Register]: {
|
||||
user: AuthUser;
|
||||
};
|
||||
};
|
||||
|
||||
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: true,
|
||||
user: action.payload.user,
|
||||
};
|
||||
case 'LOGOUT':
|
||||
return {
|
||||
...state,
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
};
|
||||
|
||||
case 'REGISTER':
|
||||
return {
|
||||
...state,
|
||||
isAuthenticated: true,
|
||||
user: action.payload.user,
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const AuthContext = createContext<JWTContextType | null>(null);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type AuthProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function AuthProvider({ children }: AuthProviderProps) {
|
||||
const [state, dispatch] = useReducer(JWTReducer, initialState);
|
||||
|
||||
useEffect(() => {
|
||||
const initialize = async () => {
|
||||
try {
|
||||
const accessToken = getSession();
|
||||
|
||||
if (accessToken) {
|
||||
setSession(accessToken);
|
||||
|
||||
// const response = await axios.get('/api/account/my-account');
|
||||
// const { user } = response.data;
|
||||
|
||||
// dispatch({
|
||||
// type: Types.Initial,
|
||||
// payload: {
|
||||
// isAuthenticated: true,
|
||||
// user,
|
||||
// },
|
||||
// });
|
||||
} else {
|
||||
dispatch({
|
||||
type: Types.Initial,
|
||||
payload: {
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
dispatch({
|
||||
type: Types.Initial,
|
||||
payload: {
|
||||
isAuthenticated: false,
|
||||
user: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
initialize();
|
||||
}, []);
|
||||
|
||||
// const csrf = () => axios.get('/sanctum/csrf-cookie')
|
||||
|
||||
const login = async (email: string, password: string) => {
|
||||
axios
|
||||
.post('/login', { email, password })
|
||||
.then((response) => {
|
||||
const { user, token } = response.data;
|
||||
setSession(token);
|
||||
|
||||
dispatch({
|
||||
type: Types.Login,
|
||||
payload: {
|
||||
user,
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response.status !== 422) throw error
|
||||
})
|
||||
};
|
||||
|
||||
const register = async (email: string, password: string, firstName: string, lastName: string) => {
|
||||
const response = await axios.post('/api/register', {
|
||||
email,
|
||||
password,
|
||||
firstName,
|
||||
lastName,
|
||||
});
|
||||
const { accessToken, user } = response.data;
|
||||
|
||||
window.localStorage.setItem('accessToken', accessToken);
|
||||
dispatch({
|
||||
type: Types.Register,
|
||||
payload: {
|
||||
user,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
console.log('LOGOUT CALLEDS NAKJSNDKJASNDKJASDNAKJSND')
|
||||
setSession(null);
|
||||
dispatch({ type: Types.Logout });
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
...state,
|
||||
method: 'jwt',
|
||||
login,
|
||||
logout,
|
||||
register,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export { AuthContext, AuthProvider };
|
||||
128
frontend/dashboard/src/contexts/SettingsContext.tsx
Normal file
128
frontend/dashboard/src/contexts/SettingsContext.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import { ReactNode, createContext } from 'react';
|
||||
// hooks
|
||||
import useLocalStorage from '../hooks/useLocalStorage';
|
||||
// utils
|
||||
import getColorPresets, { colorPresets, defaultPreset } from '../utils/getColorPresets';
|
||||
// config
|
||||
import { defaultSettings } from '../config';
|
||||
// @type
|
||||
import {
|
||||
ThemeMode,
|
||||
ThemeLayout,
|
||||
ThemeDirection,
|
||||
ThemeColorPresets,
|
||||
SettingsContextProps,
|
||||
} from '../components/settings/type';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const initialState: SettingsContextProps = {
|
||||
...defaultSettings,
|
||||
onChangeMode: () => {},
|
||||
onToggleMode: () => {},
|
||||
onChangeDirection: () => {},
|
||||
onChangeColor: () => {},
|
||||
onToggleStretch: () => {},
|
||||
onChangeLayout: () => {},
|
||||
onResetSetting: () => {},
|
||||
setColor: defaultPreset,
|
||||
colorOption: [],
|
||||
};
|
||||
|
||||
const SettingsContext = createContext(initialState);
|
||||
|
||||
type SettingsProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function SettingsProvider({ children }: SettingsProviderProps) {
|
||||
const [settings, setSettings] = useLocalStorage('settings', {
|
||||
themeMode: initialState.themeMode,
|
||||
themeDirection: initialState.themeDirection,
|
||||
themeColorPresets: initialState.themeColorPresets,
|
||||
themeStretch: initialState.themeStretch,
|
||||
themeLayout: initialState.themeLayout,
|
||||
});
|
||||
|
||||
const onChangeMode = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeMode: (event.target as HTMLInputElement).value as ThemeMode,
|
||||
});
|
||||
};
|
||||
|
||||
const onToggleMode = () => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeMode: settings.themeMode === 'light' ? 'dark' : 'light',
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeDirection = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeDirection: (event.target as HTMLInputElement).value as ThemeDirection,
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeColor = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeColorPresets: (event.target as HTMLInputElement).value as ThemeColorPresets,
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeLayout = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeLayout: (event.target as HTMLInputElement).value as ThemeLayout,
|
||||
});
|
||||
};
|
||||
|
||||
const onToggleStretch = () => {
|
||||
setSettings({
|
||||
...settings,
|
||||
themeStretch: !settings.themeStretch,
|
||||
});
|
||||
};
|
||||
|
||||
const onResetSetting = () => {
|
||||
setSettings({
|
||||
themeMode: initialState.themeMode,
|
||||
themeLayout: initialState.themeLayout,
|
||||
themeStretch: initialState.themeStretch,
|
||||
themeDirection: initialState.themeDirection,
|
||||
themeColorPresets: initialState.themeColorPresets,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsContext.Provider
|
||||
value={{
|
||||
...settings,
|
||||
// Mode
|
||||
onChangeMode,
|
||||
onToggleMode,
|
||||
// Direction
|
||||
onChangeDirection,
|
||||
// Color
|
||||
onChangeColor,
|
||||
setColor: getColorPresets(settings.themeColorPresets),
|
||||
colorOption: colorPresets.map((color) => ({
|
||||
name: color.name,
|
||||
value: color.main,
|
||||
})),
|
||||
// Stretch
|
||||
onToggleStretch,
|
||||
// Navbar Horizontal
|
||||
onChangeLayout,
|
||||
// Reset Setting
|
||||
onResetSetting,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export { SettingsProvider, SettingsContext };
|
||||
Reference in New Issue
Block a user