diff --git a/lab5/src/components/logins/hooks/DataItemHook.js b/lab5/src/components/logins/hooks/DataItemHook.js
new file mode 100644
index 0000000..0d14246
--- /dev/null
+++ b/lab5/src/components/logins/hooks/DataItemHook.js
@@ -0,0 +1,33 @@
+import { useEffect, useState } from 'react';
+import EntrysDataApiService from '../service/EntrysDataApiService';
+
+const useEntysDataItem = (id) => {
+ const emptyItem = {
+ id: '',
+ login: '',
+ password: '',
+ role: '',
+ };
+ const [item, setItem] = useState({ ...emptyItem });
+
+ const getItem = async (itemId = undefined) => {
+ if (itemId && itemId > 0) {
+ const data = await EntrysDataApiService.get(itemId);
+ setItem(data);
+ } else {
+ setItem({ ...emptyItem });
+ }
+ };
+
+ useEffect(() => {
+ getItem(id);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [id]);
+
+ return {
+ item,
+ setItem,
+ };
+};
+
+export default useEntysDataItem;
diff --git a/lab5/src/components/logins/hooks/EntrysDataHook.js b/lab5/src/components/logins/hooks/EntrysDataHook.js
new file mode 100644
index 0000000..abfc5c9
--- /dev/null
+++ b/lab5/src/components/logins/hooks/EntrysDataHook.js
@@ -0,0 +1,22 @@
+import { useEffect, useState } from 'react';
+import EntrysDataApiService from '../service/EntrysDataApiService';
+
+const useEntrysData = (login, password, expand) => {
+ const [entrys, setEntrys] = useState([]);
+
+ const getEntrysData = async () => {
+ const data = await EntrysDataApiService.getAll(expand);
+ setEntrys(data ?? []);
+ };
+
+ useEffect(() => {
+ getEntrysData();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [login, password]);
+
+ return {
+ entrys,
+ };
+};
+
+export default useEntrysData;
diff --git a/lab5/src/components/logins/hooks/EntrysDataItemHook.js b/lab5/src/components/logins/hooks/EntrysDataItemHook.js
new file mode 100644
index 0000000..2d16161
--- /dev/null
+++ b/lab5/src/components/logins/hooks/EntrysDataItemHook.js
@@ -0,0 +1,60 @@
+import { useState } from 'react';
+import EntrysDataApiService from '../service/EntrysDataApiService';
+import useEntysDataItem from './DataItemHook';
+
+const useEntrysItemForm = (id) => {
+ const { item, setItem } = useEntysDataItem(id);
+
+ const [validated, setValidated] = useState(false);
+
+ const resetValidity = () => {
+ setValidated(false);
+ };
+
+ const getLineObject = (formData) => {
+ const Login = formData.login.toString();
+ const Password = formData.password.toString();
+ const Role = 'user';
+ return {
+ login: Login,
+ password: Password,
+ role: Role,
+ };
+ };
+
+ const handleChange = (event) => {
+ const inputName = event.target.name;
+ const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
+ setItem({
+ ...item,
+ [inputName]: inputValue,
+ });
+ };
+
+ const handleSubmit = async (event) => {
+ const form = event.currentTarget;
+ event.preventDefault();
+ event.stopPropagation();
+ const body = getLineObject(item);
+ if (form.checkValidity()) {
+ if (id === undefined) {
+ await EntrysDataApiService.create(body);
+ } else {
+ await EntrysDataApiService.update(id, body);
+ }
+ return true;
+ }
+ setValidated(true);
+ return false;
+ };
+
+ return {
+ item,
+ validated,
+ UseHandleSubmit: handleSubmit,
+ UseHandleChange: handleChange,
+ resetValidity,
+ };
+};
+
+export default useEntrysItemForm;
diff --git a/lab5/src/components/logins/hooks/Reducer.js b/lab5/src/components/logins/hooks/Reducer.js
new file mode 100644
index 0000000..e69de29
diff --git a/lab5/src/components/logins/login/Entry.jsx b/lab5/src/components/logins/login/Entry.jsx
new file mode 100644
index 0000000..1b79c58
--- /dev/null
+++ b/lab5/src/components/logins/login/Entry.jsx
@@ -0,0 +1,58 @@
+import { useState } from 'react';
+import { Link } from 'react-router-dom';
+import toast from 'react-hot-toast';
+import { Button, Form } from 'react-bootstrap';
+import Input from '../../input/Input.jsx';
+import useEntrysData from '../hooks/EntrysDataHook';
+
+const Entry = () => {
+ const [validated, setValidated] = useState(false);
+ const [login, setLogin] = useState('');
+ const [password, setPassword] = useState('');
+ const isLoginValid = (value) => /^[a-zA-Z]+$/.test(value);
+ const { entrys } = useEntrysData(login, password);
+
+ const handleSubmit = (event) => {
+ const form = event.currentTarget;
+ event.preventDefault();
+ event.stopPropagation();
+ if (form.checkValidity() !== false) {
+ if (isLoginValid(login)) {
+ if (entrys.length === 0) {
+ toast.error('Аккаунт не найден');
+ } else {
+ setValidated(true);
+ toast.success('Был произведён вход');
+ }
+ } else {
+ toast.error('Логин должен быть введён латинскими символами');
+ }
+ }
+ setValidated(true);
+ };
+
+ return (
+
+
+ Личный кабинет
+
+
+
+ Вход
+
+
+
+
+ );
+};
+
+export default Entry;
diff --git a/lab5/src/components/logins/login/Entry/Entry.jsx b/lab5/src/components/logins/login/Entry/Entry.jsx
new file mode 100644
index 0000000..32e7cbc
--- /dev/null
+++ b/lab5/src/components/logins/login/Entry/Entry.jsx
@@ -0,0 +1,87 @@
+import { useContext, useState } from 'react';
+import PropTypes from 'prop-types';
+import { Link } from 'react-router-dom';
+import toast from 'react-hot-toast';
+import { Button, Form } from 'react-bootstrap';
+import Input from '../../../input/Input.jsx';
+import useEntrysData from '../../hooks/EntrysDataHook';
+import { AuthContext } from '../context/AuthContext.jsx';
+
+const Entry = () => {
+ const [validated, setValidated] = useState(false);
+ const [login, setLogin] = useState('');
+ const [password, setPassword] = useState('');
+ const isLoginValid = (value) => /^[a-zA-Z0-9]+$/.test(value);
+ const { entrys } = useEntrysData(login, password, `?login=${login}&password=${password}`);
+ const { state, dispatch } = useContext(AuthContext);
+
+ const handleSubmit = (event) => {
+ const form = event.currentTarget;
+ event.preventDefault();
+ event.stopPropagation();
+ if (form.checkValidity() !== false) {
+ if (isLoginValid(login)) {
+ if (entrys.length === 0) {
+ toast.error('Аккаунт не найден');
+ } else {
+ setValidated(true);
+ dispatch({
+ type: 'LOGIN',
+ payload: entrys,
+ });
+ toast.success(`Был произведён вход: ${login}`);
+ }
+ } else {
+ toast.error('Логин должен быть введён латинскими символами');
+ }
+ }
+ setValidated(true);
+ };
+
+ const handleLogOut = () => {
+ dispatch({
+ type: 'LOGOUT',
+ payload: entrys,
+ });
+ };
+
+ return (
+
+
+ Личный кабинет
+
+
+ {state.user === null ? (
+ <>
+
+ Вход
+
+
+ >
+ ) : (
+ <>
+
Welcome, {state.user.map((item) => item.login)}
+
+ >
+ )}
+
+
+ );
+};
+
+Entry.propTypes = {
+ item: PropTypes.object,
+ };
+
+export default Entry;
diff --git a/lab5/src/components/logins/login/Registration.jsx b/lab5/src/components/logins/login/Registration.jsx
new file mode 100644
index 0000000..08e1c21
--- /dev/null
+++ b/lab5/src/components/logins/login/Registration.jsx
@@ -0,0 +1,73 @@
+import { useState } from 'react';
+import { Link } from 'react-router-dom';
+import toast from 'react-hot-toast';
+import { Button, Form } from 'react-bootstrap';
+import Input from '../../input/Input.jsx';
+import useEntrysData from '../hooks/EntrysDataHook';
+import useEntrysItemForm from '../hooks/EntrysDataItemHook';
+
+const Entry = () => {
+ const [validated, setValidated] = useState(false);
+ const [login, setLogin] = useState('');
+ const [password, setPassword] = useState('');
+ const isLoginValid = (value) => /^[a-zA-Z0-9]+$/.test(value);
+ const { entrys } = useEntrysData(login, password, `?login=${login}`);
+
+ const { UseHandleSubmit, UseHandleChange } = useEntrysItemForm();
+
+ const handleSubmit = (event) => {
+ const form = event.currentTarget;
+ event.preventDefault();
+ event.stopPropagation();
+ if (form.checkValidity() !== false) {
+ if (isLoginValid(login)) {
+ const isLoginExists = entrys.some((item) => item.login === login);
+ if (isLoginExists) {
+ toast.error('Такой аккаунт уже создан');
+ } else {
+ UseHandleSubmit(event);
+ toast.success('Ваш аккаунт успешно создан');
+ }
+ } else {
+ toast.error('Логин должен быть введён латинскими символами');
+ return;
+ }
+ }
+ setValidated(true);
+ };
+
+ const handleChangeLogin = (event) => {
+ setLogin(event.target.value);
+ UseHandleChange(event);
+ };
+
+ const handleChangePassword = (event) => {
+ setPassword(event.target.value);
+ UseHandleChange(event);
+ };
+
+ return (
+
+
+ Личный кабинет
+
+
+
+ Регистрация
+
+
+
+
+ );
+};
+
+export default Entry;
diff --git a/lab5/src/components/logins/login/context/AuthContext.jsx b/lab5/src/components/logins/login/context/AuthContext.jsx
new file mode 100644
index 0000000..cc6712e
--- /dev/null
+++ b/lab5/src/components/logins/login/context/AuthContext.jsx
@@ -0,0 +1,66 @@
+import { createContext, useReducer, useEffect } from 'react';
+import PropTypes from 'prop-types';
+
+// Функция для сохранения состояния user в localStorage
+const saveToLocalstorage = (user) => {
+ if (user) {
+ localStorage.setItem('authState', JSON.stringify(user));
+ } else {
+ localStorage.removeItem('authState');
+ }
+};
+
+// Функция для восстановления состояния user из localStorage
+const getInitialState = () => {
+ const userStorage = localStorage.getItem('authState');
+ if (userStorage) {
+ return { user: JSON.parse(userStorage) };
+ }
+ return { user: null };
+};
+
+const AuthReducer = (state, action) => {
+ switch (action.type) {
+ case 'LOGIN':
+ saveToLocalstorage(action.payload);
+ return {
+ ...state,
+ user: action.payload,
+ };
+ case 'LOGOUT':
+ saveToLocalstorage(null);
+ return {
+ ...state,
+ user: null,
+ };
+ default:
+ return state;
+ }
+};
+
+export const AuthContext = createContext();
+
+export const AuthProvider = ({ children }) => {
+ const [state, dispatch] = useReducer(AuthReducer, getInitialState, getInitialState);
+
+ // При инициализации компонента проверим localStorage
+ useEffect(() => {
+ const user = localStorage.getItem('authState');
+ if (user) {
+ dispatch({
+ type: 'LOGIN',
+ payload: JSON.parse(user),
+ });
+ }
+ }, []);
+
+ return (
+
+ {children}
+
+ );
+};
+
+AuthProvider.propTypes = {
+ children: PropTypes.node.isRequired,
+};
diff --git a/lab5/src/components/logins/service/EntrysDataApiService.js b/lab5/src/components/logins/service/EntrysDataApiService.js
new file mode 100644
index 0000000..2d8db73
--- /dev/null
+++ b/lab5/src/components/logins/service/EntrysDataApiService.js
@@ -0,0 +1,5 @@
+import ApiService from '../../api/ApiService';
+
+const EntrysDataApiService = new ApiService('entrysData');
+
+export default EntrysDataApiService;
diff --git a/lab5/src/components/searching/search/Searching.jsx b/lab5/src/components/searching/search/Searching.jsx
index ae3a4fe..6eef8b6 100644
--- a/lab5/src/components/searching/search/Searching.jsx
+++ b/lab5/src/components/searching/search/Searching.jsx
@@ -3,13 +3,13 @@ import TableDirect from './TableDirect.jsx';
import Search from './Search.jsx';
import useSearching from '../hooks/SearchHooks.js';
import Input from '../../input/Input.jsx';
-import useTypeFilter from '../../lines/hooks/LinesFilterHook.js';
+// import useTypeFilter from '../../lines/hooks/LinesFilterHook.js';
const Searching = () => {
- const { type, currentFilter } = useTypeFilter;
+ // const { type, currentFilter } = useTypeFilter;
const { searching } = useSearching();
const [searchValue, setSearchValue] = useState('');
- const {lines} =useLines(currentFilter);
+ // const {lines} =useLines(currentFilter);
return (
<>
diff --git a/lab5/src/components/sidebar/Sidebar.css b/lab5/src/components/sidebar/Sidebar.css
index cb42c87..2a93af0 100644
--- a/lab5/src/components/sidebar/Sidebar.css
+++ b/lab5/src/components/sidebar/Sidebar.css
@@ -50,7 +50,7 @@ h4 {
height: 500px;
}*/
/* .container-fluid{
- height: 100vh;
+ height: 100%;
}
.full-page-div {
width: 100%;
@@ -109,24 +109,10 @@ font-size: 13px;
}
-/* .sidebar {
+.sidebar {
background-color: #f8f9fa;
height: 100vh;
-} */
-.video-thumbnail {
-/* width: 1920px;
-height: 1080px; */
-max-width: 100%;
-max-height: 100%;
-width: 100%;
-height: 100%;
}
-.embed-responsive{
-max-width: 100%;
-max-height: 100%;
-width: 1600px;
-height: 800px;
-}
img,
svg {
diff --git a/lab5/src/components/sidebar/Sidebar.jsx b/lab5/src/components/sidebar/Sidebar.jsx
index cd4e076..ecf2c3f 100644
--- a/lab5/src/components/sidebar/Sidebar.jsx
+++ b/lab5/src/components/sidebar/Sidebar.jsx
@@ -1,8 +1,9 @@
// import React from 'react';
-import './Sidebar.css';
+import '../sidebar/Sidebar.css';
const Sidebar = () => {
return (
+
@@ -78,6 +79,7 @@ const Sidebar = () => {
+
);
};
diff --git a/lab5/src/components/types/hooks/TypesHook.js b/lab5/src/components/types/hooks/TypesHook.js
index 35f605e..79b10e3 100644
--- a/lab5/src/components/types/hooks/TypesHook.js
+++ b/lab5/src/components/types/hooks/TypesHook.js
@@ -12,7 +12,6 @@ const useTypes = () => {
useEffect(() => {
getTypes();
}, []);
-
return {
types,
};
diff --git a/lab5/src/pages/AdminPage.jsx b/lab5/src/pages/AdminPage.jsx
index a64e187..cc343a4 100644
--- a/lab5/src/pages/AdminPage.jsx
+++ b/lab5/src/pages/AdminPage.jsx
@@ -1,3 +1,4 @@
+import Entry from '../components/logins/login/Entry/Entry.jsx';
const AdminPage = () => {
@@ -15,6 +16,7 @@ const AdminPage = () => {
<>
+