From 87b1e4724d31d888bc825e47fc89100f8a21c7d3 Mon Sep 17 00:00:00 2001 From: Veronika Smirnova Date: Wed, 23 Jul 2025 14:07:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=20FulfillmentWarehouseDemo?= =?UTF-8?q?=20=D0=B8=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D1=83=D1=8E=D1=89=D0=B0=D1=8F=20=D0=B2=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=BA=D0=B0=20=D0=B2=20UIKitSection.=20=D0=9E?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B8=D0=BC?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=82=D1=8B=20=D0=B8=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BA=D0=BE=D0=B4=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D1=83?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=87=D0=B8?= =?UTF-8?q?=D1=82=D0=B0=D0=B5=D0=BC=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=8B.=20?= =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20?= =?UTF-8?q?=D1=81=D1=82=D0=B8=D0=BB=D0=B8=20=D0=B2=D0=BA=D0=BB=D0=B0=D0=B4?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=B4=D0=BB=D1=8F=20=D0=B1=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=D0=B5=20=D1=83=D0=B4=D0=BE=D0=B1=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B4=D0=B5=D0=B9=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=B8=D1=8F=20=D1=81=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/admin/ui-kit-section.tsx | 129 +++++-- .../ui-kit/fulfillment-warehouse-demo.tsx | 332 ++++++++++++++++++ 2 files changed, 425 insertions(+), 36 deletions(-) create mode 100644 src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx diff --git a/src/components/admin/ui-kit-section.tsx b/src/components/admin/ui-kit-section.tsx index c871f80..b16beb5 100644 --- a/src/components/admin/ui-kit-section.tsx +++ b/src/components/admin/ui-kit-section.tsx @@ -1,78 +1,131 @@ -"use client" +"use client"; - -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' -import { ButtonsDemo } from './ui-kit/buttons-demo' -import { FormsDemo } from './ui-kit/forms-demo' -import { CardsDemo } from './ui-kit/cards-demo' -import { TypographyDemo } from './ui-kit/typography-demo' -import { ColorsDemo } from './ui-kit/colors-demo' -import { IconsDemo } from './ui-kit/icons-demo' -import { LayoutsDemo } from './ui-kit/layouts-demo' -import { NavigationDemo } from './ui-kit/navigation-demo' -import { SpecializedDemo } from './ui-kit/specialized-demo' -import { AnimationsDemo } from './ui-kit/animations-demo' -import { StatesDemo } from './ui-kit/states-demo' -import { MediaDemo } from './ui-kit/media-demo' -import { InteractiveDemo } from './ui-kit/interactive-demo' -import { BusinessDemo } from './ui-kit/business-demo' -import { TimesheetDemo } from './ui-kit/timesheet-demo' +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { ButtonsDemo } from "./ui-kit/buttons-demo"; +import { FormsDemo } from "./ui-kit/forms-demo"; +import { CardsDemo } from "./ui-kit/cards-demo"; +import { TypographyDemo } from "./ui-kit/typography-demo"; +import { ColorsDemo } from "./ui-kit/colors-demo"; +import { IconsDemo } from "./ui-kit/icons-demo"; +import { LayoutsDemo } from "./ui-kit/layouts-demo"; +import { NavigationDemo } from "./ui-kit/navigation-demo"; +import { SpecializedDemo } from "./ui-kit/specialized-demo"; +import { AnimationsDemo } from "./ui-kit/animations-demo"; +import { StatesDemo } from "./ui-kit/states-demo"; +import { MediaDemo } from "./ui-kit/media-demo"; +import { InteractiveDemo } from "./ui-kit/interactive-demo"; +import { BusinessDemo } from "./ui-kit/business-demo"; +import { TimesheetDemo } from "./ui-kit/timesheet-demo"; +import { FulfillmentWarehouseDemo } from "./ui-kit/fulfillment-warehouse-demo"; export function UIKitSection() { return (

UI Kit

-

Полная коллекция компонентов дизайн-системы SferaV

+

+ Полная коллекция компонентов дизайн-системы SferaV +

