Files
sfera/src/components/supplies/wholesaler-products.tsx

425 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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 {
ArrowLeft,
Package,
Plus,
Minus,
ShoppingCart,
Eye,
Info
} from 'lucide-react'
import Image from 'next/image'
interface Wholesaler {
id: string
inn: string
name: string
fullName: string
address: string
phone?: string
email?: string
rating: number
productCount: number
avatar?: string
specialization: string[]
}
interface Product {
id: string
name: string
article: string
description: string
price: number
quantity: number
category: string
brand?: string
color?: string
size?: string
weight?: number
dimensions?: string
material?: string
images: string[]
mainImage?: string
}
interface SelectedProduct extends Product {
selectedQuantity: number
}
interface WholesalerProductsProps {
wholesaler: Wholesaler
onBack: () => void
onClose: () => void
onSupplyCreated: () => void
}
// Моковые данные товаров
const mockProducts: Product[] = [
{
id: '1',
name: 'Смартфон Samsung Galaxy A54',
article: 'SGX-A54-128',
description: 'Смартфон с экраном 6.4", камерой 50 МП, 128 ГБ памяти',
price: 28900,
quantity: 150,
category: 'Смартфоны',
brand: 'Samsung',
color: 'Черный',
size: '6.4"',
weight: 202,
dimensions: '158.2 x 76.7 x 8.2 мм',
material: 'Алюминий, стекло',
images: ['/api/placeholder/300/300?text=Samsung+A54'],
mainImage: '/api/placeholder/300/300?text=Samsung+A54'
},
{
id: '2',
name: 'Наушники Sony WH-1000XM4',
article: 'SNY-WH1000XM4',
description: 'Беспроводные наушники с шумоподавлением',
price: 24900,
quantity: 85,
category: 'Наушники',
brand: 'Sony',
color: 'Черный',
weight: 254,
material: 'Пластик, кожа',
images: ['/api/placeholder/300/300?text=Sony+WH1000XM4'],
mainImage: '/api/placeholder/300/300?text=Sony+WH1000XM4'
},
{
id: '3',
name: 'Планшет iPad Air 10.9"',
article: 'APL-IPADAIR-64',
description: 'Планшет Apple iPad Air с чипом M1, 64 ГБ',
price: 54900,
quantity: 45,
category: 'Планшеты',
brand: 'Apple',
color: 'Серый космос',
size: '10.9"',
weight: 461,
dimensions: '247.6 x 178.5 x 6.1 мм',
material: 'Алюминий',
images: ['/api/placeholder/300/300?text=iPad+Air'],
mainImage: '/api/placeholder/300/300?text=iPad+Air'
},
{
id: '4',
name: 'Ноутбук Lenovo ThinkPad E15',
article: 'LNV-TE15-I5',
description: 'Ноутбук 15.6" Intel Core i5, 8 ГБ ОЗУ, 256 ГБ SSD',
price: 45900,
quantity: 25,
category: 'Ноутбуки',
brand: 'Lenovo',
color: 'Черный',
size: '15.6"',
weight: 1700,
dimensions: '365 x 240 x 19.9 мм',
material: 'Пластик',
images: ['/api/placeholder/300/300?text=ThinkPad+E15'],
mainImage: '/api/placeholder/300/300?text=ThinkPad+E15'
},
{
id: '5',
name: 'Умные часы Apple Watch SE',
article: 'APL-AWSE-40',
description: 'Умные часы Apple Watch SE 40 мм',
price: 21900,
quantity: 120,
category: 'Умные часы',
brand: 'Apple',
color: 'Белый',
size: '40 мм',
weight: 30,
dimensions: '40 x 34 x 10.7 мм',
material: 'Алюминий',
images: ['/api/placeholder/300/300?text=Apple+Watch+SE'],
mainImage: '/api/placeholder/300/300?text=Apple+Watch+SE'
},
{
id: '6',
name: 'Клавиатура Logitech MX Keys',
article: 'LGT-MXKEYS',
description: 'Беспроводная клавиатура для продуктивной работы',
price: 8900,
quantity: 75,
category: 'Клавиатуры',
brand: 'Logitech',
color: 'Графит',
weight: 810,
dimensions: '430.2 x 20.5 x 131.6 мм',
material: 'Пластик, металл',
images: ['/api/placeholder/300/300?text=MX+Keys'],
mainImage: '/api/placeholder/300/300?text=MX+Keys'
}
]
export function WholesalerProducts({ wholesaler, onBack, onClose, onSupplyCreated }: WholesalerProductsProps) {
const [selectedProducts, setSelectedProducts] = useState<SelectedProduct[]>([])
const [showSummary, setShowSummary] = useState(false)
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
minimumFractionDigits: 0
}).format(amount)
}
const updateProductQuantity = (productId: string, quantity: number) => {
const product = mockProducts.find(p => p.id === productId)
if (!product) return
setSelectedProducts(prev => {
const existing = prev.find(p => p.id === productId)
if (quantity === 0) {
// Удаляем продукт если количество 0
return prev.filter(p => p.id !== productId)
}
if (existing) {
// Обновляем количество существующего продукта
return prev.map(p =>
p.id === productId ? { ...p, selectedQuantity: quantity } : p
)
} else {
// Добавляем новый продукт
return [...prev, { ...product, selectedQuantity: quantity }]
}
})
}
const getSelectedQuantity = (productId: string): number => {
const selected = selectedProducts.find(p => p.id === productId)
return selected ? selected.selectedQuantity : 0
}
const getTotalAmount = () => {
return selectedProducts.reduce((sum, product) =>
sum + (product.price * product.selectedQuantity), 0
)
}
const getTotalItems = () => {
return selectedProducts.reduce((sum, product) => sum + product.selectedQuantity, 0)
}
const handleCreateSupply = () => {
console.log('Создание поставки с товарами:', selectedProducts)
// TODO: Здесь будет реальное создание поставки
onSupplyCreated()
}
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<Button
variant="ghost"
size="sm"
onClick={onBack}
className="text-white/60 hover:text-white hover:bg-white/10"
>
<ArrowLeft className="h-4 w-4 mr-2" />
Назад
</Button>
<div>
<h2 className="text-2xl font-bold text-white mb-1">Товары оптовика</h2>
<p className="text-white/60">{wholesaler.name} {mockProducts.length} товаров</p>
</div>
</div>
<div className="flex items-center space-x-3">
<Button
variant="ghost"
size="sm"
onClick={() => setShowSummary(!showSummary)}
className="text-white/60 hover:text-white hover:bg-white/10"
>
<Info className="h-4 w-4 mr-2" />
Резюме ({selectedProducts.length})
</Button>
<Button
variant="ghost"
size="sm"
onClick={onClose}
className="text-white/60 hover:text-white hover:bg-white/10"
>
Отмена
</Button>
</div>
</div>
{showSummary && selectedProducts.length > 0 && (
<Card className="bg-purple-500/10 backdrop-blur border-purple-500/30 p-6">
<h3 className="text-white font-semibold text-lg mb-4">Резюме заказа</h3>
<div className="space-y-3">
{selectedProducts.map((product) => (
<div key={product.id} className="flex justify-between items-center">
<div>
<span className="text-white">{product.name}</span>
<span className="text-white/60 text-sm ml-2">× {product.selectedQuantity}</span>
</div>
<span className="text-white font-medium">
{formatCurrency(product.price * product.selectedQuantity)}
</span>
</div>
))}
<div className="border-t border-white/20 pt-3 flex justify-between items-center">
<span className="text-white font-semibold">
Итого: {getTotalItems()} товаров
</span>
<span className="text-white font-bold text-xl">
{formatCurrency(getTotalAmount())}
</span>
</div>
<Button
className="w-full bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white"
onClick={handleCreateSupply}
disabled={selectedProducts.length === 0}
>
<ShoppingCart className="h-4 w-4 mr-2" />
Создать поставку
</Button>
</div>
</Card>
)}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{mockProducts.map((product) => {
const selectedQuantity = getSelectedQuantity(product.id)
return (
<Card key={product.id} className="bg-white/10 backdrop-blur border-white/20 overflow-hidden">
<div className="aspect-square relative bg-white/5">
<Image
src={product.mainImage || '/api/placeholder/300/300'}
alt={product.name}
fill
className="object-cover"
/>
<div className="absolute top-2 right-2">
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
В наличии: {product.quantity}
</Badge>
</div>
</div>
<div className="p-4 space-y-3">
<div>
<h3 className="text-white font-semibold mb-1 line-clamp-2">
{product.name}
</h3>
<p className="text-white/60 text-xs mb-2">
Артикул: {product.article}
</p>
<div className="flex items-center space-x-2 mb-2">
<Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30 text-xs">
{product.category}
</Badge>
{product.brand && (
<Badge className="bg-gray-500/20 text-gray-300 border-gray-500/30 text-xs">
{product.brand}
</Badge>
)}
</div>
</div>
<p className="text-white/60 text-sm line-clamp-2">
{product.description}
</p>
<div className="space-y-2">
{product.color && (
<div className="text-white/60 text-xs">
Цвет: <span className="text-white">{product.color}</span>
</div>
)}
{product.size && (
<div className="text-white/60 text-xs">
Размер: <span className="text-white">{product.size}</span>
</div>
)}
{product.weight && (
<div className="text-white/60 text-xs">
Вес: <span className="text-white">{product.weight} г</span>
</div>
)}
</div>
<div className="flex items-center justify-between pt-2 border-t border-white/10">
<div>
<div className="text-white font-bold text-lg">
{formatCurrency(product.price)}
</div>
<div className="text-white/60 text-xs">за штуку</div>
</div>
</div>
<div className="flex items-center space-x-2">
<Button
variant="ghost"
size="sm"
onClick={() => updateProductQuantity(product.id, 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"
>
<Minus className="h-4 w-4" />
</Button>
<Input
type="number"
value={selectedQuantity}
onChange={(e) => {
const value = Math.max(0, Math.min(product.quantity, parseInt(e.target.value) || 0))
updateProductQuantity(product.id, value)
}}
className="h-8 w-16 text-center bg-white/10 border-white/20 text-white"
min={0}
max={product.quantity}
/>
<Button
variant="ghost"
size="sm"
onClick={() => updateProductQuantity(product.id, Math.min(product.quantity, selectedQuantity + 1))}
disabled={selectedQuantity >= product.quantity}
className="h-8 w-8 p-0 text-white/60 hover:text-white hover:bg-white/10"
>
<Plus className="h-4 w-4" />
</Button>
</div>
{selectedQuantity > 0 && (
<div className="bg-green-500/20 border border-green-500/30 rounded-lg p-2">
<div className="text-green-300 text-sm font-medium">
Сумма: {formatCurrency(product.price * selectedQuantity)}
</div>
</div>
)}
</div>
</Card>
)
})}
</div>
{selectedProducts.length > 0 && (
<div className="fixed bottom-6 right-6">
<Button
className="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-lg"
onClick={() => setShowSummary(!showSummary)}
>
<ShoppingCart className="h-4 w-4 mr-2" />
Корзина ({selectedProducts.length}) {formatCurrency(getTotalAmount())}
</Button>
</div>
)}
</div>
)
}