From 796c363ea4caef0151c6339b94223183a23884b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B0=D1=82=D1=8C=D1=8F=D0=BD=D0=B0=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B4=D1=80=D0=B5=D0=B5=D0=B2=D0=B0?= Date: Wed, 25 Dec 2024 20:15:59 +0300 Subject: [PATCH] add routes auth --- frontend/index.html | 2 +- frontend/src/App.jsx | 14 ++++--- frontend/src/context/AuthProvider.jsx | 21 ++++++++++ frontend/src/context/index.jsx | 5 +++ frontend/src/hooks/index.jsx | 7 ++++ frontend/src/{index.jsx => index.js} | 0 frontend/src/locales/ru.js | 15 +++++++- frontend/src/pages/LoginPage.jsx | 55 ++++++++++++++++++--------- frontend/src/store/channelsSlice.js | 26 ++++++------- frontend/src/store/index.js | 14 +++---- frontend/src/utils/routes.js | 6 ++- frontend/src/utils/validate.js | 8 ++++ 12 files changed, 127 insertions(+), 46 deletions(-) create mode 100644 frontend/src/context/AuthProvider.jsx create mode 100644 frontend/src/context/index.jsx create mode 100644 frontend/src/hooks/index.jsx rename frontend/src/{index.jsx => index.js} (100%) create mode 100644 frontend/src/utils/validate.js diff --git a/frontend/index.html b/frontend/index.html index 580fd32..a4804d3 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -8,6 +8,6 @@
- + diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 7460f20..0752bff 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -5,6 +5,7 @@ import PageNotFound from './pages/PageNotFound.jsx'; import MainPage from './pages/MainPage.jsx'; import LoginPage from './pages/LoginPage.jsx'; import router from './utils/routes.js'; +import AuthProvider from './context/AuthProvider.jsx'; const App = () => { return ( @@ -16,11 +17,14 @@ const App = () => { - - } /> - } /> - } /> - + + + } /> + } /> + } /> + + + ); diff --git a/frontend/src/context/AuthProvider.jsx b/frontend/src/context/AuthProvider.jsx new file mode 100644 index 0000000..4f90c0f --- /dev/null +++ b/frontend/src/context/AuthProvider.jsx @@ -0,0 +1,21 @@ +import { useState } from 'react'; +import AuthContext from '../context/index.jsx'; + +// eslint-disable-next-line react/prop-types +const AuthProvider = ({ children }) => { + const [loggedIn, setLoggedIn] = useState(false); + + const logIn = () => setLoggedIn(true); + const logOut = () => { + localStorage.removeItem('username'); + setLoggedIn(false); + }; + + return ( + + {children} + + ); +}; + +export default AuthProvider; \ No newline at end of file diff --git a/frontend/src/context/index.jsx b/frontend/src/context/index.jsx new file mode 100644 index 0000000..d86a8cb --- /dev/null +++ b/frontend/src/context/index.jsx @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +const AuthContext = createContext({}); + +export default AuthContext; \ No newline at end of file diff --git a/frontend/src/hooks/index.jsx b/frontend/src/hooks/index.jsx new file mode 100644 index 0000000..0b16037 --- /dev/null +++ b/frontend/src/hooks/index.jsx @@ -0,0 +1,7 @@ +import { useContext } from 'react'; + +import authContext from '../context/index.jsx'; + +const useAuth = () => useContext(authContext); + +export default useAuth; \ No newline at end of file diff --git a/frontend/src/index.jsx b/frontend/src/index.js similarity index 100% rename from frontend/src/index.jsx rename to frontend/src/index.js diff --git a/frontend/src/locales/ru.js b/frontend/src/locales/ru.js index 7c645e4..fd6f18e 100644 --- a/frontend/src/locales/ru.js +++ b/frontend/src/locales/ru.js @@ -1 +1,14 @@ -export default {}; \ No newline at end of file +export default { + translation: { + loginForm: { + title: 'Войти', + username: 'Ваш ник', + password: 'Пароль', + span: 'Нет аккаунта?', + signUp: 'Регистрация', + }, + // singUpForm: { + // username: '' + // } + } + }; \ No newline at end of file diff --git a/frontend/src/pages/LoginPage.jsx b/frontend/src/pages/LoginPage.jsx index 9cee4f5..bdf8ce4 100644 --- a/frontend/src/pages/LoginPage.jsx +++ b/frontend/src/pages/LoginPage.jsx @@ -1,23 +1,44 @@ +import axios from 'axios'; +import { useEffect, useRef, useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap'; import { useFormik } from 'formik'; -import * as yup from 'yup'; +import { useTranslation } from 'react-i18next'; import avatarLogin from '../assets/avatarLogin.jpg'; +import useAuth from '../hooks/index.js'; +import routes from '../utils/routes.js'; + const LoginPage = () => { - const schema = yup.object().shape({ - username: yup.string().required(), - password: yup.string().required(), - }); + const auth = useAuth(); + const { t } = useTranslation(); + const [authFailed, setAuthFailed] = useState(false); + const inputEl = useRef(null); + const navigate = useNavigate(); + + useEffect(() => { + inputEl.current.focus(); + }, []); const formik = useFormik({ initialValues: { username: '', password: '', }, - onSubmit: values => { - alert(JSON.stringify(values, null, 2)); + validationSchema: userSchema(t), + onSubmit: async (values) => { + setAuthFailed(false); + try { + const res = await axios.post(routes.loginPath(), values); + console.log(res); + localStorage.setItem('token', res.data.token); + auth.logIn(); + } catch (err) { + console.log(err); + } }, }); + return ( @@ -28,44 +49,44 @@ const LoginPage = () => { Войти
-

