Добавлены новые зависимости: react-datepicker и обновлены импорты в компоненте WBProductCards. Реализован новый функционал для выбора даты поставки с использованием календаря. Обновлены компоненты для улучшения взаимодействия с пользователем и оптимизации кода.

This commit is contained in:
Bivekich
2025-07-23 15:16:10 +03:00
parent 5bb38574fe
commit 158411cc98
15 changed files with 1896 additions and 1079 deletions

View File

@ -0,0 +1,634 @@
"use client";
import React, { useState } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
ShoppingCart,
Plus,
Minus,
Eye,
Heart,
Package,
Building2,
Calendar,
Users,
Search,
Star,
Truck
} from "lucide-react";
export function SuppliesDemo() {
const [selectedQuantity, setSelectedQuantity] = useState(1);
const [cartItems, setCartItems] = useState(3);
const [cartTotal, setCartTotal] = useState(15750);
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
minimumFractionDigits: 0
}).format(amount);
};
const mockProduct = {
id: "1",
name: "Футболка мужская базовая хлопок 100%",
brand: "BASIC",
price: 1299,
discount: 15,
quantity: 47,
color: "Черный",
size: "L",
mainImage: "/api/placeholder/300/300",
isNew: true,
isBestseller: false
};
const mockWholesaler = {
id: "w1",
name: "ТекстильПром ООО",
rating: 4.8,
reviewsCount: 1247,
location: "Москва",
specialization: "Текстиль и одежда",
verified: true
};
const discountedPrice = mockProduct.discount
? mockProduct.price * (1 - mockProduct.discount / 100)
: mockProduct.price;
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>
<Tabs defaultValue="product-cards" className="w-full">
<TabsList className="grid grid-cols-4 bg-white/5 backdrop-blur border-white/10 mb-6">
<TabsTrigger value="product-cards">Карточки товаров</TabsTrigger>
<TabsTrigger value="wholesaler-cards">Карточки оптовиков</TabsTrigger>
<TabsTrigger value="floating-cart">Плавающая корзина</TabsTrigger>
<TabsTrigger value="supply-types">Типы поставок</TabsTrigger>
</TabsList>
<TabsContent value="product-cards" className="space-y-6">
<div>
<h3 className="text-xl font-semibold text-white mb-4">Карточки товаров</h3>
<p className="text-white/60 mb-6">
Интерактивные карточки товаров с возможностью управления количеством
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Обычная карточка товара */}
<Card className="bg-white/10 backdrop-blur border-white/20 overflow-hidden group hover:bg-white/15 hover:border-white/30 transition-all duration-300 hover:scale-105 hover:shadow-2xl">
<div className="aspect-square relative bg-white/5 overflow-hidden">
<div className="w-full h-full bg-gradient-to-br from-purple-500/20 to-pink-500/20 flex items-center justify-center">
<Package className="h-16 w-16 text-white/40" />
</div>
{/* Количество в наличии */}
<div className="absolute top-2 right-2">
<Badge className={`${
mockProduct.quantity > 50
? 'bg-green-500/80'
: mockProduct.quantity > 10
? 'bg-yellow-500/80'
: 'bg-red-500/80'
} text-white border-0 backdrop-blur text-xs`}>
{mockProduct.quantity}
</Badge>
</div>
{/* Скидка */}
{mockProduct.discount && (
<div className="absolute top-2 left-2">
<Badge className="bg-red-500/80 text-white border-0 backdrop-blur text-xs">
-{mockProduct.discount}%
</Badge>
</div>
)}
{/* Overlay с кнопками */}
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<div className="flex space-x-2">
<Button size="sm" variant="secondary" className="bg-white/20 backdrop-blur text-white border-white/30 hover:bg-white/30">
<Eye className="h-4 w-4" />
</Button>
<Button size="sm" variant="secondary" className="bg-white/20 backdrop-blur text-white border-white/30 hover:bg-white/30">
<Heart className="h-4 w-4" />
</Button>
</div>
</div>
</div>
<div className="p-3 space-y-3">
{/* Заголовок и бренд */}
<div>
<div className="flex items-center justify-between mb-1">
{mockProduct.brand && (
<Badge className="bg-gray-500/20 text-gray-300 border-gray-500/30 text-xs">
{mockProduct.brand}
</Badge>
)}
<div className="flex items-center space-x-1">
{mockProduct.isNew && (
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-xs">
NEW
</Badge>
)}
{mockProduct.isBestseller && (
<Badge className="bg-orange-500/20 text-orange-300 border-orange-500/30 text-xs">
HIT
</Badge>
)}
</div>
</div>
<h3 className="text-white font-semibold text-sm mb-1 line-clamp-2 leading-tight">
{mockProduct.name}
</h3>
</div>
{/* Основная характеристика */}
<div className="text-white/60 text-xs">
{mockProduct.color && <span className="text-white">{mockProduct.color}</span>}
{mockProduct.size && <span className="text-white ml-2">{mockProduct.size}</span>}
</div>
{/* Цена */}
<div className="pt-2 border-t border-white/10">
<div className="flex items-center space-x-2">
<div className="text-white font-bold text-lg">
{formatCurrency(discountedPrice)}
</div>
{mockProduct.discount && (
<div className="text-white/40 text-sm line-through">
{formatCurrency(mockProduct.price)}
</div>
)}
</div>
</div>
{/* Управление количеством */}
<div className="flex items-center space-x-2">
<Button
variant="ghost"
size="sm"
onClick={() => setSelectedQuantity(Math.max(0, selectedQuantity - 1))}
disabled={selectedQuantity === 0}
className="h-8 w-8 p-0 text-white/60 hover:text-white hover:bg-white/10 border border-white/20"
>
<Minus className="h-3 w-3" />
</Button>
<Input
type="text"
value={selectedQuantity}
onChange={(e) => {
const value = e.target.value.replace(/[^0-9]/g, '');
const numValue = parseInt(value) || 0;
setSelectedQuantity(Math.min(mockProduct.quantity, numValue));
}}
className="h-8 w-12 text-center bg-white/10 border-white/20 text-white text-sm"
/>
<Button
variant="ghost"
size="sm"
onClick={() => setSelectedQuantity(Math.min(mockProduct.quantity, selectedQuantity + 1))}
disabled={selectedQuantity >= mockProduct.quantity}
className="h-8 w-8 p-0 text-white/60 hover:text-white hover:bg-white/10 border border-white/20"
>
<Plus className="h-3 w-3" />
</Button>
{selectedQuantity > 0 && (
<Badge className="bg-gradient-to-r from-purple-500 to-pink-500 text-white border-0 text-xs ml-auto">
<ShoppingCart className="h-3 w-3 mr-1" />
{selectedQuantity}
</Badge>
)}
</div>
{/* Сумма для выбранного товара */}
{selectedQuantity > 0 && (
<div className="bg-gradient-to-r from-green-500/20 to-emerald-500/20 border border-green-500/30 rounded p-2">
<div className="text-green-300 text-xs font-medium text-center">
{formatCurrency(discountedPrice * selectedQuantity)}
</div>
</div>
)}
</div>
</Card>
{/* Компактная карточка товара */}
<Card className="bg-white/10 backdrop-blur border-white/20 p-4 hover:bg-white/15 transition-colors">
<div className="flex items-center space-x-3">
<div className="w-16 h-16 bg-gradient-to-br from-blue-500/20 to-cyan-500/20 rounded flex items-center justify-center">
<Package className="h-8 w-8 text-white/40" />
</div>
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm truncate">Товар компактно</h4>
<p className="text-white/60 text-xs">Краткое описание</p>
<div className="flex items-center justify-between mt-2">
<span className="text-white font-bold text-sm">{formatCurrency(1599)}</span>
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-xs">
В наличии
</Badge>
</div>
</div>
</div>
</Card>
{/* Карточка товара со статусом */}
<Card className="bg-white/10 backdrop-blur border-white/20 p-4">
<div className="space-y-3">
<div className="flex items-center justify-between">
<Badge className="bg-orange-500/20 text-orange-300 border-orange-500/30 text-xs">
Ожидается
</Badge>
<span className="text-white/60 text-xs">Арт: TB-001</span>
</div>
<h4 className="text-white font-medium text-sm">Товар с уведомлением</h4>
<div className="text-white/60 text-xs">
<p>Поступление: 15 марта</p>
<p>Количество: ~200 шт</p>
</div>
<div className="flex items-center justify-between">
<span className="text-white font-bold">{formatCurrency(899)}</span>
<Button size="sm" variant="outline" className="border-white/20 text-white text-xs">
Уведомить
</Button>
</div>
</div>
</Card>
</div>
</div>
</TabsContent>
<TabsContent value="wholesaler-cards" className="space-y-6">
<div>
<h3 className="text-xl font-semibold text-white mb-4">Карточки оптовиков</h3>
<p className="text-white/60 mb-6">
Информационные карточки поставщиков и оптовиков
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Главная карточка оптовика */}
<Card className="bg-white/10 backdrop-blur border-white/20 p-6 hover:bg-white/15 hover:border-white/30 transition-all duration-300 hover:scale-105">
<div className="space-y-4">
<div className="flex items-start justify-between">
<div className="flex items-center space-x-3">
<div className="w-12 h-12 bg-gradient-to-br from-purple-500 to-pink-500 rounded-full flex items-center justify-center">
<Building2 className="h-6 w-6 text-white" />
</div>
<div>
<h3 className="text-white font-semibold text-lg">
{mockWholesaler.name}
</h3>
<p className="text-white/60 text-sm">
{mockWholesaler.specialization}
</p>
</div>
</div>
{mockWholesaler.verified && (
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
Верифицирован
</Badge>
)}
</div>
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="text-white/60 text-sm">Рейтинг:</span>
<div className="flex items-center space-x-1">
<div className="flex">
{Array.from({ length: 5 }, (_, i) => (
<Star
key={i}
className={`h-4 w-4 ${
i < Math.floor(mockWholesaler.rating)
? 'text-yellow-400 fill-current'
: 'text-gray-400'
}`}
/>
))}
</div>
<span className="text-white text-sm font-medium">
{mockWholesaler.rating}
</span>
</div>
</div>
<div className="flex items-center justify-between">
<span className="text-white/60 text-sm">Отзывы:</span>
<span className="text-white text-sm">
{mockWholesaler.reviewsCount.toLocaleString('ru-RU')}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-white/60 text-sm">Местоположение:</span>
<span className="text-white text-sm">{mockWholesaler.location}</span>
</div>
</div>
<div className="flex space-x-2">
<Button
size="sm"
className="flex-1 bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white"
>
<Package className="h-4 w-4 mr-2" />
Товары
</Button>
<Button
size="sm"
variant="outline"
className="border-white/20 text-white hover:bg-white/10"
>
<Eye className="h-4 w-4" />
</Button>
</div>
</div>
</Card>
{/* Компактная карточка поставщика */}
<Card className="bg-white/10 backdrop-blur border-white/20 p-4 hover:bg-white/15 transition-colors">
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-gradient-to-br from-green-500 to-emerald-500 rounded-full flex items-center justify-center">
<Truck className="h-5 w-5 text-white" />
</div>
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm">Логистический партнер</h4>
<p className="text-white/60 text-xs">Быстрая доставка</p>
<div className="flex items-center mt-1">
<div className="flex">
{Array.from({ length: 5 }, (_, i) => (
<Star key={i} className="h-3 w-3 text-yellow-400 fill-current" />
))}
</div>
<span className="text-white/60 text-xs ml-1">(4.9)</span>
</div>
</div>
</div>
</Card>
{/* Карточка нового поставщика */}
<Card className="bg-gradient-to-br from-blue-500/10 to-cyan-500/10 backdrop-blur border-blue-500/30 p-4">
<div className="space-y-3">
<div className="flex items-center justify-between">
<Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30 text-xs">
Новый партнер
</Badge>
<Users className="h-5 w-5 text-blue-400" />
</div>
<h4 className="text-white font-medium">ТехноТрейд ООО</h4>
<p className="text-white/60 text-sm">
Электроника и техника
</p>
<div className="flex items-center justify-between">
<span className="text-white/60 text-xs">Заявка на партнерство</span>
<Button size="sm" variant="outline" className="border-blue-500/30 text-blue-300 text-xs">
Рассмотреть
</Button>
</div>
</div>
</Card>
</div>
</div>
</TabsContent>
<TabsContent value="floating-cart" className="space-y-6">
<div>
<h3 className="text-xl font-semibold text-white mb-4">Плавающая корзина</h3>
<p className="text-white/60 mb-6">
Плавающий элемент для быстрого доступа к корзине
</p>
<div className="space-y-6">
{/* Демонстрация плавающей корзины */}
<div className="relative bg-gray-900/50 border border-white/10 rounded-lg p-8 min-h-[300px]">
<p className="text-white/60 text-center">
Область контента страницы
<br />
<span className="text-xs">Плавающая корзина появляется в правом нижнем углу</span>
</p>
{/* Демо плавающей корзины */}
<div className="absolute bottom-4 right-4">
<Button
size="lg"
className="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-2xl"
onClick={() => {
setCartItems(cartItems + 1);
setCartTotal(cartTotal + 1299);
}}
>
<ShoppingCart className="h-5 w-5 mr-2" />
{cartItems} {formatCurrency(cartTotal)}
</Button>
</div>
</div>
{/* Различные варианты плавающих кнопок */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card className="bg-white/10 backdrop-blur border-white/20 p-4">
<h4 className="text-white font-medium mb-3">Стандартная корзина</h4>
<Button
className="w-full bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white"
>
<ShoppingCart className="h-4 w-4 mr-2" />
3 {formatCurrency(cartTotal)}
</Button>
</Card>
<Card className="bg-white/10 backdrop-blur border-white/20 p-4">
<h4 className="text-white font-medium mb-3">Компактная</h4>
<Button size="sm" className="w-full bg-gradient-to-r from-green-500 to-emerald-500 text-white">
<ShoppingCart className="h-4 w-4 mr-1" />
{formatCurrency(cartTotal)}
</Button>
</Card>
<Card className="bg-white/10 backdrop-blur border-white/20 p-4">
<h4 className="text-white font-medium mb-3">С индикатором</h4>
<div className="relative">
<Button className="w-full bg-gradient-to-r from-orange-500 to-red-500 text-white">
<ShoppingCart className="h-4 w-4 mr-2" />
Корзина
</Button>
<Badge className="absolute -top-2 -right-2 bg-red-500 text-white text-xs">
{cartItems}
</Badge>
</div>
</Card>
</div>
{/* Кнопки управления демо */}
<div className="flex justify-center space-x-4">
<Button
variant="outline"
size="sm"
className="border-white/20 text-white"
onClick={() => {
setCartItems(Math.max(0, cartItems - 1));
setCartTotal(Math.max(0, cartTotal - 1299));
}}
>
<Minus className="h-4 w-4 mr-1" />
Убрать товар
</Button>
<Button
variant="outline"
size="sm"
className="border-white/20 text-white"
onClick={() => {
setCartItems(cartItems + 1);
setCartTotal(cartTotal + 1299);
}}
>
<Plus className="h-4 w-4 mr-1" />
Добавить товар
</Button>
<Button
variant="outline"
size="sm"
className="border-red-500/30 text-red-300"
onClick={() => {
setCartItems(0);
setCartTotal(0);
}}
>
Очистить корзину
</Button>
</div>
</div>
</div>
</TabsContent>
<TabsContent value="supply-types" className="space-y-6">
<div>
<h3 className="text-xl font-semibold text-white mb-4">Типы поставок</h3>
<p className="text-white/60 mb-6">
Различные варианты выбора типа поставки
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Вариант 1: Карточки */}
<Card
className="bg-white/10 backdrop-blur border-white/20 p-6 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30"
>
<div className="text-center space-y-4">
<div className="p-4 bg-blue-500/20 rounded-lg w-fit mx-auto">
<ShoppingCart className="h-8 w-8 text-blue-400" />
</div>
<div>
<h3 className="text-xl font-semibold text-white mb-2">Карточки</h3>
<p className="text-white/60 text-sm">
Создание поставки через выбор товаров по карточкам
</p>
</div>
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
Доступно
</Badge>
</div>
</Card>
{/* Вариант 2: Оптовик */}
<Card
className="bg-white/10 backdrop-blur border-white/20 p-6 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30"
>
<div className="text-center space-y-4">
<div className="p-4 bg-green-500/20 rounded-lg w-fit mx-auto">
<Users className="h-8 w-8 text-green-400" />
</div>
<div>
<h3 className="text-xl font-semibold text-white mb-2">Оптовик</h3>
<p className="text-white/60 text-sm">
Создание поставки через выбор товаров у оптовиков
</p>
</div>
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
Доступно
</Badge>
</div>
</Card>
{/* Дополнительные типы */}
<Card className="bg-white/10 backdrop-blur border-white/20 p-6 opacity-60">
<div className="text-center space-y-4">
<div className="p-4 bg-gray-500/20 rounded-lg w-fit mx-auto">
<Package className="h-8 w-8 text-gray-400" />
</div>
<div>
<h3 className="text-xl font-semibold text-white mb-2">Импорт</h3>
<p className="text-white/60 text-sm">
Массовый импорт товаров из файла
</p>
</div>
<Badge className="bg-gray-500/20 text-gray-300 border-gray-500/30">
Скоро
</Badge>
</div>
</Card>
<Card className="bg-white/10 backdrop-blur border-white/20 p-6 opacity-60">
<div className="text-center space-y-4">
<div className="p-4 bg-purple-500/20 rounded-lg w-fit mx-auto">
<Calendar className="h-8 w-8 text-purple-400" />
</div>
<div>
<h3 className="text-xl font-semibold text-white mb-2">Регулярные</h3>
<p className="text-white/60 text-sm">
Автоматические поставки по расписанию
</p>
</div>
<Badge className="bg-gray-500/20 text-gray-300 border-gray-500/30">
В разработке
</Badge>
</div>
</Card>
</div>
{/* Статусы поставок */}
<div className="mt-8">
<h4 className="text-lg font-semibold text-white mb-4">Статусы поставок</h4>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center space-y-2">
<Badge className="bg-yellow-500/20 text-yellow-300 border-yellow-500/30">
Подготовка
</Badge>
<p className="text-white/60 text-xs">Сбор товаров</p>
</div>
<div className="text-center space-y-2">
<Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30">
В пути
</Badge>
<p className="text-white/60 text-xs">Доставка</p>
</div>
<div className="text-center space-y-2">
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
Доставлено
</Badge>
<p className="text-white/60 text-xs">Успешно</p>
</div>
<div className="text-center space-y-2">
<Badge className="bg-red-500/20 text-red-300 border-red-500/30">
Ошибка
</Badge>
<p className="text-white/60 text-xs">Требует внимания</p>
</div>
</div>
</div>
</div>
</TabsContent>
</Tabs>
</div>
);
}