Добавлены новые зависимости: react-datepicker и обновлены импорты в компоненте WBProductCards. Реализован новый функционал для выбора даты поставки с использованием календаря. Обновлены компоненты для улучшения взаимодействия с пользователем и оптимизации кода.
This commit is contained in:
183
src/components/supplies/product-card.tsx
Normal file
183
src/components/supplies/product-card.tsx
Normal 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>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user