Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bao fe #227

Merged
merged 4 commits into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend-manager-student/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,8 @@ module.exports = {
'no-unused-expressions': 'off',
'eslint-disable-next-line implicit-arrow-linebreak': 'off',
'eslint-disable object-curly-newline': 'off',
'brace-style': ['error', '1tbs', { allowSingleLine: true }],
'object-curly-newline': 'off',
'implicit-arrow-linebreak': 'off',
},
};
62 changes: 60 additions & 2 deletions frontend-manager-cms/src/App.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,78 @@
//!LIBRARY
import React, { Suspense } from 'react';
import React, { Suspense, useState } from 'react';
import { Route, Routes } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import axios from 'axios';

//! SHARE
import CONSTANTS from 'configs/constants';
import { clearToken, setToken } from 'utils/auth';
import HELPERS from 'utils/helper';

//! COMPONENT
import Loading from 'components/Loading';

//! PAGE
//! API
import API_ADMIN from 'api/api_admin';

//! PLUGIN
import { axiosIns } from 'plugins/axios/axios';

//! ROUTES
import RouteDataMain from 'routers/index';

//! IMPORT
import { NotFound } from 'imports/notfound_import/index';

//! CUSTOM HOOK
import Navigate from 'custom_hook/useNavigate/Navigate';
import { useDispatch } from 'react-redux';
import { Renew_Token_Cms_Initial } from 'redux/managers/authentication_slice/auth_thunk';

