Добавлены новые зависимости: 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,183 @@
"use client"
import React from 'react'
import { Card } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
Plus,
Minus,
Eye,
Heart,
ShoppingCart
} from 'lucide-react'
import { WholesalerProduct } from './types'
interface ProductCardProps {
product: WholesalerProduct
selectedQuantity: number
onQuantityChange: (quantity: number) => void
formatCurrency: (amount: number) => string
}
export function ProductCard({
product,
selectedQuantity,
onQuantityChange,
formatCurrency
}: ProductCardProps) {
const discountedPrice = product.discount
? product.price * (1 - product.discount / 100)
: product.price
const handleQuantityChange = (newQuantity: number) => {
const clampedQuantity = Math.max(0, Math.min(product.quantity, newQuantity))
onQuantityChange(clampedQuantity)
}
return (
<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">
<img
src={product.mainImage || '/api/placeholder/400/400'}
alt={product.name}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
/>
{/* Количество в наличии */}
<div className="absolute top-2 right-2">
<Badge className={`${
product.quantity > 50
? 'bg-green-500/80'
: product.quantity > 10
? 'bg-yellow-500/80'
: 'bg-red-500/80'
} text-white border-0 backdrop-blur text-xs`}>
{product.quantity}
</Badge>
</div>
{/* Скидка */}
{product.discount && (
<div className="absolute top-2 left-2">
<Badge className="bg-red-500/80 text-white border-0 backdrop-blur text-xs">
-{product.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">
{product.brand && (
<Badge className="bg-gray-500/20 text-gray-300 border-gray-500/30 text-xs">
{product.brand}
</Badge>
)}
<div className="flex items-center space-x-1">
{product.isNew && (
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-xs">
NEW
</Badge>
)}
{product.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">
{product.name}
</h3>
</div>
{/* Основная характеристика */}
<div className="text-white/60 text-xs">
{product.color && <span className="text-white">{product.color}</span>}
{product.size && <span className="text-white ml-2">{product.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>
{product.discount && (
<div className="text-white/40 text-sm line-through">
{formatCurrency(product.price)}
</div>
)}
</div>
</div>
{/* Управление количеством */}
<div className="flex items-center space-x-2">
<Button
variant="ghost"
size="sm"
onClick={() => handleQuantityChange(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"
inputMode="numeric"
pattern="[0-9]*"
value={selectedQuantity}
onChange={(e) => {
const value = e.target.value.replace(/[^0-9]/g, '')
const numValue = parseInt(value) || 0
handleQuantityChange(numValue)
}}
onFocus={(e) => e.target.select()}
className="h-8 w-12 text-center bg-white/10 border border-white/20 text-white text-sm rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
/>
<Button
variant="ghost"
size="sm"
onClick={() => handleQuantityChange(selectedQuantity + 1)}
disabled={selectedQuantity >= product.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>
)
}