From 62695acf74f853433d2d6707f74c8d6b43572835 Mon Sep 17 00:00:00 2001 From: cracklesparkle Date: Mon, 24 Jun 2024 17:06:41 +0900 Subject: [PATCH] Auth: SignIn, SignUp (TODO: rewrite into react-hook-form) --- frontend_reactjs/package-lock.json | 41 ++++++- frontend_reactjs/package.json | 3 +- frontend_reactjs/src/App.tsx | 63 +++++++---- frontend_reactjs/src/components/DataTable.tsx | 24 ++++ .../src/components/FetchingData.ts | 5 +- frontend_reactjs/src/components/UserData.ts | 19 ++++ frontend_reactjs/src/http/axiosInstance.ts | 21 ++++ .../src/layouts/DashboardLayout.tsx | 35 +++++- frontend_reactjs/src/main.tsx | 16 ++- frontend_reactjs/src/pages/ApiTest.tsx | 35 ++++-- frontend_reactjs/src/pages/Roles.tsx | 34 +++++- frontend_reactjs/src/pages/Users.tsx | 57 +++++++--- frontend_reactjs/src/pages/auth/SignIn.tsx | 102 ++++++++++++++++- frontend_reactjs/src/pages/auth/SignUp.tsx | 105 ++++++++++++++++++ frontend_reactjs/src/services/AuthService.ts | 9 ++ frontend_reactjs/src/services/RoleService.ts | 11 ++ frontend_reactjs/src/store/auth.ts | 50 +++++++++ .../src/store/{auth-store.ts => user.ts} | 0 frontend_reactjs/src/types/auth.ts | 25 +++++ frontend_reactjs/yarn.lock | 33 ++++-- 20 files changed, 617 insertions(+), 71 deletions(-) create mode 100644 frontend_reactjs/src/components/DataTable.tsx create mode 100644 frontend_reactjs/src/components/UserData.ts create mode 100644 frontend_reactjs/src/http/axiosInstance.ts create mode 100644 frontend_reactjs/src/services/RoleService.ts create mode 100644 frontend_reactjs/src/store/auth.ts rename frontend_reactjs/src/store/{auth-store.ts => user.ts} (100%) create mode 100644 frontend_reactjs/src/types/auth.ts diff --git a/frontend_reactjs/package-lock.json b/frontend_reactjs/package-lock.json index 81d1a46..9847a4a 100644 --- a/frontend_reactjs/package-lock.json +++ b/frontend_reactjs/package-lock.json @@ -13,12 +13,13 @@ "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.15.20", "@mui/material": "^5.15.20", + "@mui/x-data-grid": "^7.7.1", "autoprefixer": "^10.4.19", "axios": "^1.7.2", "postcss": "^8.4.38", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-hook-form": "^7.51.5", + "react-hook-form": "^7.52.0", "react-router-dom": "^6.23.1", "zod": "^3.23.8", "zustand": "^4.5.2" @@ -2885,6 +2886,31 @@ } } }, + "node_modules/@mui/x-data-grid": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.7.1.tgz", + "integrity": "sha512-5XsvuVpJfjV2ERtNiVRWL+0UUq5rh2Tq8aLZdJ8Ca5PnweEfNzOesQMlf0lpjXqnzuoq7uTwvICqoAMjsTTglg==", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@mui/system": "^5.15.20", + "@mui/utils": "^5.15.20", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "reselect": "^4.1.8" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.15.14", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6753,9 +6779,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.51.5", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz", - "integrity": "sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q==", + "version": "7.52.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.0.tgz", + "integrity": "sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==", "engines": { "node": ">=12.22.0" }, @@ -6764,7 +6790,7 @@ "url": "https://opencollective.com/react-hook-form" }, "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18" + "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "node_modules/react-is": { @@ -6935,6 +6961,11 @@ "node": ">=0.10.0" } }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", diff --git a/frontend_reactjs/package.json b/frontend_reactjs/package.json index 0a4684f..382f586 100644 --- a/frontend_reactjs/package.json +++ b/frontend_reactjs/package.json @@ -15,12 +15,13 @@ "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.15.20", "@mui/material": "^5.15.20", + "@mui/x-data-grid": "^7.7.1", "autoprefixer": "^10.4.19", "axios": "^1.7.2", "postcss": "^8.4.38", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-hook-form": "^7.51.5", + "react-hook-form": "^7.52.0", "react-router-dom": "^6.23.1", "zod": "^3.23.8", "zustand": "^4.5.2" diff --git a/frontend_reactjs/src/App.tsx b/frontend_reactjs/src/App.tsx index 72a2a12..5958b75 100644 --- a/frontend_reactjs/src/App.tsx +++ b/frontend_reactjs/src/App.tsx @@ -1,4 +1,4 @@ -import { BrowserRouter as Router, Route, Routes } from "react-router-dom" +import { BrowserRouter as Router, Route, Routes, Navigate, redirect } from "react-router-dom" import Main from "./pages/Main" import Users from "./pages/Users" import Roles from "./pages/Roles" @@ -7,27 +7,52 @@ import DashboardLayout from "./layouts/DashboardLayout" import MainLayout from "./layouts/MainLayout" import SignIn from "./pages/auth/SignIn" import ApiTest from "./pages/ApiTest" +import SignUp from "./pages/auth/SignUp" +import { useAuthStore } from "./store/auth" +import { useEffect, useState } from "react" +import { CircularProgress } from "@mui/material" function App() { - return ( - <> - - - }> - }/> - + const auth = useAuthStore() + const [isLoading, setIsLoading] = useState(true) - }> - } /> - } /> - } /> - } /> - } /> - - - - - ) + useEffect(() => { + auth.initializeAuth() + }, []) + + // Once auth is there, set loading to false and render the app + useEffect(() => { + if (auth) { + setIsLoading(false) + } + }, [auth]) + + if (isLoading) { + return ( + + ) + } else { + return ( + <> + + + }> + } /> + } /> + + + : }> + } /> + } /> + } /> + } /> + } /> + + + + + ) + } } export default App \ No newline at end of file diff --git a/frontend_reactjs/src/components/DataTable.tsx b/frontend_reactjs/src/components/DataTable.tsx new file mode 100644 index 0000000..c32b05e --- /dev/null +++ b/frontend_reactjs/src/components/DataTable.tsx @@ -0,0 +1,24 @@ +import { DataGrid } from '@mui/x-data-grid'; + +interface Props { + rows: any, + columns: any +} + +export default function DataTable(props: Props) { + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/frontend_reactjs/src/components/FetchingData.ts b/frontend_reactjs/src/components/FetchingData.ts index fdaf04e..cf9c3ed 100644 --- a/frontend_reactjs/src/components/FetchingData.ts +++ b/frontend_reactjs/src/components/FetchingData.ts @@ -1,11 +1,12 @@ import { useState, useEffect, useMemo } from 'react'; +import axiosInstance from '../http/axiosInstance'; export function useDataFetching(url: string, initData: T): T { const [data, setData] = useState(initData); useEffect(() => { const fetchData = async () => { - const response = await fetch(url); - const result = await response.json(); + const response = await axiosInstance.get(url); + const result = await response.data; setData(result); }; diff --git a/frontend_reactjs/src/components/UserData.ts b/frontend_reactjs/src/components/UserData.ts new file mode 100644 index 0000000..a83ff95 --- /dev/null +++ b/frontend_reactjs/src/components/UserData.ts @@ -0,0 +1,19 @@ +import { memo, useEffect, useMemo, useState } from "react"; +import UserService from "../services/UserService"; +import AuthService from "../services/AuthService"; + +export default function useUserData(token: string, initData: T): T { + const [userData, setUserData] = useState(initData) + + useEffect(()=> { + const fetchUserData = async (token: string) => { + const response = await AuthService.getCurrentUser(token) + setUserData(response.data) + } + + fetchUserData(token) + }, [token]) + + const memoizedData = useMemo(() => userData, [userData]) + return memoizedData +} \ No newline at end of file diff --git a/frontend_reactjs/src/http/axiosInstance.ts b/frontend_reactjs/src/http/axiosInstance.ts new file mode 100644 index 0000000..671dee2 --- /dev/null +++ b/frontend_reactjs/src/http/axiosInstance.ts @@ -0,0 +1,21 @@ +import axios from 'axios'; +import { useAuthStore } from '../store/auth'; + +const axiosInstance = axios.create({ + baseURL: `${import.meta.env.VITE_API_AUTH_URL}`, +}); + +axiosInstance.interceptors.request.use( + (config) => { + const token = useAuthStore.getState().token; + if (token) { + config.headers['Authorization'] = `Bearer ${token}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +export default axiosInstance; diff --git a/frontend_reactjs/src/layouts/DashboardLayout.tsx b/frontend_reactjs/src/layouts/DashboardLayout.tsx index d3c9923..0bb7296 100644 --- a/frontend_reactjs/src/layouts/DashboardLayout.tsx +++ b/frontend_reactjs/src/layouts/DashboardLayout.tsx @@ -1,6 +1,6 @@ // Layout for dashboard with responsive drawer -import { Outlet } from "react-router-dom" +import { Navigate, Outlet } from "react-router-dom" import * as React from 'react'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; @@ -17,10 +17,14 @@ import MenuIcon from '@mui/icons-material/Menu'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import { Api, ExitToApp, Home, People, Settings, Shield } from "@mui/icons-material"; +import { UserData, useAuthStore } from "../store/auth"; const drawerWidth = 240; export default function DashboardLayout() { + const authStore = useAuthStore(); + const [userData, setUserData] = React.useState(); + //const { window } = props; const [mobileOpen, setMobileOpen] = React.useState(false); const [isClosing, setIsClosing] = React.useState(false); @@ -78,7 +82,13 @@ export default function DashboardLayout() { const drawer = (
- + + + {userData?.name} {userData?.surname} + + {userData?.login} + + @@ -112,8 +122,21 @@ export default function DashboardLayout() {
); + React.useEffect(() => { + if (authStore) { + const stored = authStore.getUserData() + if (stored) { + setUserData(stored) + } + } + }, [authStore]) + return ( - + diff --git a/frontend_reactjs/src/main.tsx b/frontend_reactjs/src/main.tsx index 8782212..d66dc94 100644 --- a/frontend_reactjs/src/main.tsx +++ b/frontend_reactjs/src/main.tsx @@ -3,6 +3,18 @@ import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' import { registerSW } from 'virtual:pwa-register' +import { ThemeProvider } from '@emotion/react' +import { createTheme } from '@mui/material' +import { ruRU } from '@mui/material/locale' + +const theme = createTheme( + { + palette: { + primary: { main: '#1976d2' }, + }, + }, + ruRU, +); const updateSW = registerSW({ onNeedRefresh() { @@ -17,6 +29,8 @@ const updateSW = registerSW({ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - + + + , ) diff --git a/frontend_reactjs/src/pages/ApiTest.tsx b/frontend_reactjs/src/pages/ApiTest.tsx index 7ece3fc..10a1f6a 100644 --- a/frontend_reactjs/src/pages/ApiTest.tsx +++ b/frontend_reactjs/src/pages/ApiTest.tsx @@ -2,22 +2,43 @@ import { useEffect, useState } from "react" import UserService from "../services/UserService" import AuthService from "../services/AuthService" import { Button } from "@mui/material" +import DataTable from "../components/DataTable" +import { GridColDef } from "@mui/x-data-grid" export default function ApiTest() { - const [temp, setTemp] = useState(null) + const [users, setUsers] = useState(null) - const hello = async () => { - await AuthService.hello().then(response => { - setTemp(response) + const getUsers = async () => { + await AuthService.getUsers().then(response => { + setUsers(response.data) }) } + const columns: GridColDef[] = [ + { field: 'id', headerName: 'ID', type: "number", width: 70 }, + { field: 'email', headerName: 'Email', width: 130 }, + { field: 'login', headerName: 'Логин', width: 130 }, + { field: 'phone', headerName: 'Телефон', width: 90 }, + { field: 'name', headerName: 'Имя', width: 90 }, + { field: 'surname', headerName: 'Фамилия', width: 90 }, + { field: 'is_active', headerName: 'Активен', type: "boolean", width: 90 }, + { + field: 'role_id', + headerName: 'Роль', + valueGetter: (value, row) => `${value}`, + width: 90 + }, + ]; + return ( <> -
{JSON.stringify(temp)}
- + + {users && + + } ) } \ No newline at end of file diff --git a/frontend_reactjs/src/pages/Roles.tsx b/frontend_reactjs/src/pages/Roles.tsx index 9306c1a..3c38e04 100644 --- a/frontend_reactjs/src/pages/Roles.tsx +++ b/frontend_reactjs/src/pages/Roles.tsx @@ -2,6 +2,10 @@ import { useState } from 'react' import RoleCard from '../components/RoleCard' import Modal from '../components/Modal' import useDataFetching from '../components/FetchingData' +import RoleService from '../services/RoleService' +import { Box, Button } from '@mui/material' +import DataTable from '../components/DataTable' +import { GridColDef } from '@mui/x-data-grid' interface IRoleCard { id: number @@ -11,12 +15,38 @@ interface Props { showModal: boolean; } function Roles() { + const [roles, setRoles] = useState(null) + + const getRoles = async () => { + await RoleService.getRoles().then(response => { + setRoles(response.data) + }) + } + const [showModal, setShowModal] = useState({ showModal: false }); - const cards = useDataFetching(`${import.meta.env.VITE_API_URL}/auth/role/`, []) + const cards = useDataFetching(`${import.meta.env.VITE_API_AUTH_URL}/auth/roles/`, []) + + const columns: GridColDef[] = [ + { field: 'id', headerName: 'ID', type: "number", width: 70 }, + { field: 'name', headerName: 'Название', width: 90 }, + { field: 'description', headerName: 'Описание', width: 90 }, + ]; + + return ( + + + + {roles && + + } + + ) return (
- {cards.map((card, index) => )} + {cards.length > 0 && cards.map((card, index) => )}
diff --git a/frontend_reactjs/src/pages/Users.tsx b/frontend_reactjs/src/pages/Users.tsx index 5da4091..ae3dee5 100644 --- a/frontend_reactjs/src/pages/Users.tsx +++ b/frontend_reactjs/src/pages/Users.tsx @@ -1,18 +1,43 @@ -import Card from '../components/Card' -import useDataFetching from '../components/FetchingData' -interface ICard { - firstname: string - lastname: string - email: string -} +import { useEffect, useState } from "react" +import AuthService from "../services/AuthService" +import { Box, Button } from "@mui/material" +import DataTable from "../components/DataTable" +import { GridColDef } from "@mui/x-data-grid" -function Users() { - const cards = useDataFetching(`${import.meta.env.VITE_API_URL}/auth/user/`, []) - return ( -
- {cards.map((card, index) => )} -
- ) -} +export default function Users() { + const [users, setUsers] = useState(null) -export default Users \ No newline at end of file + const getUsers = async () => { + await AuthService.getUsers().then(response => { + setUsers(response.data) + }) + } + + const columns: GridColDef[] = [ + { field: 'id', headerName: 'ID', type: "number", width: 70 }, + { field: 'email', headerName: 'Email', width: 130 }, + { field: 'login', headerName: 'Логин', width: 130 }, + { field: 'phone', headerName: 'Телефон', width: 90 }, + { field: 'name', headerName: 'Имя', width: 90 }, + { field: 'surname', headerName: 'Фамилия', width: 90 }, + { field: 'is_active', headerName: 'Активен', type: "boolean", width: 90 }, + { + field: 'role_id', + headerName: 'Роль', + valueGetter: (value, row) => `${value}`, + width: 90 + }, + ]; + + return ( + + + + {users && + + } + + ) +} \ No newline at end of file diff --git a/frontend_reactjs/src/pages/auth/SignIn.tsx b/frontend_reactjs/src/pages/auth/SignIn.tsx index be5a893..861fbcc 100644 --- a/frontend_reactjs/src/pages/auth/SignIn.tsx +++ b/frontend_reactjs/src/pages/auth/SignIn.tsx @@ -1,9 +1,99 @@ -import React from 'react' +import React, { useState, ChangeEvent, FormEvent } from 'react'; +import { TextField, Button, Container, Typography, Box } from '@mui/material'; +import axios, { AxiosResponse } from 'axios'; +import { SignInFormData, ApiResponse } from '../../types/auth'; +import { UserData, useAuthStore } from '../../store/auth'; +import { useNavigate } from 'react-router-dom'; +import axiosInstance from '../../http/axiosInstance'; +import AuthService from '../../services/AuthService'; const SignIn = () => { - return ( -
SignIn
- ) -} + const [formData, setFormData] = useState({ + username: '', + password: '', + grant_type: 'password', + scope: '', + client_id: '', + client_secret: '' + }); -export default SignIn \ No newline at end of file + const authStore = useAuthStore(); + + const navigate = useNavigate(); + + const handleChange = (e: ChangeEvent) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value, + }); + }; + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + const formBody = new URLSearchParams(); + for (const key in formData) { + formBody.append(key, formData[key as keyof SignInFormData] as string); + } + + try { + const response: AxiosResponse = await axiosInstance.post(`/auth/login`, formBody, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }); + console.log('Вход произошел успешно:', response.data); + const token = response.data.access_token + + const userDataResponse: AxiosResponse = await AuthService.getCurrentUser(token) + + console.log('Пользователь:', userDataResponse.data) + + authStore.setUserData(JSON.stringify(userDataResponse.data)) + + authStore.login(token) + + navigate('/'); + } catch (error) { + console.error('Ошибка при входе:', error); + } + }; + + return ( + + + + Вход + +
+ + + + + +
+
+ ); +}; + +export default SignIn; \ No newline at end of file diff --git a/frontend_reactjs/src/pages/auth/SignUp.tsx b/frontend_reactjs/src/pages/auth/SignUp.tsx index e69de29..3b881a4 100644 --- a/frontend_reactjs/src/pages/auth/SignUp.tsx +++ b/frontend_reactjs/src/pages/auth/SignUp.tsx @@ -0,0 +1,105 @@ +// src/components/SignUp.tsx + +import React, { useState, ChangeEvent, FormEvent } from 'react'; +import { TextField, Button, Container, Typography, Box } from '@mui/material'; +import axios, { AxiosResponse } from 'axios'; +import { SignUpFormData, ApiResponse } from '../../types/auth'; +import axiosInstance from '../../http/axiosInstance'; + +const SignUp: React.FC = () => { + const [formData, setFormData] = useState({ + email: '', + login: '', + phone: '', + name: '', + surname: '', + is_active: true, + password: '', + }); + + const handleChange = (e: ChangeEvent) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value, + }); + }; + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + try { + const response: AxiosResponse = await axiosInstance.post(`${import.meta.env.VITE_API_AUTH_URL}/auth/user`, formData); + console.log('Успешная регистрация:', response.data); + } catch (error) { + console.error('Ошибка регистрации:', error); + } + }; + + return ( + + + + Регистрация + +
+ + + + + + + + +
+
+ ); +}; + +export default SignUp; \ No newline at end of file diff --git a/frontend_reactjs/src/services/AuthService.ts b/frontend_reactjs/src/services/AuthService.ts index 9a0a79b..1c38b3c 100644 --- a/frontend_reactjs/src/services/AuthService.ts +++ b/frontend_reactjs/src/services/AuthService.ts @@ -1,7 +1,16 @@ import axios from "axios"; +import axiosInstance from "../http/axiosInstance"; export default class AuthService { static async hello() { return await axios.get(`${import.meta.env.VITE_API_AUTH_URL}/hello`) } + + static async getUsers() { + return await axiosInstance.get(`/auth/user`) + } + + static async getCurrentUser(token: string){ + return await axiosInstance.get(`/auth/get_current_user/${token}`) + } } \ No newline at end of file diff --git a/frontend_reactjs/src/services/RoleService.ts b/frontend_reactjs/src/services/RoleService.ts new file mode 100644 index 0000000..0dc0bc4 --- /dev/null +++ b/frontend_reactjs/src/services/RoleService.ts @@ -0,0 +1,11 @@ +import axiosInstance from "../http/axiosInstance"; + +export default class RoleService { + static async getRoles() { + return await axiosInstance.get(`/auth/roles`) + } + + static async getRoleById(id: number) { + return await axiosInstance.get(`/auth/roles/${id}`) + } +} \ No newline at end of file diff --git a/frontend_reactjs/src/store/auth.ts b/frontend_reactjs/src/store/auth.ts new file mode 100644 index 0000000..9086e14 --- /dev/null +++ b/frontend_reactjs/src/store/auth.ts @@ -0,0 +1,50 @@ +import { create } from 'zustand'; + +export interface UserData { + id: number; + email: string; + login: string; + phone: string; + name: string; + surname: string; + is_active: boolean; + role_id: number; +} + +interface AuthState { + isAuthenticated: boolean; + token: string | null; + login: (token: string) => void; + logout: () => void; + initializeAuth: () => void; + userData: UserData | {}; + getUserData: () => UserData; + setUserData: (userData: string) => void; +} + +export const useAuthStore = create((set) => ({ + isAuthenticated: false, + token: null, + login: (token: string) => { + localStorage.setItem('authToken', token); + set({ isAuthenticated: true, token }); + }, + logout: () => { + localStorage.removeItem('authToken'); + set({ isAuthenticated: false, token: null }); + }, + initializeAuth: () => { + const token = localStorage.getItem('authToken'); + if (token) { + set({ isAuthenticated: true, token }); + } + }, + userData: {}, + setUserData: (userData: string) => { + localStorage.setItem('userData', userData) + }, + getUserData: () => { + const userData = localStorage.getItem('userData') + return JSON.parse(userData || "") + } +})); \ No newline at end of file diff --git a/frontend_reactjs/src/store/auth-store.ts b/frontend_reactjs/src/store/user.ts similarity index 100% rename from frontend_reactjs/src/store/auth-store.ts rename to frontend_reactjs/src/store/user.ts diff --git a/frontend_reactjs/src/types/auth.ts b/frontend_reactjs/src/types/auth.ts new file mode 100644 index 0000000..ac1bb4a --- /dev/null +++ b/frontend_reactjs/src/types/auth.ts @@ -0,0 +1,25 @@ +export interface SignUpFormData { + email: string; + login: string; + phone: string; + name: string; + surname: string; + is_active: boolean; + password: string; +} + +export interface SignInFormData { + username: string; + password: string; + grant_type: string; + scope?: string; + client_id?: string; + client_secret?: string; +} + +export interface ApiResponse { + access_token: any; + data: any; + status: number; + statusText: string; +} \ No newline at end of file diff --git a/frontend_reactjs/yarn.lock b/frontend_reactjs/yarn.lock index 9b1ec41..9b263b4 100644 --- a/frontend_reactjs/yarn.lock +++ b/frontend_reactjs/yarn.lock @@ -936,7 +936,7 @@ resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.24.7" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== @@ -1244,7 +1244,7 @@ dependencies: "@babel/runtime" "^7.23.9" -"@mui/material@^5.0.0", "@mui/material@^5.15.20": +"@mui/material@^5.0.0", "@mui/material@^5.15.14", "@mui/material@^5.15.20": version "5.15.20" resolved "https://registry.npmjs.org/@mui/material/-/material-5.15.20.tgz" integrity sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg== @@ -1310,6 +1310,18 @@ prop-types "^15.8.1" react-is "^18.2.0" +"@mui/x-data-grid@^7.7.1": + version "7.7.1" + resolved "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.7.1.tgz" + integrity sha512-5XsvuVpJfjV2ERtNiVRWL+0UUq5rh2Tq8aLZdJ8Ca5PnweEfNzOesQMlf0lpjXqnzuoq7uTwvICqoAMjsTTglg== + dependencies: + "@babel/runtime" "^7.24.7" + "@mui/system" "^5.15.20" + "@mui/utils" "^5.15.20" + clsx "^2.1.1" + prop-types "^15.8.1" + reselect "^4.1.8" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -1892,7 +1904,7 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -clsx@^2.1.0: +clsx@^2.1.0, clsx@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== @@ -3459,10 +3471,10 @@ randombytes@^2.1.0: loose-envify "^1.1.0" scheduler "^0.23.2" -react-hook-form@^7.51.5: - version "7.51.5" - resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz" - integrity sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q== +react-hook-form@^7.52.0: + version "7.52.0" + resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.0.tgz" + integrity sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A== react-is@^16.13.1: version "16.13.1" @@ -3504,7 +3516,7 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" -"react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.2.0, react@^18.3.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0: +"react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.2.0, react@^18.3.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0: version "18.3.1" resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== @@ -3583,6 +3595,11 @@ require-from-string@^2.0.2: resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +reselect@^4.1.8: + version "4.1.8" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"