feat: add base styles and base routes

This commit is contained in:
Vladislav Syrochkin 2025-04-17 12:24:03 +05:00
parent 51227bfd7b
commit 583d2005a7
13 changed files with 259 additions and 59 deletions

View File

@ -0,0 +1,3 @@
<svg width="4" height="16" viewBox="0 0 4 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4C3.1 4 4 3.1 4 2C4 0.9 3.1 0 2 0C0.9 0 0 0.9 0 2C0 3.1 0.9 4 2 4ZM2 6C0.9 6 0 6.9 0 8C0 9.1 0.9 10 2 10C3.1 10 4 9.1 4 8C4 6.9 3.1 6 2 6ZM2 12C0.9 12 0 12.9 0 14C0 15.1 0.9 16 2 16C3.1 16 4 15.1 4 14C4 12.9 3.1 12 2 12Z" fill="#606060"/>
</svg>

After

Width:  |  Height:  |  Size: 392 B

View File

@ -6,14 +6,12 @@ import ProtectedRoute from './pages/ProtectedRoute';
function App() {
return (
<div className="App">
<div>
<Routes>
<Route path="/login" element={<div>login</div>} />
<Route element={<ProtectedRoute />}>
<Route path="*" element={<MainLayout />}></Route>
</Route>
</Routes>
</div>
<Routes>
<Route path="/login" element={<div>login</div>} />
<Route element={<ProtectedRoute />}>
<Route path="*" element={<MainLayout />}></Route>
</Route>
</Routes>
</div>
);
}

View File

