/
anv
/
Platform
Обзор
Документация
Войти
/
anv
/
Platform
Код
Запросы
2
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/App.tsx
261 строка
6 KB
nw
init
23 мар 2025, 20:31
23 мар 2025, 20:31
4875380
Код
Авторство
О чём код?
import React, { useState } from "react"; import { UnorderedListOutlined, FileOutlined, HomeOutlined, TeamOutlined, } from "@ant-design/icons"; import type { MenuProps } from "antd"; import { Avatar, Breadcrumb, Layout, Menu, Table, Tag, theme } from "antd"; const { Content, Footer, Sider } = Layout; type MenuItem = Required<MenuProps>["items"][number]; // Типы задач type TaskType = "Баг" | "Фича" | "Улучшение"; // Статусы задач type TaskStatus = "Новая" | "В работе" | "Ревью" | "Завершена"; // Приоритеты задач type TaskPriority = "Высокий" | "Средний" | "Низкий"; // Маппинг цветов для типов задач const typeColorMap: Record<TaskType, string> = { Баг: "error", Фича: "geekblue", Улучшение: "purple", }; // Маппинг цветов для статусов задач const statusColorMap: Record<TaskStatus, string> = { Новая: "cyan", "В работе": "processing", Ревью: "warning", Завершена: "success", }; // Интерфейс для исполнителя interface Assignee { id: number; name: string; initials: string; } // Список исполнителей const assignees: Assignee[] = [ { id: 1, name: "Иванов И.И.", initials: "ИИ" }, { id: 2, name: "Петров П.П.", initials: "ПП" }, { id: 3, name: "Сидоров С.С.", initials: "СС" }, ]; // Интерфейс для данных задачи interface TaskData { key: string; id: number; type: TaskType; address: string; status: TaskStatus; priority: TaskPriority; assigneeId: number; } const dataSource: TaskData[] = [ { key: "1", id: 1, type: "Баг", address: "Исправить ошибку авторизации", status: "В работе", priority: "Высокий", assigneeId: 1, }, { key: "2", id: 2, type: "Фича", address: "Добавить фильтрацию в таблицу", status: "Новая", priority: "Средний", assigneeId: 2, }, { key: "3", id: 3, type: "Улучшение", address: "Оптимизировать загрузку данных", status: "Завершена", priority: "Низкий", assigneeId: 3, }, { key: "4", id: 4, type: "Баг", address: "Исправить верстку на мобильных устройствах", status: "В работе", priority: "Высокий", assigneeId: 1, }, { key: "5", id: 5, type: "Фича", address: "Добавить экспорт в Excel", status: "Новая", priority: "Средний", assigneeId: 2, }, { key: "6", id: 6, type: "Улучшение", address: "Обновить руководство пользователя", status: "Ревью", priority: "Низкий", assigneeId: 3, }, ]; const columns = [ { title: "#", dataIndex: "id", key: "id", }, { title: "Тип", dataIndex: "type", key: "type", render: (type: TaskType) => ( <Tag color={typeColorMap[type] || "default"}>{type}</Tag> ), }, { title: "Название", dataIndex: "address", key: "address", }, { title: "Статус", dataIndex: "status", key: "status", render: (status: TaskStatus) => ( <Tag color={statusColorMap[status] || "default"}>{status}</Tag> ), }, { title: "Приоритет", dataIndex: "priority", key: "priority", }, { title: "Исполнитель", dataIndex: "assigneeId", key: "assignee", render: (assigneeId: number) => { const assignee = assignees.find((a) => a.id === assigneeId); if (!assignee) return null; return ( <div style={{ display: "flex", alignItems: "center" }}> <Avatar style={{ backgroundColor: stringToColor(assignee.name), marginRight: "8px", }} > {assignee.initials} </Avatar> {assignee.name} </div> ); }, }, ]; function getItem( label: React.ReactNode, key: React.Key, icon?: React.ReactNode, children?: MenuItem[] ): MenuItem { return { key, icon, children, label, } as MenuItem; } const items: MenuItem[] = [ getItem("Главная", "1", <HomeOutlined />), getItem("Задачи", "2", <UnorderedListOutlined />), getItem("Команда", "sub2", <TeamOutlined />, [ getItem("Команда 1", "6"), getItem("Команда 2", "8"), ]), getItem("Докумениы", "9", <FileOutlined />), ]; const stringToColor = (str: string) => { let hash = 0; for (let i = 0; i < str.length; i++) { hash = str.charCodeAt(i) + ((hash << 5) - hash); } let color = "#"; for (let i = 0; i < 3; i++) { const value = (hash >> (i * 8)) & 0xff; color += ("00" + value.toString(16)).substr(-2); } return color; }; const App: React.FC = () => { const [collapsed, setCollapsed] = useState(false); const { token: { colorBgContainer, borderRadiusLG }, } = theme.useToken(); return ( <Layout style={{ minHeight: "100vh" }}> <Sider collapsible collapsed={collapsed} onCollapse={(value) => setCollapsed(value)} > <div className="demo-logo-vertical" /> <Menu theme="dark" defaultSelectedKeys={["1"]} mode="inline" items={items} /> </Sider> <Layout> <Content style={{ margin: "0 16px" }}> <Breadcrumb style={{ margin: "16px 0" }}> <Breadcrumb.Item>Главная</Breadcrumb.Item> <Breadcrumb.Item>Задачи</Breadcrumb.Item> </Breadcrumb> <div style={{ padding: 24, minHeight: 360, background: colorBgContainer, borderRadius: borderRadiusLG, }} > <Table dataSource={dataSource} columns={columns} /> </div> </Content> <Footer style={{ textAlign: "center" }}> Платформа управления командой и процессами{new Date().getFullYear()}{" "} </Footer> </Layout> </Layout> ); }; export default App;