Open zezung27 opened 1 year ago
import { ENDPOINTS } from "constants/endpoints"; import baseApi from "./base-api";
const apiAuth = {
register: (data) =>
baseApi.post(${ENDPOINTS.BASE_BACK_END_URL}${ENDPOINTS.REGISTER}
, data),
login: (data) =>
baseApi.post(${ENDPOINTS.BASE_BACK_END_URL}${ENDPOINTS.LOGIN}
, data),
fetchAlluser: () =>
baseApi.get(${ENDPOINTS.BASE_BACK_END_URL}${ENDPOINTS.ALL_USER}
),
};
export default apiAuth;
import apiAuth from "api/auth"; import { ACTION_CONST } from "constants/actions"; import { LOCAL_STORAGE } from "constants/store"; import { takeLatest, put, call } from "redux-saga/effects";
const saveToken = async (resData) => { await localStorage.setItem( LOCAL_STORAGE.ACCESS_TOKEN, resData.data.accessToken ); await localStorage.setItem( LOCAL_STORAGE.REFRESH_TOKEN, resData.data.refreshToken ); await localStorage.setItem(LOCAL_STORAGE.ACCOUNT_ID, resData.data.id); };
function* handleLogin(action) { try { const res = yield call(apiAuth.login, action.payload); if (res.status === 200) { saveToken(res); yield put({ type: ACTION_CONST.LOGIN_SUCCESS, data: res.data.data, }); } } catch (error) { console.log(error); } }
function* handleRegister(action) { try { const res = yield call(apiAuth.register, action.payload); console.log(res); if (res?.status === 200) { yield put({ type: ACTION_CONST.REGISTER_SUCCESS, data: res.data.data.id, }); } } catch (error) { console.log(error); } }
function* handleFetchAllUser() { try { const res = yield call(apiAuth.fetchAlluser); console.log(res); } catch (error) { console.log(error); } }
export function watchSubmitLogin() { yield takeLatest(ACTION_CONST.LOGIN_REQUEST, handleLogin); } export function watchSubmitRegister() { yield takeLatest(ACTION_CONST.REGISTER_REQUEST, handleRegister); } export function* watchFetchAllUser() { yield takeLatest(ACTION_CONST.FETCH_ALL_USER, handleFetchAllUser); }
import { all, call } from "redux-saga/effects"; import { watchSubmitLogin, watchSubmitRegister, watchFetchAllUser, } from "./userSaga";
export default function* rootSaga() { yield all([ call(watchSubmitLogin), call(watchSubmitRegister), call(watchFetchAllUser), ]); }
import { createStore, applyMiddleware } from "redux";
import reducers from "./reducers";
//Redux saga import createSagaMiddleware from "redux-saga"; import rootSaga from "./saga/rootSaga"; import { configureStore } from "@reduxjs/toolkit";
const middleware = []; const sagaMiddleware = createSagaMiddleware();
middleware.push(sagaMiddleware);
// const appMiddleWare = applyMiddleware(...middleware);
const store = configureStore({ reducer: reducers, middleware: middleware, });
sagaMiddleware.run(rootSaga);
export default store;
import { ACTION_CONST } from "constants/actions";
const initState = { userInfo: null, tokens: [], uuid: null, listUser: null, };
const reducer = (state = initState, action) => { switch (action.type) { case ACTION_CONST.LOGIN_SUCCESS: return { ...state, tokens: action.data, }; case ACTION_CONST.REGISTER_SUCCESS: return { ...state, uuid: action.data, };
case ACTION_CONST.GET_ALL_USER:
return {
...state,
listUser: action.data,
};
default:
return state;
} };
export default reducer;
import { combineReducers } from "redux"; import user from "redux/reducers/userReducer";
const reducers = combineReducers({ user, });
export default reducers;
import AboutPage from "page/About/AboutPage";
import LoginPage from "page/Auth/LoginPage";
import RegisterPage from "page/Auth/RegisterPage";
import ResetAccount from "page/Auth/ResetAccount";
import PageNotFound from "page/error/PageNotFound";
import HomePage from "page/Home/HomePage";
import React, { useState } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <HomePage />,
errorElement: <PageNotFound />,
},
{
path: "/about",
element: <AboutPage />,
},
{
path: "/register",
element: <RegisterPage />,
},
{
path: "/login",
element: <LoginPage />,
},
{
path: "/reset",
element: <ResetAccount />,
},
]);
const App = () => {
return
};
export default App;
import { Button, Form, Input } from "antd"; import React from "react"; import "./auth.scss"; import { Link } from "react-router-dom"; import { ROUTES } from "constants/routers";
const LoginPage = () => { const onFinish = (values) => { console.log(values); };
return ( <div className="container background-container" style={{ backgroundImage: "url(asset/bg5.jpg)" }}
Login to your account
<Form layout="vertical" name="register form" onFinish={onFinish}> <Form.Item name="email" label="Email" rules={[ { required: true, message: "Please enter your email" }, ]} hasFeedback > <Input placeholder="Please enter your email" /> </Form.Item> <Form.Item name="password" label="Password" rules={[ { required: true, message: "Please enter you password" }, ]} hasFeedback > <Input placeholder="Please enter your password" /> </Form.Item> <div style={{ marginTop: 5, marginBottom: 5 }}> <Link to={ROUTES.FORGET_PASSWORD}>Forgot your password?</Link> </div> <Form.Item> <Button block type="primary" htmlType="submit"> Login </Button> </Form.Item> <div className="text-center"> <small>Don't have an account?</small>{" "} <Link to={ROUTES.REGISTER}>Register</Link> </div> </Form> </div> </div> </div> </div> </div>
); };
export default LoginPage;
zezung27 commented 1 year agoimport { Button, Checkbox, Form, Input } from "antd"; import React from "react"; import "./auth.scss"; import { Link } from "react-router-dom"; import { ROUTES } from "constants/routers";
const RegisterPage = () => { const regex = /^(?=.?[A-Z])(?=.?[a-z])(?=.*?[0-9]).{8,}$/;
const onFinish = (values) => { console.log(values); };
return ( <div className="container background-container" style={{ backgroundImage: "url(asset/bg5.jpg)" }}
Register Account
<Form layout="vertical" name="register form" onFinish={onFinish}> <Form.Item name="email" label="Email" rules={[ { required: true, message: "Please enter your email" }, { type: "email", message: "Please enter a valid mail" }, ]} hasFeedback > <Input placeholder="Please enter your email" /> </Form.Item> <Form.Item name="username" label="User Name" rules={[ { required: true, message: "Please enter your user name" }, { whitespace: true }, { min: 6 }, { max: 12 }, ]} hasFeedback > <Input placeholder="Please enter your user name" /> </Form.Item> <Form.Item name="password" label="Password" rules={[ { required: true }, { min: 8 }, { validator: (_, value) => value && regex.test(value) ? Promise.resolve() : Promise.reject( "Minimum 8 characters, at least one uppercase English letter, one lowercase English letter and one number." ), }, ]} hasFeedback > <Input.Password placeholder="Please enter your password" value="" /> </Form.Item> <Form.Item name="confirmPassword" label="Comfirm Password" rules={[ { required: true }, ({ getFieldValue }) => ({ validator(_, value) { if (!value || getFieldValue("password") === value) { return Promise.resolve(); } return Promise.reject( new Error( "The two passwords that you entered do not match!" ) ); }, }), ]} hasFeedback > <Input.Password placeholder="Please comfirm your password" /> </Form.Item> <Form.Item name="agreement" valuePropName="checked" rules={[ { validator: (_, value) => value ? Promise.resolve() : Promise.reject( "To proceed, you need to agree with our terms and conditions" ), }, ]} > <Checkbox> {" "} Agree to our{" "} <Link to={ROUTES.TERMS}> <span style={{ color: "blue" }}> Terms and Conditions </span> </Link> </Checkbox> </Form.Item> <Form.Item> <Button block type="primary" htmlType="submit"> Register </Button> </Form.Item> <div className="text-center"> <small>Already have an account?</small>{" "} <Link to={ROUTES.LOGIN}>Login</Link> </div> </Form> </div> </div> </div> </div> </div>
); };
export default RegisterPage;
zezung27 commented 1 year agoimport { Button, Form, Input } from "antd"; import React from "react"; import "./auth.scss"; import { Link } from "react-router-dom"; import { ROUTES } from "constants/routers";
const ResetAccount = () => { const onFinish = (values) => { console.log(values); };
return ( <div className="container background-container" style={{ backgroundImage: "url(asset/bg5.jpg)" }}
Reset your password
Enter the email address associated with your account and we'll send you a link to reset your password.
<Form layout="vertical" name="register form" onFinish={onFinish}> <Form.Item name="email" label="Email" rules={[ { required: true, message: "Please enter your email" }, { type: "email", message: "Please enter a valid mail" }, ]} hasFeedback > <Input placeholder="Please enter your email" /> </Form.Item> <Form.Item> <Button block type="primary" htmlType="submit"> Reset Account </Button> </Form.Item> <div className="text-center"> <Link to={ROUTES.REGISTER}>Return to login</Link> </div> </Form> </div> </div> </div> </div> </div>
); };
export default ResetAccount;
zezung27 commented 1 year ago"dependencies": {
"@reduxjs/toolkit": "^1.9.3", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "antd": "^5.3.2", "axios": "^1.3.4", "lodash": "^4.17.21", "react": "^18.2.0", "react-bootstrap": "^2.7.2", "react-dom": "^18.2.0", "react-icons": "^4.8.0", "react-redux": "^8.0.5", "react-router-dom": "^6.9.0", "react-scripts": "5.0.1", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-saga": "^1.2.2", "sass": "^1.59.3", "web-vitals": "^2.1.4"
},
zezung27 commented 1 year ago{ "compilerOptions": { "baseUrl": "src" } }
import axios from "axios"; import { ENDPOINTS } from "constants/endpoints"; import { LOCAL_STORAGE } from "constants/store"; import { get } from "lodash";
const headersDefault = { "Content-Type": "application/json", Accept: "application/json", }; const api = axios.create({ baseURL: ENDPOINTS.BASE_BACK_END_URL, timeout: LOCAL_STORAGE.TIMEOUT, headers: headersDefault, });
// Add a request interceptor api.interceptors.request.use( async (config) => { const token = localStorage.getItem(LOCAL_STORAGE.ACCESS_TOKEN); if (token) config.headers["Authorization"] =
Bearer ${token}
; return config; }, (error) => { Promise.reject(error); } );// Add a response interceptor api.interceptors.response.use( (response) => { return response; }, async (error) => { const originalRequest = error.response.config; if ( error.response.status === 401 && originalRequest.url ===
${ENDPOINTS.BASE_BACK_END_URL}${ENDPOINTS.REFRESH_TOKEN}
) { localStorage.removeItem(LOCAL_STORAGE.ACCESS_TOKEN); localStorage.removeItem(LOCAL_STORAGE.REFRESH_TOKEN); localStorage.removeItem(LOCAL_STORAGE.ACCOUNT_ID); // navagate to login page} );
const baseApi = { get: (url, params) => { return api({ method: "get", url: url, params, headers: { ...headersDefault, Authorization:
Bearer ${localStorage.getItem( LOCAL_STORAGE.ACCESS_TOKEN )}
, }, }) .then((response) => { return response; }) .catch((err) => { throw err; }); }, post: (url, data, header = headersDefault) => { return api({ method: "post", url: url, data: data, headers: { ...headersDefault, Authorization:Bearer ${localStorage.getItem( LOCAL_STORAGE.ACCESS_TOKEN )}
, ...header, }, }) .then((response) => { return response; }) .catch((err) => { throw err; }); }, delete: (url, data) => { return api({ method: "delete", url: url, data: data, headers: { ...headersDefault, Authorization:Bearer ${localStorage.getItem( LOCAL_STORAGE.ACCESS_TOKEN )}
, }, }) .then((response) => { return response; }) .catch((err) => { throw err; }); }, put: (url, data) => { return api({ method: "put", url: url, data: data, headers: { ...headersDefault, Authorization:Bearer ${localStorage.getItem( LOCAL_STORAGE.ACCESS_TOKEN )}
, }, }) .then((response) => { return response; }) .catch((err) => { throw err; }); }, };export default baseApi;