Изменен механизм выбора вкладок в компоненте CreateSupplyPage: заменено состояние selectedVariant на activeTab для улучшения читаемости кода. Обновлены условия отображения корзины и логика обработки товаров. Оптимизирован рендеринг карточек и оптовиков. В компоненте WBProductCards изменен заголовок на "Нет товаров" при отсутствии выбранных карточек.

This commit is contained in:
Bivekich
2025-07-23 14:19:59 +03:00
parent ac3578aa7f
commit ff873482a5
2 changed files with 350 additions and 432 deletions

View File

@ -255,7 +255,7 @@ const mockProducts: WholesalerProduct[] = [
export function CreateSupplyPage() { export function CreateSupplyPage() {
const router = useRouter() const router = useRouter()
const { getSidebarMargin } = useSidebar() const { getSidebarMargin } = useSidebar()
const [selectedVariant, setSelectedVariant] = useState<'cards' | 'wholesaler' | null>(null) const [activeTab, setActiveTab] = useState<'cards' | 'wholesaler'>('cards')
const [selectedWholesaler, setSelectedWholesaler] = useState<WholesalerForCreation | null>(null) const [selectedWholesaler, setSelectedWholesaler] = useState<WholesalerForCreation | null>(null)
const [selectedProducts, setSelectedProducts] = useState<SelectedProduct[]>([]) const [selectedProducts, setSelectedProducts] = useState<SelectedProduct[]>([])
const [selectedCards, setSelectedCards] = useState<SelectedCard[]>([]) const [selectedCards, setSelectedCards] = useState<SelectedCard[]>([])
@ -290,10 +290,10 @@ export function CreateSupplyPage() {
// Автоматически показываем корзину если в ней есть товары и мы на этапе выбора оптовиков // Автоматически показываем корзину если в ней есть товары и мы на этапе выбора оптовиков
useEffect(() => { useEffect(() => {
if (selectedVariant === 'wholesaler' && !selectedWholesaler && selectedProducts.length > 0) { if (activeTab === 'wholesaler' && !selectedWholesaler && selectedProducts.length > 0) {
setShowSummary(true) setShowSummary(true)
} }
}, [selectedVariant, selectedWholesaler, selectedProducts.length]) }, [activeTab, selectedWholesaler, selectedProducts.length])
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('ru-RU', { return new Intl.NumberFormat('ru-RU', {
@ -367,7 +367,7 @@ export function CreateSupplyPage() {
} }
const handleCreateSupply = () => { const handleCreateSupply = () => {
if (selectedVariant === 'cards') { if (activeTab === 'cards') {
console.log('Создание поставки с карточками Wildberries') console.log('Создание поставки с карточками Wildberries')
// TODO: Здесь будет создание поставки с данными карточек // TODO: Здесь будет создание поставки с данными карточек
} else { } else {
@ -382,17 +382,13 @@ export function CreateSupplyPage() {
setSelectedWholesaler(null) setSelectedWholesaler(null)
// НЕ очищаем корзину! setSelectedProducts([]) // НЕ очищаем корзину! setSelectedProducts([])
setShowSummary(false) setShowSummary(false)
} else if (selectedVariant) {
setSelectedVariant(null)
setSelectedProducts([]) // Очищаем корзину только при полном выходе
setShowSummary(false)
} else { } else {
router.push('/supplies') router.push('/supplies')
} }
} }
// Рендер товаров оптовика // Рендер товаров оптовика
if (selectedWholesaler && selectedVariant === 'wholesaler') { if (selectedWholesaler && activeTab === 'wholesaler') {
return ( return (
<div className="h-screen flex overflow-hidden"> <div className="h-screen flex overflow-hidden">
<Sidebar /> <Sidebar />
@ -743,370 +739,16 @@ export function CreateSupplyPage() {
) )
} }
// Рендер карточек Wildberries
if (selectedVariant === 'cards') {
return (
<WBProductCards
onBack={() => setSelectedVariant(null)}
onComplete={handleCardsComplete}
/>
)
}
// Рендер выбора оптовиков
if (selectedVariant === 'wholesaler') {
return (
<div className="h-screen flex overflow-hidden">
<Sidebar />
<main className={`flex-1 ${getSidebarMargin()} px-6 py-4 overflow-hidden transition-all duration-300`}>
<div className="p-8">
<div className="flex items-center justify-between mb-8">
<div className="flex items-center space-x-4">
<Button
variant="ghost"
size="sm"
onClick={handleGoBack}
className="text-white/60 hover:text-white hover:bg-white/10"
>
<ArrowLeft className="h-4 w-4 mr-2" />
Назад
</Button>
<div>
<h1 className="text-3xl font-bold text-white mb-2">Выбор оптовика</h1>
<p className="text-white/60">
{selectedProducts.length > 0
? `Выберите еще оптовика или перейдите к оформлению (${selectedProducts.length} товаров в корзине)`
: "Выберите оптовика для создания поставки"
}
</p>
</div>
</div>
{selectedProducts.length > 0 && (
<Button
variant="ghost"
size="sm"
onClick={() => setShowSummary(!showSummary)}
className="text-white/60 hover:text-white hover:bg-white/10"
>
<ShoppingCart className="h-4 w-4 mr-2" />
Корзина ({selectedProducts.length})
</Button>
)}
</div>
{/* Корзина */} // Главная страница с табами
{showSummary && selectedProducts.length > 0 && (
<Card className="bg-gradient-to-br from-purple-500/10 to-pink-500/10 backdrop-blur-xl border border-purple-500/20 mb-8 shadow-2xl">
<div className="p-6">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center space-x-3">
<div className="p-3 bg-gradient-to-r from-purple-500 to-pink-500 rounded-xl">
<ShoppingCart className="h-6 w-6 text-white" />
</div>
<div>
<h3 className="text-white font-bold text-xl">Корзина</h3>
<p className="text-purple-200 text-sm">{selectedProducts.length} товаров от {Object.keys(selectedProducts.reduce((acc, p) => ({ ...acc, [p.wholesalerId]: true }), {})).length} поставщиков</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => setShowSummary(false)}
className="text-white/60 hover:text-white hover:bg-white/10 rounded-xl"
>
<Eye className="h-4 w-4" />
</Button>
</div>
{/* Группировка по оптовикам */}
{Object.entries(
selectedProducts.reduce((acc, product) => {
if (!acc[product.wholesalerId]) {
acc[product.wholesalerId] = {
wholesaler: product.wholesalerName,
products: []
}
}
acc[product.wholesalerId].products.push(product)
return acc
}, {} as Record<string, { wholesaler: string; products: SelectedProduct[] }>)
).map(([wholesalerId, group]) => (
<div key={wholesalerId} className="mb-6 last:mb-0">
<div className="flex items-center mb-3 pb-2 border-b border-white/10">
<Building2 className="h-4 w-4 text-blue-400 mr-2" />
<span className="text-white font-medium">{group.wholesaler}</span>
<Badge className="ml-2 bg-blue-500/20 text-blue-300 border-blue-500/30 text-xs">
{group.products.length} товар(ов)
</Badge>
</div>
<div className="space-y-3">
{group.products.map((product) => {
const discountedPrice = product.discount
? product.price * (1 - product.discount / 100)
: product.price
const totalPrice = discountedPrice * product.selectedQuantity
return (
<div key={`${product.wholesalerId}-${product.id}`} className="flex items-center space-x-4 bg-white/5 rounded-lg p-4">
<img
src={product.mainImage || '/api/placeholder/60/60'}
alt={product.name}
className="w-16 h-16 rounded-lg object-cover"
/>
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm mb-1 truncate">{product.name}</h4>
<p className="text-white/60 text-xs mb-2">{product.article}</p>
<div className="flex items-center space-x-3">
<div className="flex items-center space-x-1">
<Button
variant="ghost"
size="sm"
onClick={() => {
const newQuantity = Math.max(0, product.selectedQuantity - 1)
if (newQuantity === 0) {
setSelectedProducts(prev =>
prev.filter(p => !(p.id === product.id && p.wholesalerId === product.wholesalerId))
)
} else {
setSelectedProducts(prev =>
prev.map(p =>
p.id === product.id && p.wholesalerId === product.wholesalerId
? { ...p, selectedQuantity: newQuantity }
: p
)
)
}
}}
className="h-7 w-7 p-0 text-white/60 hover:text-white hover:bg-white/10"
>
<Minus className="h-3 w-3" />
</Button>
<span className="text-white text-sm w-8 text-center">{product.selectedQuantity}</span>
<Button
variant="ghost"
size="sm"
onClick={() => {
setSelectedProducts(prev =>
prev.map(p =>
p.id === product.id && p.wholesalerId === product.wholesalerId
? { ...p, selectedQuantity: Math.min(product.quantity, p.selectedQuantity + 1) }
: p
)
)
}}
disabled={product.selectedQuantity >= product.quantity}
className="h-7 w-7 p-0 text-white/60 hover:text-white hover:bg-white/10"
>
<Plus className="h-3 w-3" />
</Button>
</div>
<div className="text-right">
<div className="text-white font-semibold text-sm">{formatCurrency(totalPrice)}</div>
{product.discount && (
<div className="text-white/40 text-xs line-through">
{formatCurrency(product.price * product.selectedQuantity)}
</div>
)}
</div>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => {
setSelectedProducts(prev =>
prev.filter(p => !(p.id === product.id && p.wholesalerId === product.wholesalerId))
)
}}
className="text-red-400 hover:text-red-300 hover:bg-red-500/10"
>
</Button>
</div>
)
})}
</div>
</div>
))}
{/* Итого */}
<div className="border-t border-white/20 pt-4 mt-6">
<div className="flex justify-between items-center">
<span className="text-white font-semibold text-lg">
Итого: {getTotalItems()} товаров
</span>
<span className="text-white font-bold text-2xl">
{formatCurrency(getTotalAmount())}
</span>
</div>
<div className="flex space-x-3 mt-4">
<Button
variant="outline"
className="flex-1 border-purple-300/30 text-white hover:bg-white/10"
onClick={() => setShowSummary(false)}
>
<Plus className="h-4 w-4 mr-2" />
Добавить еще
</Button>
<Button
className="flex-1 bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white"
onClick={handleCreateSupply}
>
<ShoppingCart className="h-4 w-4 mr-2" />
Оформить поставку
</Button>
</div>
</div>
</div>
</Card>
)}
{/* Поиск */}
<div className="mb-6">
<div className="relative">
<Search className="absolute left-3 top-3 h-4 w-4 text-white/40" />
<Input
placeholder="Поиск оптовиков по названию или ИНН..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 glass-input text-white placeholder:text-white/40"
/>
</div>
</div>
{counterpartiesLoading ? (
<div className="flex items-center justify-center p-8">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-4 border-white border-t-transparent mx-auto mb-4"></div>
<p className="text-white/60">Загружаем оптовиков...</p>
</div>
</div>
) : filteredWholesalers.length === 0 ? (
<div className="text-center p-8">
<Users className="h-12 w-12 text-white/20 mx-auto mb-4" />
<p className="text-white/60">
{searchQuery ? 'Оптовики не найдены' : 'У вас нет контрагентов-оптовиков'}
</p>
<p className="text-white/40 text-sm mt-2">
{searchQuery ? 'Попробуйте изменить условия поиска' : 'Добавьте оптовиков в разделе "Партнеры"'}
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredWholesalers.map((wholesaler: {
id: string;
name?: string;
fullName?: string;
inn?: string;
address?: string;
phones?: { value: string }[];
emails?: { value: string }[]
}) => (
<Card
key={wholesaler.id}
className="bg-white/10 backdrop-blur border-white/20 p-6 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30 hover:scale-105"
onClick={() => {
// Адаптируем данные под существующий интерфейс
const adaptedWholesaler = {
id: wholesaler.id,
inn: wholesaler.inn || '',
name: wholesaler.name || 'Неизвестная организация',
fullName: wholesaler.fullName || wholesaler.name || 'Неизвестная организация',
address: wholesaler.address || 'Адрес не указан',
phone: wholesaler.phones?.[0]?.value,
email: wholesaler.emails?.[0]?.value,
rating: 4.5, // Временное значение
productCount: 0, // Временное значение
specialization: ['Оптовая торговля'] // Временное значение
}
setSelectedWholesaler(adaptedWholesaler)
}}
>
<div className="space-y-4">
<div className="flex items-start space-x-3">
<div className="p-3 bg-blue-500/20 rounded-lg">
<Building2 className="h-6 w-6 text-blue-400" />
</div>
<div className="flex-1 min-w-0">
<h3 className="text-white font-semibold text-lg mb-1 truncate">
{wholesaler.name || 'Неизвестная организация'}
</h3>
<p className="text-white/60 text-xs mb-2 truncate">
{wholesaler.fullName || wholesaler.name}
</p>
{wholesaler.inn && (
<p className="text-white/40 text-xs">
ИНН: {wholesaler.inn}
</p>
)}
</div>
</div>
<div className="space-y-2">
{wholesaler.address && (
<div className="flex items-center space-x-2">
<MapPin className="h-4 w-4 text-gray-400" />
<span className="text-white/80 text-sm truncate">{wholesaler.address}</span>
</div>
)}
{wholesaler.phones?.[0]?.value && (
<div className="flex items-center space-x-2">
<Phone className="h-4 w-4 text-gray-400" />
<span className="text-white/80 text-sm">{wholesaler.phones[0].value}</span>
</div>
)}
{wholesaler.emails?.[0]?.value && (
<div className="flex items-center space-x-2">
<Mail className="h-4 w-4 text-gray-400" />
<span className="text-white/80 text-sm truncate">{wholesaler.emails[0].value}</span>
</div>
)}
</div>
<div className="mt-4">
<Badge className="bg-green-500/20 text-green-300 border-green-500/30">
Контрагент
</Badge>
</div>
<div className="pt-2 border-t border-white/10">
<p className="text-white/60 text-xs">ИНН: {wholesaler.inn}</p>
</div>
</div>
</Card>
))}
</div>
)}
{/* Floating корзина */}
{selectedProducts.length > 0 && !showSummary && (
<div className="fixed bottom-6 right-6 z-50">
<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={() => setShowSummary(true)}
>
<ShoppingCart className="h-5 w-5 mr-2" />
{selectedProducts.length} {formatCurrency(getTotalAmount())}
</Button>
</div>
)}
</div>
</main>
</div>
)
}
// Главная страница выбора варианта
return ( return (
<div className="h-screen flex overflow-hidden"> <div className="h-screen flex overflow-hidden">
<Sidebar /> <Sidebar />
<main className={`flex-1 ${getSidebarMargin()} px-6 py-4 overflow-hidden transition-all duration-300`}> <main className={`flex-1 ${getSidebarMargin()} px-4 py-3 overflow-hidden transition-all duration-300`}>
<div className="p-8"> <div className="p-4">
<div className="flex items-center justify-between mb-8"> {/* Верхняя строка: Назад + Заголовок + Табы */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-4"> <div className="flex items-center space-x-4">
<Button <Button
variant="ghost" variant="ghost"
@ -1115,56 +757,352 @@ export function CreateSupplyPage() {
className="text-white/60 hover:text-white hover:bg-white/10" className="text-white/60 hover:text-white hover:bg-white/10"
> >
<ArrowLeft className="h-4 w-4 mr-2" /> <ArrowLeft className="h-4 w-4 mr-2" />
Назад к поставкам Назад
</Button> </Button>
<div> <h1 className="text-2xl font-bold text-white">Создание поставки</h1>
<h1 className="text-3xl font-bold text-white mb-2">Создание поставки</h1> </div>
<p className="text-white/60">Выберите способ создания поставки</p>
<div>
<div className="grid grid-cols-2 bg-white/10 backdrop-blur border border-white/20 rounded-lg p-1">
<button
onClick={() => setActiveTab('cards')}
className={`px-4 py-2 text-sm rounded transition-all ${
activeTab === 'cards'
? 'bg-white/20 text-white'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}
>
<ShoppingCart className="h-4 w-4 mr-1 inline" />
Карточки
</button>
<button
onClick={() => setActiveTab('wholesaler')}
className={`px-4 py-2 text-sm rounded transition-all ${
activeTab === 'wholesaler'
? 'bg-white/20 text-white'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}
>
<Users className="h-4 w-4 mr-1 inline" />
Оптовики
</button>
</div> </div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> {/* Контент карточек */}
<Card {activeTab === 'cards' && (
className="bg-white/10 backdrop-blur border-white/20 p-8 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30 hover:scale-105" <WBProductCards
onClick={() => setSelectedVariant('cards')} onBack={() => router.push('/supplies')}
> onComplete={handleCardsComplete}
<div className="text-center space-y-6"> />
<div className="p-6 bg-blue-500/20 rounded-2xl w-fit mx-auto"> )}
<ShoppingCart className="h-12 w-12 text-blue-400" />
</div>
<div>
<h3 className="text-2xl font-semibold text-white mb-3">Карточки</h3>
<p className="text-white/60">
Создание поставки через выбор товаров по карточкам Wildberries
</p>
</div>
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-lg px-4 py-2">
Доступно
</Badge>
</div>
</Card>
<Card {/* Контент оптовиков */}
className="bg-white/10 backdrop-blur border-white/20 p-8 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30 hover:scale-105" {activeTab === 'wholesaler' && (
onClick={() => setSelectedVariant('wholesaler')} <div>
> {/* Поиск */}
<div className="text-center space-y-6"> <div className="mb-4">
<div className="p-6 bg-green-500/20 rounded-2xl w-fit mx-auto"> <div className="relative max-w-md">
<Users className="h-12 w-12 text-green-400" /> <Search className="absolute left-3 top-3 h-4 w-4 text-white/40" />
<Input
placeholder="Поиск оптовиков..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 glass-input text-white placeholder:text-white/40 h-10"
/>
</div> </div>
<div> </div>
<h3 className="text-2xl font-semibold text-white mb-3">Оптовик</h3>
{/* Корзина */}
{showSummary && selectedProducts.length > 0 && (
<Card className="bg-gradient-to-br from-purple-500/10 to-pink-500/10 backdrop-blur-xl border border-purple-500/20 mb-6 shadow-2xl">
<div className="p-4">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
<div className="p-2 bg-gradient-to-r from-purple-500 to-pink-500 rounded-lg">
<ShoppingCart className="h-5 w-5 text-white" />
</div>
<div>
<h3 className="text-white font-bold text-lg">Корзина</h3>
<p className="text-purple-200 text-xs">{selectedProducts.length} товаров от {Object.keys(selectedProducts.reduce((acc, p) => ({ ...acc, [p.wholesalerId]: true }), {})).length} поставщиков</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => setShowSummary(false)}
className="text-white/60 hover:text-white hover:bg-white/10 rounded-xl"
>
<Eye className="h-4 w-4" />
</Button>
</div>
{/* Группировка по оптовикам */}
{Object.entries(
selectedProducts.reduce((acc, product) => {
if (!acc[product.wholesalerId]) {
acc[product.wholesalerId] = {
wholesaler: product.wholesalerName,
products: []
}
}
acc[product.wholesalerId].products.push(product)
return acc
}, {} as Record<string, { wholesaler: string; products: SelectedProduct[] }>)
).map(([wholesalerId, group]) => (
<div key={wholesalerId} className="mb-4 last:mb-0">
<div className="flex items-center mb-2 pb-1 border-b border-white/10">
<Building2 className="h-4 w-4 text-blue-400 mr-2" />
<span className="text-white font-medium">{group.wholesaler}</span>
<Badge className="ml-2 bg-blue-500/20 text-blue-300 border-blue-500/30 text-xs">
{group.products.length} товар(ов)
</Badge>
</div>
<div className="space-y-2">
{group.products.map((product) => {
const discountedPrice = product.discount
? product.price * (1 - product.discount / 100)
: product.price
const totalPrice = discountedPrice * product.selectedQuantity
return (
<div key={`${product.wholesalerId}-${product.id}`} className="flex items-center space-x-3 bg-white/5 rounded-lg p-3">
<img
src={product.mainImage || '/api/placeholder/50/50'}
alt={product.name}
className="w-12 h-12 rounded-lg object-cover"
/>
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-xs mb-1 truncate">{product.name}</h4>
<p className="text-white/60 text-xs mb-1">{product.article}</p>
<div className="flex items-center space-x-2">
<div className="flex items-center space-x-1">
<Button
variant="ghost"
size="sm"
onClick={() => {
const newQuantity = Math.max(0, product.selectedQuantity - 1)
if (newQuantity === 0) {
setSelectedProducts(prev =>
prev.filter(p => !(p.id === product.id && p.wholesalerId === product.wholesalerId))
)
} else {
setSelectedProducts(prev =>
prev.map(p =>
p.id === product.id && p.wholesalerId === product.wholesalerId
? { ...p, selectedQuantity: newQuantity }
: p
)
)
}
}}
className="h-6 w-6 p-0 text-white/60 hover:text-white hover:bg-white/10"
>
<Minus className="h-3 w-3" />
</Button>
<span className="text-white text-xs w-6 text-center">{product.selectedQuantity}</span>
<Button
variant="ghost"
size="sm"
onClick={() => {
setSelectedProducts(prev =>
prev.map(p =>
p.id === product.id && p.wholesalerId === product.wholesalerId
? { ...p, selectedQuantity: Math.min(product.quantity, p.selectedQuantity + 1) }
: p
)
)
}}
disabled={product.selectedQuantity >= product.quantity}
className="h-6 w-6 p-0 text-white/60 hover:text-white hover:bg-white/10"
>
<Plus className="h-3 w-3" />
</Button>
</div>
<div className="text-right">
<div className="text-white font-semibold text-xs">{formatCurrency(totalPrice)}</div>
{product.discount && (
<div className="text-white/40 text-xs line-through">
{formatCurrency(product.price * product.selectedQuantity)}
</div>
)}
</div>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => {
setSelectedProducts(prev =>
prev.filter(p => !(p.id === product.id && p.wholesalerId === product.wholesalerId))
)
}}
className="text-red-400 hover:text-red-300 hover:bg-red-500/10"
>
</Button>
</div>
)
})}
</div>
</div>
))}
{/* Итого */}
<div className="border-t border-white/20 pt-3 mt-4">
<div className="flex justify-between items-center">
<span className="text-white font-semibold text-sm">
Итого: {getTotalItems()} товаров
</span>
<span className="text-white font-bold text-lg">
{formatCurrency(getTotalAmount())}
</span>
</div>
<div className="flex space-x-2 mt-3">
<Button
variant="outline"
className="flex-1 border-purple-300/30 text-white hover:bg-white/10"
onClick={() => setShowSummary(false)}
>
<Plus className="h-4 w-4 mr-2" />
Добавить еще
</Button>
<Button
className="flex-1 bg-gradient-to-r from-green-500 to-emerald-500 hover:from-green-600 hover:to-emerald-600 text-white"
onClick={handleCreateSupply}
>
<ShoppingCart className="h-4 w-4 mr-2" />
Оформить поставку
</Button>
</div>
</div>
</div>
</Card>
)}
{counterpartiesLoading ? (
<div className="flex items-center justify-center p-8">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-4 border-white border-t-transparent mx-auto mb-4"></div>
<p className="text-white/60">Загружаем оптовиков...</p>
</div>
</div>
) : filteredWholesalers.length === 0 ? (
<div className="text-center p-8">
<Users className="h-12 w-12 text-white/20 mx-auto mb-4" />
<p className="text-white/60"> <p className="text-white/60">
Создание поставки через выбор товаров у оптовиков {searchQuery ? 'Оптовики не найдены' : 'У вас нет контрагентов-оптовиков'}
</p>
<p className="text-white/40 text-sm mt-2">
{searchQuery ? 'Попробуйте изменить условия поиска' : 'Добавьте оптовиков в разделе "Партнеры"'}
</p> </p>
</div> </div>
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-lg px-4 py-2"> ) : (
Доступно <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
</Badge> {filteredWholesalers.map((wholesaler: {
id: string;
name?: string;
fullName?: string;
inn?: string;
address?: string;
phones?: { value: string }[];
emails?: { value: string }[]
}) => (
<Card
key={wholesaler.id}
className="bg-white/10 backdrop-blur border-white/20 p-4 cursor-pointer transition-all hover:bg-white/15 hover:border-white/30 hover:scale-[1.02]"
onClick={() => {
// Адаптируем данные под существующий интерфейс
const adaptedWholesaler = {
id: wholesaler.id,
inn: wholesaler.inn || '',
name: wholesaler.name || 'Неизвестная организация',
fullName: wholesaler.fullName || wholesaler.name || 'Неизвестная организация',
address: wholesaler.address || 'Адрес не указан',
phone: wholesaler.phones?.[0]?.value,
email: wholesaler.emails?.[0]?.value,
rating: 4.5, // Временное значение
productCount: 0, // Временное значение
specialization: ['Оптовая торговля'] // Временное значение
}
setSelectedWholesaler(adaptedWholesaler)
}}
>
<div className="space-y-3">
<div className="flex items-start space-x-2">
<div className="p-2 bg-blue-500/20 rounded-lg">
<Building2 className="h-4 w-4 text-blue-400" />
</div>
<div className="flex-1 min-w-0">
<h3 className="text-white font-semibold text-sm mb-1 truncate">
{wholesaler.name || 'Неизвестная организация'}
</h3>
<p className="text-white/60 text-xs mb-1 truncate">
{wholesaler.fullName || wholesaler.name}
</p>
{wholesaler.inn && (
<p className="text-white/40 text-xs">
ИНН: {wholesaler.inn}
</p>
)}
</div>
</div>
<div className="space-y-1">
{wholesaler.address && (
<div className="flex items-center space-x-1">
<MapPin className="h-3 w-3 text-gray-400" />
<span className="text-white/80 text-xs truncate">{wholesaler.address}</span>
</div>
)}
{wholesaler.phones?.[0]?.value && (
<div className="flex items-center space-x-1">
<Phone className="h-3 w-3 text-gray-400" />
<span className="text-white/80 text-xs">{wholesaler.phones[0].value}</span>
</div>
)}
{wholesaler.emails?.[0]?.value && (
<div className="flex items-center space-x-1">
<Mail className="h-3 w-3 text-gray-400" />
<span className="text-white/80 text-xs truncate">{wholesaler.emails[0].value}</span>
</div>
)}
</div>
<div className="mt-2">
<Badge className="bg-green-500/20 text-green-300 border-green-500/30 text-xs px-2 py-1">
Контрагент
</Badge>
</div>
<div className="pt-2 border-t border-white/10">
<p className="text-white/60 text-xs">ИНН: {wholesaler.inn}</p>
</div>
</div>
</Card>
))}
</div> </div>
</Card> )}
</div>
{/* Floating корзина */}
{selectedProducts.length > 0 && !showSummary && (
<div className="fixed bottom-6 right-6 z-50">
<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={() => setShowSummary(true)}
>
<ShoppingCart className="h-5 w-5 mr-2" />
{selectedProducts.length} {formatCurrency(getTotalAmount())}
</Button>
</div>
)}
</div>
)}
</div> </div>
</main> </main>
</div> </div>

View File

@ -997,26 +997,8 @@ export function WBProductCards({ onBack, onComplete }: WBProductCardsProps) {
} }
return ( return (
<div className="h-screen flex overflow-hidden"> <div className="space-y-4">
<Sidebar /> <div className="flex items-center justify-end">
<main className={`flex-1 ${getSidebarMargin()} overflow-auto transition-all duration-300`}>
<div className="p-6 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">Карточки товаров Wildberries</h2>
<p className="text-white/60">Найдите и выберите товары для поставки</p>
</div>
</div>
{selectedCards.length > 0 && ( {selectedCards.length > 0 && (
<Button <Button
@ -1324,7 +1306,7 @@ export function WBProductCards({ onBack, onComplete }: WBProductCardsProps) {
<Card className="bg-white/10 backdrop-blur border-white/20 p-8"> <Card className="bg-white/10 backdrop-blur border-white/20 p-8">
<div className="text-center max-w-md mx-auto"> <div className="text-center max-w-md mx-auto">
<Package className="h-12 w-12 text-white/20 mx-auto mb-4" /> <Package className="h-12 w-12 text-white/20 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-white mb-2">Карточки товаров Wildberries</h3> <h3 className="text-lg font-semibold text-white mb-2">Нет товаров</h3>
{user?.organization?.apiKeys?.find(key => key.marketplace === 'WILDBERRIES')?.isActive ? ( {user?.organization?.apiKeys?.find(key => key.marketplace === 'WILDBERRIES')?.isActive ? (
<> <>
<p className="text-white/60 mb-4 text-sm"> <p className="text-white/60 mb-4 text-sm">
@ -1446,8 +1428,6 @@ export function WBProductCards({ onBack, onComplete }: WBProductCardsProps) {
)} )}
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </div>
</main> )
</div>
)
} }