Merge branch 'main' of https://gittea.biveki.ru/Sfera/sfera
This commit is contained in:
@ -1,78 +1,131 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
import { ButtonsDemo } from "./ui-kit/buttons-demo";
|
||||||
import { ButtonsDemo } from './ui-kit/buttons-demo'
|
import { FormsDemo } from "./ui-kit/forms-demo";
|
||||||
import { FormsDemo } from './ui-kit/forms-demo'
|
import { CardsDemo } from "./ui-kit/cards-demo";
|
||||||
import { CardsDemo } from './ui-kit/cards-demo'
|
import { TypographyDemo } from "./ui-kit/typography-demo";
|
||||||
import { TypographyDemo } from './ui-kit/typography-demo'
|
import { ColorsDemo } from "./ui-kit/colors-demo";
|
||||||
import { ColorsDemo } from './ui-kit/colors-demo'
|
import { IconsDemo } from "./ui-kit/icons-demo";
|
||||||
import { IconsDemo } from './ui-kit/icons-demo'
|
import { LayoutsDemo } from "./ui-kit/layouts-demo";
|
||||||
import { LayoutsDemo } from './ui-kit/layouts-demo'
|
import { NavigationDemo } from "./ui-kit/navigation-demo";
|
||||||
import { NavigationDemo } from './ui-kit/navigation-demo'
|
import { SpecializedDemo } from "./ui-kit/specialized-demo";
|
||||||
import { SpecializedDemo } from './ui-kit/specialized-demo'
|
import { AnimationsDemo } from "./ui-kit/animations-demo";
|
||||||
import { AnimationsDemo } from './ui-kit/animations-demo'
|
import { StatesDemo } from "./ui-kit/states-demo";
|
||||||
import { StatesDemo } from './ui-kit/states-demo'
|
import { MediaDemo } from "./ui-kit/media-demo";
|
||||||
import { MediaDemo } from './ui-kit/media-demo'
|
import { InteractiveDemo } from "./ui-kit/interactive-demo";
|
||||||
import { InteractiveDemo } from './ui-kit/interactive-demo'
|
import { BusinessDemo } from "./ui-kit/business-demo";
|
||||||
import { BusinessDemo } from './ui-kit/business-demo'
|
import { TimesheetDemo } from "./ui-kit/timesheet-demo";
|
||||||
import { TimesheetDemo } from './ui-kit/timesheet-demo'
|
import { FulfillmentWarehouseDemo } from "./ui-kit/fulfillment-warehouse-demo";
|
||||||
|
|
||||||
export function UIKitSection() {
|
export function UIKitSection() {
|
||||||
return (
|
return (
|
||||||
<div className="p-8">
|
<div className="p-8">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<h1 className="text-3xl font-bold text-white mb-2">UI Kit</h1>
|
<h1 className="text-3xl font-bold text-white mb-2">UI Kit</h1>
|
||||||
<p className="text-white/70">Полная коллекция компонентов дизайн-системы SferaV</p>
|
<p className="text-white/70">
|
||||||
|
Полная коллекция компонентов дизайн-системы SferaV
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tabs defaultValue="buttons" className="w-full">
|
<Tabs defaultValue="buttons" className="w-full">
|
||||||
<TabsList className="flex flex-wrap gap-1 bg-white/5 backdrop-blur border-white/10 p-2 rounded-lg mb-8 h-auto">
|
<TabsList className="flex flex-wrap gap-1 bg-white/5 backdrop-blur border-white/10 p-2 rounded-lg mb-8 h-auto">
|
||||||
<TabsTrigger value="buttons" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="buttons"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Кнопки
|
Кнопки
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="forms" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="forms"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Формы
|
Формы
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="cards" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="cards"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Карточки
|
Карточки
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="typography" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="typography"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Типографика
|
Типографика
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="colors" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="colors"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Цвета
|
Цвета
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="icons" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="icons"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Иконки
|
Иконки
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="layouts" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="layouts"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Макеты
|
Макеты
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="navigation" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="navigation"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Навигация
|
Навигация
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="specialized" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="specialized"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Специальные
|
Специальные
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="animations" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="animations"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Анимации
|
Анимации
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="states" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="states"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Состояния
|
Состояния
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="media" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="media"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Медиа
|
Медиа
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="interactive" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="interactive"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Интерактив
|
Интерактив
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="business" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="business"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Бизнес
|
Бизнес
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="timesheet" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2">
|
<TabsTrigger
|
||||||
|
value="timesheet"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
Табель
|
Табель
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
<TabsTrigger
|
||||||
|
value="fulfillment-warehouse"
|
||||||
|
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
|
||||||
|
>
|
||||||
|
Склад фулфилмент
|
||||||
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="buttons" className="space-y-6">
|
<TabsContent value="buttons" className="space-y-6">
|
||||||
@ -134,7 +187,11 @@ export function UIKitSection() {
|
|||||||
<TabsContent value="timesheet" className="space-y-6">
|
<TabsContent value="timesheet" className="space-y-6">
|
||||||
<TimesheetDemo />
|
<TimesheetDemo />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="fulfillment-warehouse" className="space-y-6">
|
||||||
|
<FulfillmentWarehouseDemo />
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
332
src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx
Normal file
332
src/components/admin/ui-kit/fulfillment-warehouse-demo.tsx
Normal file
@ -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<SortField>(null);
|
||||||
|
const [sortDirection, setSortDirection] = useState<SortDirection>("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 (
|
||||||
|
<div className="flex flex-col ml-1 opacity-30">
|
||||||
|
<ChevronUp size={12} />
|
||||||
|
<ChevronDown size={12} className="-mt-1" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortDirection === "asc" ? (
|
||||||
|
<ChevronUp size={14} className="ml-1 text-blue-400" />
|
||||||
|
) : (
|
||||||
|
<ChevronDown size={14} className="ml-1 text-blue-400" />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatCell = ({
|
||||||
|
value,
|
||||||
|
prevValue,
|
||||||
|
nextValue,
|
||||||
|
}: {
|
||||||
|
value: number;
|
||||||
|
prevValue: number;
|
||||||
|
nextValue: number;
|
||||||
|
}) => (
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
<div className="flex items-center text-xs text-green-400">
|
||||||
|
<TrendingUp size={12} className="mr-1" />
|
||||||
|
{prevValue}
|
||||||
|
</div>
|
||||||
|
<div className="text-lg font-semibold text-white">
|
||||||
|
{value.toLocaleString()}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-xs text-red-400">
|
||||||
|
<TrendingDown size={12} className="mr-1" />
|
||||||
|
{nextValue}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-8">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-4">Склад фулфилмент</h2>
|
||||||
|
<p className="text-white/70 mb-6">
|
||||||
|
Многоуровневая таблица с сортировкой и агрегированными данными
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white/5 backdrop-blur border border-white/10 rounded-lg overflow-hidden">
|
||||||
|
{/* Заголовки таблицы */}
|
||||||
|
<div className="bg-white/10 border-b border-white/10">
|
||||||
|
<div className="grid grid-cols-7 gap-4 p-4">
|
||||||
|
{columns.map((column) => (
|
||||||
|
<div
|
||||||
|
key={column.key}
|
||||||
|
className={`flex items-center justify-center text-sm font-medium text-white/90 ${
|
||||||
|
column.sortable ? "cursor-pointer hover:text-white" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() =>
|
||||||
|
column.sortable && handleSort(column.key as keyof TableData)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{column.title}
|
||||||
|
{column.sortable && (
|
||||||
|
<SortIcon field={column.key as keyof TableData} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Суммарные значения */}
|
||||||
|
<div className="bg-white/5 border-b border-white/10">
|
||||||
|
<div className="grid grid-cols-7 gap-4 p-6">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60">Всего</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60">Магазинов</div>
|
||||||
|
<div className="text-lg font-semibold text-white">3</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60">Продуктов</div>
|
||||||
|
<div className="text-lg font-semibold text-white">5</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60 mb-2">Товар</div>
|
||||||
|
<StatCell value={totals.goods} prevValue={520} nextValue={610} />
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60 mb-2">Брак</div>
|
||||||
|
<StatCell value={totals.defects} prevValue={15} nextValue={25} />
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60 mb-2">Расходники</div>
|
||||||
|
<StatCell
|
||||||
|
value={totals.sellerSupplies}
|
||||||
|
prevValue={95}
|
||||||
|
nextValue={125}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-sm text-white/60 mb-2">Возвраты</div>
|
||||||
|
<StatCell
|
||||||
|
value={totals.pvzReturns}
|
||||||
|
prevValue={38}
|
||||||
|
nextValue={55}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Данные таблицы */}
|
||||||
|
<div className="divide-y divide-white/10">
|
||||||
|
{sortedData.map((row) => (
|
||||||
|
<div
|
||||||
|
key={row.id}
|
||||||
|
className="grid grid-cols-7 gap-4 p-4 hover:bg-white/5 transition-colors"
|
||||||
|
>
|
||||||
|
<div className="text-center text-white/80">{row.number}</div>
|
||||||
|
<div className="text-center text-white/80">{row.store}</div>
|
||||||
|
<div
|
||||||
|
className="text-center text-white/80 truncate"
|
||||||
|
title={row.product}
|
||||||
|
>
|
||||||
|
{row.product}
|
||||||
|
</div>
|
||||||
|
<div className="text-center text-white font-medium">
|
||||||
|
{row.goods.toLocaleString()}
|
||||||
|
</div>
|
||||||
|
<div className="text-center text-red-400 font-medium">
|
||||||
|
{row.defects}
|
||||||
|
</div>
|
||||||
|
<div className="text-center text-yellow-400 font-medium">
|
||||||
|
{row.sellerSupplies}
|
||||||
|
</div>
|
||||||
|
<div className="text-center text-orange-400 font-medium">
|
||||||
|
{row.pvzReturns}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Дополнительная информация */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<div className="bg-white/5 backdrop-blur border border-white/10 rounded-lg p-4">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2">
|
||||||
|
Особенности таблицы
|
||||||
|
</h3>
|
||||||
|
<ul className="text-sm text-white/70 space-y-1">
|
||||||
|
<li>• Сортировка по всем столбцам</li>
|
||||||
|
<li>• Агрегированные данные с индикаторами</li>
|
||||||
|
<li>• Многоуровневая структура</li>
|
||||||
|
<li>• Цветовое кодирование данных</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white/5 backdrop-blur border border-white/10 rounded-lg p-4">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2">Индикаторы</h3>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<TrendingUp size={16} className="text-green-400 mr-2" />
|
||||||
|
<span className="text-white/70">Рост (левое значение)</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<TrendingDown size={16} className="text-red-400 mr-2" />
|
||||||
|
<span className="text-white/70">Падение (правое значение)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white/5 backdrop-blur border border-white/10 rounded-lg p-4">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2">
|
||||||
|
Цветовая схема
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="w-3 h-3 bg-white rounded mr-2"></div>
|
||||||
|
<span className="text-white/70">Товары</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="w-3 h-3 bg-red-400 rounded mr-2"></div>
|
||||||
|
<span className="text-white/70">Брак</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="w-3 h-3 bg-yellow-400 rounded mr-2"></div>
|
||||||
|
<span className="text-white/70">Расходники</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="w-3 h-3 bg-orange-400 rounded mr-2"></div>
|
||||||
|
<span className="text-white/70">Возвраты</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user