@ -0,0 +1,56 @@
import Title from 'antd/es/typography/Title';
interface HeaderProps {
title: string;
}
export default function Header({ title }: HeaderProps) {
return (
<div
style={{
height: '72px',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Title style={{ marginLeft: '16px' }} level={3}>
{title}
</Title>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '24px',
marginRight: '26px',
}}
>
<img
src="./icons/sider/more.svg"
alt="more"
style={{ height: '16px', width: '16px' }}
/>
<div
style={{
borderRadius: '50%',
border: '2px solid #8BC34A',
height: '32px',
width: '32px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<img
src="https://cdn-icons-png.flaticon.com/512/219/219986.png"
alt="user"
style={{
height: '25.771240234375px',
width: '25.771240234375px',
}}
/>
</div>
</div>
</div>
);
}

View File

@ -1,61 +1,96 @@
import { Menu, MenuProps } from 'antd';
type MenuItem = Required<MenuProps>['items'][number];
function getItem(
label: React.ReactNode,
key: React.Key,
icon?: React.ReactNode,
children?: MenuItem[]
): MenuItem {
return {
key,
icon,
children,
label,
} as MenuItem;
}
const sidebarItems: MenuItem[] = [
getItem('VORKOUT', '0', <img src="./icons/sider/menu.svg" alt="toggle" />),
getItem(
'Схемы процессов',
'1',
<img src="./icons/sider/process-diagram.svg" alt="process diagram" />
),
getItem(
'Запущенные процессы',
'2',
<img src="./icons/sider/running-processes.svg" alt="running processes" />
),
getItem(
'Настройки',
'sub1',
<img src="./icons/sider/settings.svg" alt="settings" />,
[
getItem('Учетные записи', '3'),
getItem('Справичник событий', '4'),
getItem('Конфигурация', '5'),
]
),
];
import { Divider, Menu } from 'antd';
import React from 'react';
interface SiderMenuProps {
collapsed: boolean;
selectedKey: string;
hangleMenuClick: (e: any) => void;
}
export default function SiderMenu({
collapsed,
selectedKey,
hangleMenuClick,
}: SiderMenuProps) {
const menuItems = (
<React.Fragment>
<Menu.Item
key="0"
icon={
<img
src={
!collapsed
? './icons/sider/menu_open.svg'
: './icons/sider/menu.svg'
}
alt="toggle"
/>
}
style={{ fontSize: '20px' }}
>
VORKOUT
</Menu.Item>
<Menu.Item
key="/process-diagram"
icon={
<img src="./icons/sider/process-diagram.svg" alt="process diagram" />
}
>
Схемы процессов
</Menu.Item>
<Menu.Item
key="/running-processes"
icon={
<img
src="./icons/sider/running-processes.svg"
alt="running processes"
/>
}
>
Запущенные процессы
</Menu.Item>
{!collapsed && <Divider style={{ marginBottom: 0 }} />}
<Menu.SubMenu
key="sub1"
icon={<img src="./icons/sider/settings.svg" alt="settings" />}
title="Настройки"
expandIcon={false}
>
<Menu.Item
key="/accounts"
style={{ fontSize: '12px', paddingLeft: '52px' }}
>
Учетные записи
</Menu.Item>
<Menu.Item
key="/events-list"
style={{ fontSize: '12px', paddingLeft: '52px' }}
>
Справочник событий
</Menu.Item>
<Menu.Item
key="/configuration"
style={{ fontSize: '12px', paddingLeft: '52px' }}
>
Конфигурация
</Menu.Item>
</Menu.SubMenu>
</React.Fragment>
);
return (
<Menu
theme="light"
selectedKeys={[selectedKey]}
mode="inline"
items={sidebarItems}
onClick={hangleMenuClick}
/>
defaultOpenKeys={['sub1']}
>
{menuItems}
</Menu>
);
}

View File

@ -0,0 +1,14 @@
export const theme = {
token: {
fontFamily: 'Roboto, sans-serif',
colorPrimary: '#548d10',
Menu: {
itemColor: 'f2f2f2',
itemBg: '#f2f2f2',
subMenuItemBg: '#f2f2f2',
},
Layout: {
bodyBg: '#f2f2f2',
},
},
};

View File

@ -11,3 +11,17 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.ant-menu-inline .ant-menu-submenu-selected {
border: none;
}
.ant-menu-inline .ant-menu-submenu-selected > .ant-menu-submenu-title {
color: #548d10;
}
.ant-menu-inline .ant-menu-item-selected {
background-color: transparent;
border: none;
color: #548d10;
}

View File

@ -3,12 +3,17 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import { theme } from './config/customTheme';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
<ConfigProvider theme={theme}>
<BrowserRouter>
<App />
</BrowserRouter>
</ConfigProvider>
);

View File

@ -0,0 +1,9 @@
import Header from '../components/Header';
export default function AccountsPage() {
return (
<>
<Header title="Учетные записи" />
</>
);
}

View File

@ -0,0 +1,9 @@
import Header from '../components/Header';
export default function ConfigurationPage() {
return (
<>
<Header title="Конфигурация" />
</>
);
}

View File

@ -0,0 +1,9 @@
import Header from '../components/Header';
export default function EventsListPage() {
return (
<>
<Header title="Справочник событий" />
</>
);
}

View File

@ -1,19 +1,40 @@
import React, { useState } from 'react';
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState } from 'react';
import { Layout } from 'antd';
import Sider from 'antd/es/layout/Sider';
import SiderMenu from '../components/SiderMenu';
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import ProcessDiagramPage from './ProcessDiagramPage';
import RunningProcessesPage from './RunningProcessesPage';
import AccountsPage from './AccountsPage';
import EventsListPage from './EventsListPage';
import ConfigurationPage from './ConfigurationPage';
export default function MainLayout() {
const navigate = useNavigate();
const location = useLocation();
const [collapsed, setCollapsed] = useState(false);
const [selectedKey, setSelectedKey] = useState('1');
useEffect(() => {
if (location.pathname === '/') {
navigate('/process-diagram');
}
}, [location.pathname]);
useEffect(() => {
setSelectedKey(location.pathname);
});
function hangleMenuClick(e: any) {
if (e.key === '0') {
setCollapsed((prev) => !prev);
const key = e.key;
if (key === '0') {
setCollapsed(!collapsed);
return;
}
setSelectedKey(e.key);
setSelectedKey(key);
navigate(key);
}
return (
@ -26,14 +47,23 @@ export default function MainLayout() {
width={'15%'}
collapsedWidth={'3.8%'}
trigger={null}
style={{ backgroundColor: '#f2f2f2' }}
>
<SiderMenu
collapsed={collapsed}
selectedKey={selectedKey}
hangleMenuClick={hangleMenuClick}
/>
</Sider>
<Layout>
<div>Main layout</div>
<Routes>
<Route path="/process-diagram" element={<ProcessDiagramPage />} />
<Route path="/running-processes" element={<RunningProcessesPage />} />
<Route path="/accounts" element={<AccountsPage />} />
<Route path="/events-list" element={<EventsListPage />} />
<Route path="/configuration" element={<ConfigurationPage />} />
<Route path="*" element={<div>404 Not Found</div>} />
</Routes>
</Layout>
</Layout>
);

View File

@ -0,0 +1,9 @@
import Header from '../components/Header';
export default function ProcessDiagramPage() {
return (
<>
<Header title="Схемы процессов" />
</>
);
}

View File

@ -0,0 +1,9 @@
import Header from '../components/Header';
export default function RunningProcessesPage() {
return (
<>
<Header title="Запущенные процессы" />
</>
);
}