сделал заготовку под навигацию

This commit is contained in:
Андрей Дувакин 2025-02-07 19:55:19 +05:00
parent 8e85ea7b23
commit df5809232b
9 changed files with 110 additions and 31 deletions

View File

@ -1,7 +1,7 @@
from pydantic import BaseModel, Field
from pydantic import BaseModel
class AuthEntity(BaseModel):
login: str = Field(..., example='user@example.com')
password: str = Field(..., min_length=5, example='strongpassword')
login: str
password: str

View File

@ -4,9 +4,9 @@ from pydantic import BaseModel, Field
class RegisterEntity(BaseModel):
first_name: str = Field(..., example='Ivan')
last_name: str = Field(..., example='Ivanov')
patronymic: Optional[str] = Field(None, example='Ivanov')
role_id: int = Field(..., example=1)
login: str = Field(..., example='user@example.com')
password: str = Field(..., min_length=5, example='strongpassword')
first_name: str
last_name: str
patronymic: Optional[str]
role_id: int
login: str
password: str

View File

@ -4,11 +4,10 @@ from pydantic import BaseModel, Field
class UserEntity(BaseModel):
id: int = Field(..., example=1)
first_name: str = Field(..., example='Ivan')
last_name: str = Field(..., example='Ivanov')
patronymic: Optional[str] = Field(None, example='Ivanov')
login: str = Field(..., example='ivanov74')
role_id: int = Field(..., example=1)
id: int
first_name: str
last_name: str
patronymic: Optional[str]
login: str
role_id: int

View File

@ -8,6 +8,7 @@
"name": "web-app",
"version": "0.0.0",
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@react-buddy/ide-toolbox": "^2.4.0",
"@react-buddy/palette-antd": "^5.3.0",
"antd": "^5.23.1",
@ -86,9 +87,9 @@
}
},
"node_modules/@ant-design/icons": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.5.2.tgz",
"integrity": "sha512-xc53rjVBl9v2BqFxUjZGti/RfdDeA8/6KYglmInM2PNqSXc/WfuGDTifJI/ZsokJK0aeKvOIbXc9y2g8ILAhEA==",
"version": "5.6.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz",
"integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^7.0.0",

View File

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@react-buddy/ide-toolbox": "^2.4.0",
"@react-buddy/palette-antd": "^5.3.0",
"antd": "^5.23.1",

View File

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/favicon-70x70.png"/>
<square150x150logo src="/favicon-150x150.png"/>
<square310x310logo src="/favicon-310x310.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
<msapplication>
<tile>
<square70x70logo src="/favicon-70x70.png"/>
<square150x150logo src="/favicon-150x150.png"/>
<square310x310logo src="/favicon-310x310.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -1,6 +1,7 @@
import {Routes, Route} from "react-router-dom";
import PrivateRoute from "./components/PrivateRoute.jsx";
import LoginPage from "./pages/LoginPage.jsx";
import MainLayout from "./layouts/MainLayout.jsx";
const AppRouter = () => (
@ -8,7 +9,9 @@ const AppRouter = () => (
<Route path="/login" element={<LoginPage/>}/>
<Route element={<PrivateRoute/>}>
<Route path={"/"} element={<p>1234</p>}/>
<Route element={<MainLayout/>}>
<Route path={"/"} element={<p>1234</p>}/>
</Route>
</Route>
</Routes>
)

View File

@ -0,0 +1,66 @@
import {useState} from "react";
import {Layout, Menu} from "antd";
import {Outlet, useLocation, useNavigate} from "react-router-dom";
import {
DesktopOutlined,
FileOutlined,
PieChartOutlined,
TeamOutlined,
UserOutlined,
} from "@ant-design/icons";
const {Content, Footer, Sider} = Layout;
const getItem = (label, key, icon, children) => ({
key,
icon,
children,
label,
});
const items = [
getItem("Главная", "/", <PieChartOutlined/>),
getItem("Настройки", "/settings", <DesktopOutlined/>),
getItem("Пользователи", "sub1", <UserOutlined/>, [
getItem("Том", "/users/tom"),
getItem("Билл", "/users/bill"),
getItem("Алекс", "/users/alex"),
]),
getItem("Команда", "sub2", <TeamOutlined/>, [
getItem("Команда 1", "/team/1"),
getItem("Команда 2", "/team/2"),
]),
getItem("Файлы", "/files", <FileOutlined/>),
];
const MainLayout = () => {
const [collapsed, setCollapsed] = useState(false);
const navigate = useNavigate();
const location = useLocation();
return (
<Layout style={{minHeight: "100vh"}}>
<Sider collapsible collapsed={collapsed} onCollapse={setCollapsed}>
<Menu
theme="dark"
defaultSelectedKeys={[location.pathname]}
mode="inline"
items={items}
onClick={({key}) => navigate(key)}
/>
</Sider>
<Layout>
<Content style={{margin: "0 16px"}}>
<div style={{padding: 24, minHeight: 360, background: "#fff", borderRadius: 8}}>
<Outlet/>
</div>
</Content>
<Footer style={{textAlign: "center"}}>Линза+ © {new Date().getFullYear()}</Footer>
</Layout>
</Layout>
);
};
export default MainLayout;

View File

@ -1,20 +1,30 @@
import {Form, Input, Button, Row, Col, Typography} from 'antd';
import {useState} from 'react';
import {useEffect, useState} from 'react';
import {useAuth} from "../AuthContext.jsx";
import {useNavigate} from "react-router-dom";
const {Title} = Typography;
const LoginPage = () => {
const {login} = useAuth();
const {user, login} = useAuth();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const navigate = useNavigate();
useEffect(() => {
if (user) {
navigate("/");
}
}, [user, navigate]);
const onFinish = async (values) => {
setLoading(true);
setError(null);
try {
await login(values);
navigate("/");
} catch (error) {
setError(`Ошибка при входе: ${error.message}`);
} finally {