feat: add base styles and base routes
This commit is contained in:
parent
51227bfd7b
commit
583d2005a7
3
client/public/icons/sider/more.svg
Normal file
3
client/public/icons/sider/more.svg
Normal 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 |
@ -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>
|
||||
);
|
||||
}
|
||||
|
56
client/src/components/Header.tsx
Normal file
56
client/src/components/Header.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
14
client/src/config/customTheme.ts
Normal file
14
client/src/config/customTheme.ts
Normal 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',
|
||||
},
|
||||
},
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
|
9
client/src/pages/AccountsPage.tsx
Normal file
9
client/src/pages/AccountsPage.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function AccountsPage() {
|
||||
return (
|
||||
<>
|
||||
<Header title="Учетные записи" />
|
||||
</>
|
||||
);
|
||||
}
|
9
client/src/pages/ConfigurationPage.tsx
Normal file
9
client/src/pages/ConfigurationPage.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function ConfigurationPage() {
|
||||
return (
|
||||
<>
|
||||
<Header title="Конфигурация" />
|
||||
</>
|
||||
);
|
||||
}
|
9
client/src/pages/EventsListPage.tsx
Normal file
9
client/src/pages/EventsListPage.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function EventsListPage() {
|
||||
return (
|
||||
<>
|
||||
<Header title="Справочник событий" />
|
||||
</>
|
||||
);
|
||||
}
|
@ -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>
|
||||
);
|
||||
|
9
client/src/pages/ProcessDiagramPage.tsx
Normal file
9
client/src/pages/ProcessDiagramPage.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function ProcessDiagramPage() {
|
||||
return (
|
||||
<>
|
||||
<Header title="Схемы процессов" />
|
||||
</>
|
||||
);
|
||||
}
|
9
client/src/pages/RunningProcessesPage.tsx
Normal file
9
client/src/pages/RunningProcessesPage.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function RunningProcessesPage() {
|
||||
return (
|
||||
<>
|
||||
<Header title="Запущенные процессы" />
|
||||
</>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user