- + Кнопки - + Формы - + Карточки - + Типографика - + Цвета - + Иконки - + Макеты - + Навигация - + Специальные - + Анимации - + Состояния - + Медиа - + Интерактив - + Бизнес - + Табель + + Склад фулфилмент + @@ -134,7 +187,11 @@ export function UIKitSection() { + + + +
- ) -} \ No newline at end of file + ); +} diff --git a/src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx b/src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx new file mode 100644 index 0000000..c074845 --- /dev/null +++ b/src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx @@ -0,0 +1,332 @@ +"use client"; + +import { useState } from "react"; +import { ChevronUp, ChevronDown, TrendingUp, TrendingDown } from "lucide-react"; + +interface TableColumn { + key: string; + title: string; + sortable: boolean; +} + +interface TableData { + id: number; + number: string; + store: string; + product: string; + goods: number; + defects: number; + sellerSupplies: number; + pvzReturns: number; +} + +const columns: TableColumn[] = [ + { key: "number", title: "№", sortable: true }, + { key: "store", title: "Магазин", sortable: true }, + { key: "product", title: "Продукт", sortable: true }, + { key: "goods", title: "Товар", sortable: true }, + { key: "defects", title: "Брак", sortable: true }, + { key: "sellerSupplies", title: "Расходники селлеров", sortable: true }, + { key: "pvzReturns", title: "Возвраты с ПВЗ", sortable: true }, +]; + +const sampleData: TableData[] = [ + { + id: 1, + number: "001", + store: "Wildberries", + product: "Смартфон iPhone 15", + goods: 150, + defects: 5, + sellerSupplies: 25, + pvzReturns: 12, + }, + { + id: 2, + number: "002", + store: "Ozon", + product: "Наушники AirPods", + goods: 89, + defects: 3, + sellerSupplies: 18, + pvzReturns: 8, + }, + { + id: 3, + number: "003", + store: "Яндекс Маркет", + product: "Планшет iPad", + goods: 67, + defects: 2, + sellerSupplies: 12, + pvzReturns: 5, + }, + { + id: 4, + number: "004", + store: "Wildberries", + product: "Умные часы", + goods: 234, + defects: 8, + sellerSupplies: 45, + pvzReturns: 18, + }, + { + id: 5, + number: "005", + store: "Ozon", + product: "Ноутбук MacBook", + goods: 45, + defects: 1, + sellerSupplies: 8, + pvzReturns: 3, + }, +]; + +type SortField = keyof TableData | null; +type SortDirection = "asc" | "desc"; + +export function FulfillmentWarehouseDemo() { + const [sortField, setSortField] = useState(null); + const [sortDirection, setSortDirection] = useState("asc"); + + const handleSort = (field: keyof TableData) => { + if (sortField === field) { + setSortDirection(sortDirection === "asc" ? "desc" : "asc"); + } else { + setSortField(field); + setSortDirection("asc"); + } + }; + + const sortedData = [...sampleData].sort((a, b) => { + if (!sortField) return 0; + + const aValue = a[sortField]; + const bValue = b[sortField]; + + if (typeof aValue === "string" && typeof bValue === "string") { + return sortDirection === "asc" + ? aValue.localeCompare(bValue) + : bValue.localeCompare(aValue); + } + + if (typeof aValue === "number" && typeof bValue === "number") { + return sortDirection === "asc" ? aValue - bValue : bValue - aValue; + } + + return 0; + }); + + // Вычисляем суммарные значения + const totals = { + goods: sampleData.reduce((sum, item) => sum + item.goods, 0), + defects: sampleData.reduce((sum, item) => sum + item.defects, 0), + sellerSupplies: sampleData.reduce( + (sum, item) => sum + item.sellerSupplies, + 0 + ), + pvzReturns: sampleData.reduce((sum, item) => sum + item.pvzReturns, 0), + }; + + const SortIcon = ({ field }: { field: keyof TableData }) => { + if (sortField !== field) { + return ( +
+ + +
+ ); + } + + return sortDirection === "asc" ? ( + + ) : ( + + ); + }; + + const StatCell = ({ + value, + prevValue, + nextValue, + }: { + value: number; + prevValue: number; + nextValue: number; + }) => ( +
+
+ + {prevValue} +
+
+ {value.toLocaleString()} +
+
+ + {nextValue} +
+
+ ); + + return ( +
+
+

Склад фулфилмент

+

+ Многоуровневая таблица с сортировкой и агрегированными данными +

+
+ +
+ {/* Заголовки таблицы */} +
+
+ {columns.map((column) => ( +
+ column.sortable && handleSort(column.key as keyof TableData) + } + > + {column.title} + {column.sortable && ( + + )} +
+ ))} +
+
+ + {/* Суммарные значения */} +
+
+
+
Всего
+
+
+
Магазинов
+
3
+
+
+
Продуктов
+
5
+
+
+
Товар
+ +
+
+
Брак
+ +
+
+
Расходники
+ +
+
+
Возвраты
+ +
+
+
+ + {/* Данные таблицы */} +
+ {sortedData.map((row) => ( +
+
{row.number}
+
{row.store}
+
+ {row.product} +
+
+ {row.goods.toLocaleString()} +
+
+ {row.defects} +
+
+ {row.sellerSupplies} +
+
+ {row.pvzReturns} +
+
+ ))} +
+
+ + {/* Дополнительная информация */} +
+
+

+ Особенности таблицы +

+
    +
  • • Сортировка по всем столбцам
  • +
  • • Агрегированные данные с индикаторами
  • +
  • • Многоуровневая структура
  • +
  • • Цветовое кодирование данных
  • +
+
+ +
+

Индикаторы

+
+
+ + Рост (левое значение) +
+
+ + Падение (правое значение) +
+
+
+ +
+

+ Цветовая схема +

+
+
+
+ Товары +
+
+
+ Брак +
+
+
+ Расходники +
+
+
+ Возвраты +
+
+
+
+
+ ); +}