972 lines
39 KiB
TypeScript
972 lines
39 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { TimesheetDemo } from "./timesheet-demo";
|
||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||
import { Badge } from "@/components/ui/badge";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||
import { Progress } from "@/components/ui/progress";
|
||
import { Input } from "@/components/ui/input";
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "@/components/ui/select";
|
||
import {
|
||
Calendar,
|
||
Check,
|
||
X,
|
||
Clock,
|
||
User,
|
||
Package,
|
||
Star,
|
||
Heart,
|
||
ShoppingCart,
|
||
Edit,
|
||
Trash2,
|
||
Phone,
|
||
Mail,
|
||
MapPin,
|
||
Building,
|
||
TrendingUp,
|
||
Award,
|
||
Users,
|
||
Briefcase,
|
||
Eye,
|
||
Plus,
|
||
Minus,
|
||
Store,
|
||
Boxes,
|
||
ChevronDown,
|
||
ChevronRight,
|
||
Hash,
|
||
Package2,
|
||
Truck,
|
||
} from "lucide-react";
|
||
|
||
export function BusinessDemo() {
|
||
const [selectedProduct] = useState(null);
|
||
const [cartQuantity, setCartQuantity] = useState(1);
|
||
const [expandedSeller, setExpandedSeller] = useState(false);
|
||
|
||
// Данные для демонстрации
|
||
const scheduleData = Array.from({ length: 30 }, (_, i) => ({
|
||
day: i + 1,
|
||
status: ["work", "work", "work", "work", "work", "weekend", "weekend"][
|
||
i % 7
|
||
],
|
||
hours: [8, 8, 8, 8, 8, 0, 0][i % 7],
|
||
}));
|
||
|
||
const products = [
|
||
{
|
||
id: "1",
|
||
name: "iPhone 15 Pro Max 256GB",
|
||
article: "APL-IP15PM-256",
|
||
price: 89990,
|
||
oldPrice: 99990,
|
||
quantity: 45,
|
||
category: "Электроника",
|
||
brand: "Apple",
|
||
rating: 4.8,
|
||
reviews: 1234,
|
||
image: "/placeholder-phone.jpg",
|
||
seller: "TechStore Moscow",
|
||
isNew: true,
|
||
inStock: true,
|
||
},
|
||
{
|
||
id: "2",
|
||
name: "Беспроводные наушники AirPods Pro",
|
||
article: "APL-APP-PRO",
|
||
price: 24990,
|
||
quantity: 23,
|
||
category: "Аксессуары",
|
||
brand: "Apple",
|
||
rating: 4.6,
|
||
reviews: 856,
|
||
image: "/placeholder-headphones.jpg",
|
||
seller: "Audio Expert",
|
||
isNew: false,
|
||
inStock: true,
|
||
},
|
||
{
|
||
id: "3",
|
||
name: "Ноутбук MacBook Air M2",
|
||
article: "APL-MBA-M2",
|
||
price: 0,
|
||
quantity: 0,
|
||
category: "Компьютеры",
|
||
brand: "Apple",
|
||
rating: 4.9,
|
||
reviews: 445,
|
||
image: "/placeholder-laptop.jpg",
|
||
seller: "Digital World",
|
||
isNew: false,
|
||
inStock: false,
|
||
},
|
||
];
|
||
|
||
// Данные для поставки фулфилмента
|
||
const fulfillmentSupply = {
|
||
id: "1",
|
||
supplyNumber: "ФФ-2024-001",
|
||
supplyDate: "2024-01-15",
|
||
seller: {
|
||
id: "seller1",
|
||
name: "TechStore LLC",
|
||
storeName: "ТехноМагазин",
|
||
managerName: "Иванов Иван Иванович",
|
||
phone: "+7 (495) 123-45-67",
|
||
email: "contact@techstore.ru",
|
||
inn: "7701234567",
|
||
},
|
||
itemsQuantity: 150,
|
||
cargoPlaces: 5,
|
||
volume: 12.5,
|
||
responsibleEmployeeId: "emp1",
|
||
logisticsPartnerId: "log1",
|
||
status: "planned",
|
||
totalValue: 2500000,
|
||
};
|
||
|
||
const employees = [
|
||
{
|
||
id: "emp1",
|
||
firstName: "Иван",
|
||
lastName: "Петров",
|
||
position: "Менеджер склада",
|
||
},
|
||
{
|
||
id: "emp2",
|
||
firstName: "Мария",
|
||
lastName: "Сидорова",
|
||
position: "Логист",
|
||
},
|
||
];
|
||
|
||
const logisticsPartners = [
|
||
{ id: "log1", name: "ТК Энергия", fullName: "ООО ТК Энергия" },
|
||
{ id: "log2", name: "СДЭК", fullName: "ООО СДЭК" },
|
||
];
|
||
|
||
const wholesalers = [
|
||
{
|
||
id: "1",
|
||
name: "ТехноОпт Москва",
|
||
fullName: 'ООО "Технологии Оптом"',
|
||
inn: "7735123456",
|
||
type: "WHOLESALE",
|
||
avatar: "/placeholder-company.jpg",
|
||
rating: 4.8,
|
||
reviewsCount: 2345,
|
||
productsCount: 15670,
|
||
completedOrders: 8934,
|
||
responseTime: "2 часа",
|
||
categories: ["Электроника", "Компьютеры", "Аксессуары"],
|
||
location: "Москва, Россия",
|
||
workingSince: "2018",
|
||
verifiedBadges: ["verified", "premium", "fast-delivery"],
|
||
description:
|
||
"Крупнейший поставщик электроники и компьютерной техники в России",
|
||
specialOffers: 3,
|
||
minOrder: 50000,
|
||
},
|
||
{
|
||
id: "2",
|
||
name: "СтройБаза Регион",
|
||
fullName: "ИП Строительные материалы",
|
||
inn: "7735987654",
|
||
type: "WHOLESALE",
|
||
avatar: "/placeholder-construction.jpg",
|
||
rating: 4.5,
|
||
reviewsCount: 1876,
|
||
productsCount: 8430,
|
||
completedOrders: 5621,
|
||
responseTime: "4 часа",
|
||
categories: ["Стройматериалы", "Инструменты", "Сантехника"],
|
||
location: "Екатеринбург, Россия",
|
||
workingSince: "2015",
|
||
verifiedBadges: ["verified", "eco-friendly"],
|
||
description: "Надежный поставщик строительных материалов по всей России",
|
||
specialOffers: 1,
|
||
minOrder: 30000,
|
||
},
|
||
];
|
||
|
||
const getStatusColor = (status: string) => {
|
||
switch (status) {
|
||
case "work":
|
||
return "bg-green-500";
|
||
case "weekend":
|
||
return "bg-gray-400";
|
||
case "vacation":
|
||
return "bg-blue-500";
|
||
case "sick":
|
||
return "bg-yellow-500";
|
||
case "absent":
|
||
return "bg-red-500";
|
||
default:
|
||
return "bg-gray-400";
|
||
}
|
||
};
|
||
|
||
const getStatusText = (status: string) => {
|
||
switch (status) {
|
||
case "work":
|
||
return "Работа";
|
||
case "weekend":
|
||
return "Выходной";
|
||
case "vacation":
|
||
return "Отпуск";
|
||
case "sick":
|
||
return "Больничный";
|
||
case "absent":
|
||
return "Прогул";
|
||
default:
|
||
return "Неизвестно";
|
||
}
|
||
};
|
||
|
||
const formatPrice = (price: number) => {
|
||
return new Intl.NumberFormat("ru-RU", {
|
||
style: "currency",
|
||
currency: "RUB",
|
||
minimumFractionDigits: 0,
|
||
}).format(price);
|
||
};
|
||
|
||
const formatCurrency = (amount: number) => {
|
||
return new Intl.NumberFormat("ru-RU", {
|
||
style: "currency",
|
||
currency: "RUB",
|
||
minimumFractionDigits: 0,
|
||
}).format(amount);
|
||
};
|
||
|
||
const formatDate = (dateString: string) => {
|
||
return new Date(dateString).toLocaleDateString("ru-RU", {
|
||
day: "2-digit",
|
||
month: "2-digit",
|
||
year: "numeric",
|
||
});
|
||
};
|
||
|
||
const getStatusBadge = (status: string) => {
|
||
const statusConfig = {
|
||
planned: {
|
||
color: "text-blue-300 border-blue-400/30",
|
||
label: "Запланировано",
|
||
},
|
||
"in-transit": {
|
||
color: "text-yellow-300 border-yellow-400/30",
|
||
label: "В пути",
|
||
},
|
||
delivered: {
|
||
color: "text-green-300 border-green-400/30",
|
||
label: "Доставлено",
|
||
},
|
||
"in-processing": {
|
||
color: "text-purple-300 border-purple-400/30",
|
||
label: "Обрабатывается",
|
||
},
|
||
};
|
||
|
||
const config =
|
||
statusConfig[status as keyof typeof statusConfig] || statusConfig.planned;
|
||
|
||
return (
|
||
<Badge variant="outline" className={`glass-secondary ${config.color}`}>
|
||
{config.label}
|
||
</Badge>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* Табель рабочего времени */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Табель рабочего времени</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Заголовок табеля */}
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center space-x-3">
|
||
<Avatar className="h-10 w-10">
|
||
<AvatarImage src="/placeholder-employee.jpg" />
|
||
<AvatarFallback className="bg-purple-600 text-white">
|
||
ИИ
|
||
</AvatarFallback>
|
||
</Avatar>
|
||
<div>
|
||
<h4 className="text-white font-medium">Иванов Иван Иванович</h4>
|
||
<p className="text-white/60 text-sm">
|
||
Менеджер по продажам • Март 2024
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="text-right">
|
||
<p className="text-white text-lg font-bold">176 часов</p>
|
||
<p className="text-white/60 text-sm">Отработано в месяце</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Календарь */}
|
||
<div className="space-y-4">
|
||
<div className="grid grid-cols-7 gap-2 text-center text-sm text-white/70">
|
||
<div>Пн</div>
|
||
<div>Вт</div>
|
||
<div>Ср</div>
|
||
<div>Чт</div>
|
||
<div>Пт</div>
|
||
<div>Сб</div>
|
||
<div>Вс</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-7 gap-2">
|
||
{scheduleData.map((day, index) => (
|
||
<div
|
||
key={index}
|
||
className={`
|
||
relative p-3 rounded-lg border border-white/10 text-center transition-all hover:border-white/30
|
||
${day.status === "work" ? "bg-green-500/20" : ""}
|
||
${day.status === "weekend" ? "bg-gray-500/20" : ""}
|
||
`}
|
||
>
|
||
<div className="text-white text-sm font-medium">
|
||
{day.day}
|
||
</div>
|
||
<div
|
||
className={`w-2 h-2 rounded-full mx-auto mt-1 ${getStatusColor(
|
||
day.status
|
||
)}`}
|
||
></div>
|
||
{day.hours > 0 && (
|
||
<div className="text-white/60 text-xs mt-1">
|
||
{day.hours}ч
|
||
</div>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Легенда */}
|
||
<div className="flex flex-wrap gap-4 text-sm">
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-green-500"></div>
|
||
<span className="text-white/70">Работа</span>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-gray-400"></div>
|
||
<span className="text-white/70">Выходной</span>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-blue-500"></div>
|
||
<span className="text-white/70">Отпуск</span>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||
<span className="text-white/70">Больничный</span>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full bg-red-500"></div>
|
||
<span className="text-white/70">Прогул</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Статистика */}
|
||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||
<div className="glass-card p-3 rounded-lg border border-white/10">
|
||
<div className="text-white/60 text-xs">Рабочие дни</div>
|
||
<div className="text-white text-lg font-bold">22</div>
|
||
</div>
|
||
<div className="glass-card p-3 rounded-lg border border-white/10">
|
||
<div className="text-white/60 text-xs">Выходные</div>
|
||
<div className="text-white text-lg font-bold">8</div>
|
||
</div>
|
||
<div className="glass-card p-3 rounded-lg border border-white/10">
|
||
<div className="text-white/60 text-xs">Отпуск</div>
|
||
<div className="text-white text-lg font-bold">0</div>
|
||
</div>
|
||
<div className="glass-card p-3 rounded-lg border border-white/10">
|
||
<div className="text-white/60 text-xs">Опозданий</div>
|
||
<div className="text-white text-lg font-bold">2</div>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Карточки товаров */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Карточки товаров</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||
{products.map((product) => (
|
||
<div
|
||
key={product.id}
|
||
className="glass-card p-4 rounded-lg border border-white/10 group hover:border-white/30 transition-all"
|
||
>
|
||
{/* Изображение товара */}
|
||
<div className="relative mb-3">
|
||
<div className="w-full h-40 bg-white/10 rounded-lg flex items-center justify-center">
|
||
<Package className="h-16 w-16 text-white/40" />
|
||
</div>
|
||
|
||
{/* Бейджи */}
|
||
<div className="absolute top-2 left-2 flex flex-col gap-1">
|
||
{product.isNew && (
|
||
<Badge className="bg-green-600 text-white text-xs">
|
||
Новинка
|
||
</Badge>
|
||
)}
|
||
{product.oldPrice && (
|
||
<Badge className="bg-red-600 text-white text-xs">
|
||
Скидка
|
||
</Badge>
|
||
)}
|
||
</div>
|
||
|
||
{/* Кнопки действий */}
|
||
<div className="absolute top-2 right-2 flex flex-col gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
className="bg-white/20 hover:bg-white/30 text-white border-white/30 h-8 w-8 p-0"
|
||
>
|
||
<Heart className="h-3 w-3" />
|
||
</Button>
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
className="bg-white/20 hover:bg-white/30 text-white border-white/30 h-8 w-8 p-0"
|
||
>
|
||
<Eye className="h-3 w-3" />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Информация о товаре */}
|
||
<div className="space-y-2">
|
||
<div>
|
||
<h4 className="text-white font-medium text-sm line-clamp-2">
|
||
{product.name}
|
||
</h4>
|
||
<p className="text-white/60 text-xs">
|
||
Артикул: {product.article}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Рейтинг и отзывы */}
|
||
<div className="flex items-center gap-2">
|
||
<div className="flex items-center gap-1">
|
||
<Star className="h-3 w-3 fill-yellow-400 text-yellow-400" />
|
||
<span className="text-white/80 text-xs">
|
||
{product.rating}
|
||
</span>
|
||
</div>
|
||
<span className="text-white/60 text-xs">
|
||
({product.reviews} отзывов)
|
||
</span>
|
||
</div>
|
||
|
||
{/* Категория и бренд */}
|
||
<div className="flex flex-wrap gap-1">
|
||
<Badge
|
||
variant="outline"
|
||
className="text-xs border-white/30 text-white/70"
|
||
>
|
||
{product.category}
|
||
</Badge>
|
||
<Badge
|
||
variant="outline"
|
||
className="text-xs border-white/30 text-white/70"
|
||
>
|
||
{product.brand}
|
||
</Badge>
|
||
</div>
|
||
|
||
{/* Цена */}
|
||
<div className="space-y-1">
|
||
{product.price > 0 ? (
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-white font-bold">
|
||
{formatPrice(product.price)}
|
||
</span>
|
||
{product.oldPrice && (
|
||
<span className="text-white/60 text-sm line-through">
|
||
{formatPrice(product.oldPrice)}
|
||
</span>
|
||
)}
|
||
</div>
|
||
) : (
|
||
<span className="text-red-400 font-medium">
|
||
Нет в наличии
|
||
</span>
|
||
)}
|
||
|
||
{product.inStock && product.quantity > 0 && (
|
||
<p className="text-green-400 text-xs">
|
||
В наличии: {product.quantity} шт.
|
||
</p>
|
||
)}
|
||
</div>
|
||
|
||
{/* Продавец */}
|
||
<div className="text-white/60 text-xs">
|
||
Продавец: {product.seller}
|
||
</div>
|
||
|
||
{/* Кнопки */}
|
||
<div className="flex gap-2 pt-2">
|
||
{product.inStock && product.price > 0 ? (
|
||
<>
|
||
<div className="flex items-center border border-white/30 rounded">
|
||
<Button
|
||
size="sm"
|
||
variant="ghost"
|
||
className="h-7 w-7 p-0 text-white hover:bg-white/20"
|
||
>
|
||
<Minus className="h-3 w-3" />
|
||
</Button>
|
||
<span className="px-2 text-white text-sm">
|
||
{cartQuantity}
|
||
</span>
|
||
<Button
|
||
size="sm"
|
||
variant="ghost"
|
||
className="h-7 w-7 p-0 text-white hover:bg-white/20"
|
||
>
|
||
<Plus className="h-3 w-3" />
|
||
</Button>
|
||
</div>
|
||
<Button
|
||
size="sm"
|
||
className="flex-1 bg-purple-600 hover:bg-purple-700 text-white"
|
||
>
|
||
<ShoppingCart className="h-3 w-3 mr-1" />В корзину
|
||
</Button>
|
||
</>
|
||
) : (
|
||
<Button
|
||
size="sm"
|
||
disabled
|
||
className="w-full bg-gray-600 text-white/50"
|
||
>
|
||
Недоступно
|
||
</Button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Карточка поставки фулфилмента */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">
|
||
Карточка поставки фулфилмента
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<Card className="glass-card p-4 hover:bg-white/10 transition-colors">
|
||
<div className="space-y-3">
|
||
{/* Компактный блок с названием магазина */}
|
||
<div className="flex items-center justify-between bg-white/5 rounded-lg p-2">
|
||
<div className="flex items-center gap-3">
|
||
<div className="p-1.5 bg-green-500/20 rounded">
|
||
<Store className="h-3 w-3 text-green-400" />
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-white font-medium text-sm">
|
||
{fulfillmentSupply.seller.storeName}
|
||
</span>
|
||
<span className="text-white/60 text-xs"> • </span>
|
||
<span className="text-white/80 text-xs">
|
||
{fulfillmentSupply.seller.managerName}
|
||
</span>
|
||
<span className="text-white/60 text-xs"> • </span>
|
||
<span className="text-white/80 text-xs">
|
||
{fulfillmentSupply.seller.phone}
|
||
</span>
|
||
<span className="text-white/60 text-xs"> • </span>
|
||
<div className="flex items-center gap-1">
|
||
<a
|
||
href={`https://t.me/${fulfillmentSupply.seller.phone.replace(
|
||
/[^\d]/g,
|
||
""
|
||
)}`}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="p-1 bg-blue-500/20 rounded hover:bg-blue-500/30 transition-colors"
|
||
title="Написать в Telegram"
|
||
>
|
||
<svg
|
||
className="h-3 w-3 text-blue-400"
|
||
viewBox="0 0 24 24"
|
||
fill="currentColor"
|
||
>
|
||
<path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z" />
|
||
</svg>
|
||
</a>
|
||
<a
|
||
href={`https://wa.me/${fulfillmentSupply.seller.phone.replace(
|
||
/[^\d]/g,
|
||
""
|
||
)}`}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="p-1 bg-green-500/20 rounded hover:bg-green-500/30 transition-colors"
|
||
title="Написать в WhatsApp"
|
||
>
|
||
<svg
|
||
className="h-3 w-3 text-green-400"
|
||
viewBox="0 0 24 24"
|
||
fill="currentColor"
|
||
>
|
||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893A11.821 11.821 0 0020.885 3.488" />
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
onClick={() => setExpandedSeller(!expandedSeller)}
|
||
className="h-6 w-6 p-0 text-white/60 hover:text-white hover:bg-white/10"
|
||
>
|
||
{expandedSeller ? (
|
||
<ChevronDown className="h-3 w-3" />
|
||
) : (
|
||
<ChevronRight className="h-3 w-3" />
|
||
)}
|
||
</Button>
|
||
</div>
|
||
|
||
{/* Скрытая детальная информация о магазине */}
|
||
{expandedSeller && (
|
||
<div className="bg-white/5 rounded-lg p-3 space-y-2">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<p className="text-white/60 text-xs">
|
||
Юридическое название
|
||
</p>
|
||
<p className="text-white text-sm">
|
||
{fulfillmentSupply.seller.name}
|
||
</p>
|
||
</div>
|
||
<div>
|
||
<p className="text-white/60 text-xs">ИНН</p>
|
||
<p className="text-white text-sm font-mono">
|
||
{fulfillmentSupply.seller.inn}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p className="text-white/60 text-xs">Email</p>
|
||
<p className="text-white text-sm">
|
||
{fulfillmentSupply.seller.email}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Единый блок со всеми параметрами в одной строке */}
|
||
<div className="bg-white/5 rounded-lg p-4">
|
||
<div className="grid grid-cols-2 lg:grid-cols-9 gap-4 items-center">
|
||
{/* Номер поставки */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Номер</p>
|
||
<p className="text-white font-semibold text-sm">
|
||
{fulfillmentSupply.supplyNumber}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Дата поставки */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Дата</p>
|
||
<p className="text-white font-semibold text-sm">
|
||
{formatDate(fulfillmentSupply.supplyDate)}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Количество товаров */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Товаров</p>
|
||
<p className="text-white font-semibold text-sm">
|
||
{fulfillmentSupply.itemsQuantity}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Количество мест */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Мест</p>
|
||
<p className="text-white font-semibold text-sm">
|
||
{fulfillmentSupply.cargoPlaces}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Объём */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Объём</p>
|
||
<p className="text-white font-semibold text-sm">
|
||
{fulfillmentSupply.volume} м³
|
||
</p>
|
||
</div>
|
||
|
||
{/* Стоимость */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Стоимость</p>
|
||
<p className="text-green-400 font-semibold text-sm">
|
||
{formatCurrency(fulfillmentSupply.totalValue)}
|
||
</p>
|
||
</div>
|
||
|
||
{/* Ответственный сотрудник */}
|
||
<div className="col-span-1">
|
||
<p className="text-white/60 text-xs mb-1">Ответственный</p>
|
||
<Select
|
||
defaultValue={fulfillmentSupply.responsibleEmployeeId}
|
||
>
|
||
<SelectTrigger className="h-8 glass-input bg-white/10 border-white/20 text-white hover:bg-white/15 focus:bg-white/15 focus:ring-1 focus:ring-purple-400/50 text-xs">
|
||
<SelectValue placeholder="Выберите" />
|
||
</SelectTrigger>
|
||
<SelectContent className="bg-gray-900/95 backdrop-blur border-white/20 text-white">
|
||
{employees.map((employee) => (
|
||
<SelectItem
|
||
key={employee.id}
|
||
value={employee.id}
|
||
className="text-white hover:bg-white/10 focus:bg-white/10 text-xs"
|
||
>
|
||
<div className="flex flex-col">
|
||
<span className="font-medium">
|
||
{employee.firstName} {employee.lastName}
|
||
</span>
|
||
<span className="text-xs text-white/60">
|
||
{employee.position}
|
||
</span>
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* Логистический партнер */}
|
||
<div className="col-span-1">
|
||
<p className="text-white/60 text-xs mb-1">Логистика</p>
|
||
<Select defaultValue={fulfillmentSupply.logisticsPartnerId}>
|
||
<SelectTrigger className="h-8 glass-input bg-white/10 border-white/20 text-white hover:bg-white/15 focus:bg-white/15 focus:ring-1 focus:ring-orange-400/50 text-xs">
|
||
<SelectValue placeholder="Выберите" />
|
||
</SelectTrigger>
|
||
<SelectContent className="bg-gray-900/95 backdrop-blur border-white/20 text-white">
|
||
{logisticsPartners.map((partner) => (
|
||
<SelectItem
|
||
key={partner.id}
|
||
value={partner.id}
|
||
className="text-white hover:bg-white/10 focus:bg-white/10 text-xs"
|
||
>
|
||
<div className="flex flex-col">
|
||
<span className="font-medium">
|
||
{partner.name ||
|
||
partner.fullName ||
|
||
"Без названия"}
|
||
</span>
|
||
<span className="text-xs text-white/60">
|
||
Логистический партнер
|
||
</span>
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* Статус */}
|
||
<div className="text-center">
|
||
<p className="text-white/60 text-xs mb-1">Статус</p>
|
||
<div className="flex justify-center">
|
||
{getStatusBadge(fulfillmentSupply.status)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Карточки поставщиков */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Карточки поставщиков</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||
{wholesalers.map((wholesaler) => (
|
||
<div
|
||
key={wholesaler.id}
|
||
className="glass-card p-6 rounded-lg border border-white/10 hover:border-white/30 transition-all"
|
||
>
|
||
{/* Заголовок карточки */}
|
||
<div className="flex items-start gap-4 mb-4">
|
||
<Avatar className="h-16 w-16">
|
||
<AvatarImage src={wholesaler.avatar} />
|
||
<AvatarFallback className="bg-purple-600 text-white text-lg">
|
||
{wholesaler.name.charAt(0)}
|
||
</AvatarFallback>
|
||
</Avatar>
|
||
|
||
<div className="flex-1 min-w-0">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<h4 className="text-white font-semibold text-lg truncate">
|
||
{wholesaler.name}
|
||
</h4>
|
||
{wholesaler.verifiedBadges.includes("verified") && (
|
||
<Badge className="bg-green-600 text-white text-xs">
|
||
Проверен
|
||
</Badge>
|
||
)}
|
||
{wholesaler.verifiedBadges.includes("premium") && (
|
||
<Badge className="bg-yellow-600 text-white text-xs">
|
||
Premium
|
||
</Badge>
|
||
)}
|
||
</div>
|
||
|
||
<p className="text-white/70 text-sm mb-2">
|
||
{wholesaler.fullName}
|
||
</p>
|
||
<p className="text-white/60 text-xs">
|
||
ИНН: {wholesaler.inn}
|
||
</p>
|
||
|
||
{/* Рейтинг и статистика */}
|
||
<div className="flex items-center gap-4 mt-2 text-sm">
|
||
<div className="flex items-center gap-1">
|
||
<Star className="h-4 w-4 fill-yellow-400 text-yellow-400" />
|
||
<span className="text-white">{wholesaler.rating}</span>
|
||
<span className="text-white/60">
|
||
({wholesaler.reviewsCount})
|
||
</span>
|
||
</div>
|
||
<div className="text-white/60">
|
||
{wholesaler.completedOrders} заказов
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Описание */}
|
||
<p className="text-white/70 text-sm mb-4 line-clamp-2">
|
||
{wholesaler.description}
|
||
</p>
|
||
|
||
{/* Статистика */}
|
||
<div className="grid grid-cols-2 gap-4 mb-4">
|
||
<div className="bg-white/5 rounded-lg p-3">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<Package className="h-4 w-4 text-purple-400" />
|
||
<span className="text-white/70 text-xs">Товаров</span>
|
||
</div>
|
||
<div className="text-white font-bold">
|
||
{wholesaler.productsCount.toLocaleString()}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="bg-white/5 rounded-lg p-3">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<Clock className="h-4 w-4 text-green-400" />
|
||
<span className="text-white/70 text-xs">Ответ</span>
|
||
</div>
|
||
<div className="text-white font-bold">
|
||
{wholesaler.responseTime}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Категории */}
|
||
<div className="mb-4">
|
||
<p className="text-white/70 text-xs mb-2">Категории:</p>
|
||
<div className="flex flex-wrap gap-1">
|
||
{wholesaler.categories.map((category, index) => (
|
||
<Badge
|
||
key={index}
|
||
variant="outline"
|
||
className="text-xs border-white/30 text-white/70"
|
||
>
|
||
{category}
|
||
</Badge>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Дополнительная информация */}
|
||
<div className="space-y-2 mb-4 text-sm">
|
||
<div className="flex items-center gap-2 text-white/60">
|
||
<MapPin className="h-3 w-3" />
|
||
<span>{wholesaler.location}</span>
|
||
</div>
|
||
<div className="flex items-center gap-2 text-white/60">
|
||
<Calendar className="h-3 w-3" />
|
||
<span>Работает с {wholesaler.workingSince} года</span>
|
||
</div>
|
||
<div className="flex items-center gap-2 text-white/60">
|
||
<Briefcase className="h-3 w-3" />
|
||
<span>Мин. заказ: {formatPrice(wholesaler.minOrder)}</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Специальные предложения */}
|
||
{wholesaler.specialOffers > 0 && (
|
||
<div className="bg-orange-500/20 border border-orange-500/30 rounded-lg p-3 mb-4">
|
||
<div className="flex items-center gap-2">
|
||
<Award className="h-4 w-4 text-orange-400" />
|
||
<span className="text-orange-200 font-medium text-sm">
|
||
{wholesaler.specialOffers} специальных предложения
|
||
</span>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Кнопки действий */}
|
||
<div className="flex gap-2">
|
||
<Button className="flex-1 bg-purple-600 hover:bg-purple-700 text-white">
|
||
<Eye className="h-4 w-4 mr-2" />
|
||
Смотреть товары
|
||
</Button>
|
||
<Button
|
||
variant="outline"
|
||
className="bg-white/10 hover:bg-white/20 text-white border-white/30"
|
||
>
|
||
<Phone className="h-4 w-4" />
|
||
</Button>
|
||
<Button
|
||
variant="outline"
|
||
className="bg-white/10 hover:bg-white/20 text-white border-white/30"
|
||
>
|
||
<Mail className="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Космически-галактические табели рабочего времени */}
|
||
<TimesheetDemo />
|
||
</div>
|
||
);
|
||
}
|