Войти

+

{t('loginForm.title')}

- Ваш ник + {t('loginForm.username')} - Пароль + {t('loginForm.password')} - +
- Нет аккаунта? - Регистрация + {t('loginForm.span')} + {t('loginForm.signUp')}
diff --git a/frontend/src/store/channelsSlice.js b/frontend/src/store/channelsSlice.js index 125f008..c8e7147 100644 --- a/frontend/src/store/channelsSlice.js +++ b/frontend/src/store/channelsSlice.js @@ -1,17 +1,17 @@ -import { createSlice } from '@reduxjs/toolkit'; +// import { createSlice } from '@reduxjs/toolkit'; -const initialState = { - channels: [], - activeChannel: 1, -}; +// const initialState = { +// channels: [], +// activeChannel: 1, +// }; -const channelsSlice = createSlice({ - name: 'channels', - initialState, - reducers: { +// const channelsSlice = createSlice({ +// name: 'channels', +// initialState, +// reducers: { - } -}); +// } +// }); -export const { actions } = channelsSlice; -export default channelsSlice.reducer; \ No newline at end of file +// export const { actions } = channelsSlice; +// export default channelsSlice.reducer; \ No newline at end of file diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 9e551b8..5f49518 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -1,8 +1,8 @@ -import { configureStore } from '@reduxjs/toolkit'; -import channelsReducer from './channelsSlice'; +// import { configureStore } from '@reduxjs/toolkit'; +// import channelsReducer from './channelsSlice'; -export default configureStore({ - reducer: { - channels: channelsReducer, - } -}); \ No newline at end of file +// export default configureStore({ +// reducer: { +// channels: channelsReducer, +// } +// }); \ No newline at end of file diff --git a/frontend/src/utils/routes.js b/frontend/src/utils/routes.js index 24d751e..e648190 100644 --- a/frontend/src/utils/routes.js +++ b/frontend/src/utils/routes.js @@ -1,4 +1,6 @@ +const apiPath = '/api/v1'; + export default { - login: '/login', - main: '/', + loginPath: () => '/login', + usersPath: () => [apiPath, 'data'].join('/'), }; \ No newline at end of file diff --git a/frontend/src/utils/validate.js b/frontend/src/utils/validate.js new file mode 100644 index 0000000..4c47810 --- /dev/null +++ b/frontend/src/utils/validate.js @@ -0,0 +1,8 @@ +import { object, string } from 'yup'; + +const userSchema = (t) => object().shape({ + username: string().required(), + password: string().required(), +}); + +export default userSchema; \ No newline at end of file