function App() {
// Navigate
const { navigateChangePage } = Navigate();

//InitialState action
const dispatch = useDispatch();

// isRefreshing
const [isRefreshing, setIsRefreshing] = useState(false);

axiosIns.interceptors.response.use(
(response) => response,
async (err) => {
const originalConfig = err?.config;
if (
originalConfig &&
originalConfig?.url !== API_ADMIN.LOGIN_ADMIN_CMS &&
err.response &&
err.response?.status === CONSTANTS.STATUS._UNAUTHORIZED &&
!originalConfig._retry &&
!isRefreshing
) {
originalConfig._retry = CONSTANTS.DELETED_ENABLE;
originalConfig.headers = { ...originalConfig.headers };

setIsRefreshing(true);

try {
dispatch(Renew_Token_Cms_Initial());

setIsRefreshing(false);

return axiosIns(originalConfig);
} catch (_error) {
clearToken(CONSTANTS.AUTH_TOKEN);

navigateChangePage('/login');

return Promise.reject(_error);
}
}
return Promise.reject(err);
},
);
return (
<React.Fragment>
<Suspense Suspense fallback={<Loading />}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import NOTIFICATION from 'utils/notification';

const LoadingMain = ({ data }) => {
console.log(data, data);
const [count, setCount] = useState(2);
const navigate = useNavigate();
const location = useLocation();

useEffect(() => {
if (data) {
// Check If Already login
const interval = setInterval(() => {
setCount((currentCount) => --currentCount);
}, 1000);
count === 0 && navigate('/', { replace: true, state: { from: location } });
count === 0 && NOTIFICATION.notifyError('Please Logout😵');
return () => clearInterval(interval);
} else {
// Check if not login
const interval = setInterval(() => {
setCount((currentCount) => --currentCount);
}, 1000);
count === 0 && navigate('/login', { replace: true, state: { from: location } });
count === 0 && NOTIFICATION.notifyError('Please Login when you to the WebSite 😵');
return () => clearInterval(interval);
}
}, [count]);
return (
<React.Fragment>
<div className=" loader-container">
<h1>Loading.....</h1>
</div>
</React.Fragment>
);
};

export default LoadingMain;
45 changes: 45 additions & 0 deletions frontend-manager-cms/src/configs/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,50 @@ const CONSTANTS = {
OS_TYPE_HEADER: 'web',
OS_VERSION_HEADER: '1.0',
APP_VERSION_HEADER: '1.0',
ACCEPT_HEADER: 'application/json',
BEARER_HEADER: 'Bearer',

/**
* @author Nguyễn Tiến Tài
* @created_at 15/03/2023
* @updated_at 22/03/2023
* @descriptionKey STATUS CODE
* @return {string}
*/
STATUS: {
// 2XX
_OK: 200,
//4X,
_BAD_REQUEST: 400,
_UNAUTHORIZED: 401,
_NOT_FOUND: 404,
},
/**
* @author Nguyễn Tiến Tài
* @created_at 22/03/2023
* @descriptionKey TIME OUT
* @return {number}
*/
TIME_OUT_AXIOS: 3000,
/**
* @author Nguyễn Tiến Tài
* @created_at 22/03/2023
* @descriptionKey Type data
* @return {*}
*/
DATA: {
_NULL: 'null',
},
/**
* @author Nguyễn Tiến Tài
* @created_at 22/03/2023
* @descriptionKey Name redux thunk
* @return {string}
*/
REDUX_NAME: {
_AUTH: 'AUTH ADMIN',
_BOOK: 'BOOK ADMIN',
_MEDIA: 'MEDIA CLOUD',
},
};
export default CONSTANTS;
31 changes: 0 additions & 31 deletions frontend-manager-cms/src/context/global_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,6 @@ export const store_library_school_contextUser = createContext();
export const useContextStudent = () => useContext(store_library_school_contextUser);

export const DataProviderCMS = ({ children }) => {
//InitialState action
const dispatch = useDispatch();

// Get Token localStore
const token_access_localStorage = getToken(CONSTANTS.AUTH_TOKEN);

useEffect(() => {
// Check Token LocalStorage
if (token_access_localStorage) {
// Return true or false
const decodedToken = HELPERS.isTokenExpired(token_access_localStorage);

// Function new token
const newToken = () => {
//Token expired
if (decodedToken === CONSTANTS.DELETED_DISABLE) {
// Token expired, try to renew it
dispatch(Renew_Token_Cms_Initial());
}
// Schedule next token renewal
setTimeout(() => {
//Start
newToken();
}, CONSTANTS._4_MINUTES);
};

//Start
newToken();
}
}, [token_access_localStorage, dispatch]);

//! Data
// const data = {
// profile_student_context: AuthStudent(),
Expand Down
16 changes: 16 additions & 0 deletions frontend-manager-cms/src/custom_hook/useNavigate/Navigate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! LIBRARY
import { useNavigate } from 'react-router-dom';

const Navigate = () => {
//Create navigate
const navigate = useNavigate();

// Handle change page
const navigateChangePage = (link) => {
navigate(link);
};

return { navigateChangePage };
};

export default Navigate;
34 changes: 31 additions & 3 deletions frontend-manager-cms/src/pages/Auth/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
//! LIBRARY
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';

//! IMPORT
import { SCHOOL_LOGO } from 'imports/home_import';
import React from 'react';
import { useDispatch } from 'react-redux';
import { Login_Cms_Initial } from 'redux/managers/authentication_slice/auth_thunk';

//! CUSTOM HOOK
import Navigate from 'custom_hook/useNavigate/Navigate';

//! UTILS
import HELPERS from 'utils/helper';

//! REDUX
import { Login_Cms_Initial } from 'redux/managers/authentication_slice/auth_thunk';

const Login = () => {
const dispatch = useDispatch();
const { admin_auth } = useSelector((state) => state.admin_user);

//Location
const location = useLocation();
// Navigate
const { navigateChangePage } = Navigate();

const handleLogin = (e) => {
e.preventDefault();
const values = HELPERS.formDataGeneral(e.target);

dispatch(Login_Cms_Initial(values));
};

useEffect(() => {
if (admin_auth) {
if (location.state?.from) {
navigateChangePage(location.state.from);
} else {
navigateChangePage('/');
}
}
}, [admin_auth]);
return (
<div className="w-screen">
<div className="h-screen grid grid-cols-5">
Expand Down
36 changes: 36 additions & 0 deletions frontend-manager-cms/src/plugins/axios/axios.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//! LIBRARY
import axios from 'axios';

//! SHARE
import CONSTANTS from 'configs/constants';
import { getToken } from 'utils/auth';

//! API
import API_STUDENT from 'api/api_admin';

export const axiosIns = axios.create({
baseURL: '',
timeout: CONSTANTS.TIME_OUT_AXIOS,
withCredentials: CONSTANTS.DELETED_ENABLE,
headers: {
Accept: CONSTANTS.ACCEPT_HEADER,
},
});

axiosIns.interceptors.request.use(
(config) => {
config.headers = config.headers ?? {};
if (config.url !== API_STUDENT.LOGIN_STUDENT) {
const auth = getToken(CONSTANTS.AUTH_TOKEN) || CONSTANTS.DATA._NULL;

if (auth) {
config.headers.authorization = `${CONSTANTS.BEARER_HEADER} ${auth}`;
}
}

return config;
},
(error) => {
return Promise.reject(error);
},
);
16 changes: 16 additions & 0 deletions frontend-manager-cms/src/private/Admin_Private_Router.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! LIBRARY
import CONSTANTS from 'configs/constants';
import { Outlet } from 'react-router-dom';

//! UTILS
import { getToken } from 'utils/auth';

//! COMPONENT
import LoadingMain from 'components/LoadingToRedirects/LoadingMain';

function Admin_Private_Router({ element: Element, ...rest }) {
const token = getToken(CONSTANTS.AUTH_TOKEN);
return <>{!token ? <Outlet /> : <LoadingMain data={true} />}</>;
}

export default Admin_Private_Router;
17 changes: 17 additions & 0 deletions frontend-manager-cms/src/private/Admin_Private_Router_login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! LIBRARY
import CONSTANTS from 'configs/constants';
import { Outlet } from 'react-router-dom';

//! UTILS
import { getToken } from 'utils/auth';

//! COMPONENT
import LoadingMain from 'components/LoadingToRedirects/LoadingMain';

function Admin_Private_Router({ element: Element, ...rest }) {
// Take token
const token = getToken(CONSTANTS.AUTH_TOKEN);
return <>{token ? <Outlet /> : <LoadingMain data={false} />}</>;
}

export default Admin_Private_Router;
15 changes: 0 additions & 15 deletions frontend-manager-cms/src/private/auth/Login.js

This file was deleted.

Loading