+
Товаров:
{getTotalItems()}
-
+
Карточек:
- {selectedCards.length}
+ {actualSelectedCards.length}
Общая сумма:
- {formatCurrency(getTotalAmount())}
+ {formatCurrency(getTotalAmount())}
e.target.select()}
- className="flex-1 h-7 text-center bg-white/10 border border-white/20 text-white text-xs rounded focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
- placeholder="Кол-во"
+ className="flex-1 h-6 text-center bg-white/10 border border-white/20 text-white text-xs rounded focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none min-w-0"
+ placeholder="0"
/>
-
+
@@ -1253,8 +1304,8 @@ export function WBProductCards({ onBack, onComplete }: WBProductCardsProps) {
updateCardSelection(card, 'customPrice', totalPrice)
}}
onFocus={(e) => e.target.select()}
- className="w-full h-7 text-center bg-white/10 border border-white/20 text-white text-xs rounded focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-transparent"
- placeholder={`Общая цена за ${selectedQuantity} шт`}
+ className="w-full h-6 text-center bg-white/10 border border-white/20 text-white text-xs rounded focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-transparent"
+ placeholder={`Цена за ${selectedQuantity} шт`}
/>
)}
diff --git a/src/components/supplies/wholesaler-card.tsx b/src/components/supplies/wholesaler-card.tsx
new file mode 100644
index 0000000..d79aa26
--- /dev/null
+++ b/src/components/supplies/wholesaler-card.tsx
@@ -0,0 +1,84 @@
+"use client"
+
+import React from 'react'
+import { Card } from '@/components/ui/card'
+import { Badge } from '@/components/ui/badge'
+import {
+ Building2,
+ MapPin,
+ Phone,
+ Mail
+} from 'lucide-react'
+import { WholesalerForCreation } from './types'
+
+interface WholesalerCardProps {
+ wholesaler: WholesalerForCreation
+ onClick: () => void
+}
+
+export function WholesalerCard({ wholesaler, onClick }: WholesalerCardProps) {
+ return (
+
+
+
+
+
+
+
+
+ {wholesaler.name}
+
+
+ {wholesaler.fullName}
+
+
+ ИНН: {wholesaler.inn}
+
+
+
+
+
+
+
+ {wholesaler.address}
+
+
+ {wholesaler.phone && (
+
+ )}
+
+ {wholesaler.email && (
+
+
+ {wholesaler.email}
+
+ )}
+
+
+
+ {wholesaler.specialization.map((spec, index) => (
+
+ {spec}
+
+ ))}
+
+
+
+
+
Товаров: {wholesaler.productCount}
+
Рейтинг: {wholesaler.rating}/5
+
+
+ Контрагент
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/supplies/wholesaler-grid.tsx b/src/components/supplies/wholesaler-grid.tsx
new file mode 100644
index 0000000..9d5a44d
--- /dev/null
+++ b/src/components/supplies/wholesaler-grid.tsx
@@ -0,0 +1,112 @@
+"use client"
+
+import React from 'react'
+import { WholesalerCard } from './wholesaler-card'
+import { Input } from '@/components/ui/input'
+import { Users, Search } from 'lucide-react'
+import { WholesalerForCreation, CounterpartyWholesaler } from './types'
+
+interface WholesalerGridProps {
+ wholesalers: CounterpartyWholesaler[]
+ onWholesalerSelect: (wholesaler: WholesalerForCreation) => void
+ searchQuery: string
+ onSearchChange: (query: string) => void
+ loading?: boolean
+}
+
+export function WholesalerGrid({
+ wholesalers,
+ onWholesalerSelect,
+ searchQuery,
+ onSearchChange,
+ loading = false
+}: WholesalerGridProps) {
+ // Фильтруем оптовиков по поисковому запросу
+ const filteredWholesalers = wholesalers.filter((wholesaler) =>
+ wholesaler.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ wholesaler.fullName?.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ wholesaler.inn?.toLowerCase().includes(searchQuery.toLowerCase())
+ )
+
+ const handleWholesalerClick = (wholesaler: CounterpartyWholesaler) => {
+ // Адаптируем данные под существующий интерфейс
+ const adaptedWholesaler: WholesalerForCreation = {
+ 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: ['Оптовая торговля'] // Временное значение
+ }
+ onWholesalerSelect(adaptedWholesaler)
+ }
+
+ if (loading) {
+ return (
+
+
+
+
Загружаем оптовиков...
+
+
+ )
+ }
+
+ return (
+
+ {/* Поиск */}
+
+
+
+ onSearchChange(e.target.value)}
+ className="pl-10 glass-input text-white placeholder:text-white/40 h-10"
+ />
+
+
+
+ {filteredWholesalers.length === 0 ? (
+
+
+
+ {searchQuery ? 'Оптовики не найдены' : 'У вас нет контрагентов-оптовиков'}
+
+
+ {searchQuery ? 'Попробуйте изменить условия поиска' : 'Добавьте оптовиков в разделе "Партнеры"'}
+
+
+ ) : (
+
+ {filteredWholesalers.map((wholesaler) => {
+ const adaptedWholesaler: WholesalerForCreation = {
+ 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: ['Оптовая торговля']
+ }
+
+ return (
+ handleWholesalerClick(wholesaler)}
+ />
+ )
+ })}
+
+ )}
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/supplies/wholesaler-products-page.tsx b/src/components/supplies/wholesaler-products-page.tsx
new file mode 100644
index 0000000..c1e61ce
--- /dev/null
+++ b/src/components/supplies/wholesaler-products-page.tsx
@@ -0,0 +1,134 @@
+"use client"
+
+import React from 'react'
+import { Button } from '@/components/ui/button'
+import { ProductGrid } from './product-grid'
+import { CartSummary } from './cart-summary'
+import { FloatingCart } from './floating-cart'
+import { Sidebar } from '@/components/dashboard/sidebar'
+import { useSidebar } from '@/hooks/useSidebar'
+import { ArrowLeft, Info } from 'lucide-react'
+import { WholesalerForCreation, WholesalerProduct, SelectedProduct } from './types'
+
+interface WholesalerProductsPageProps {
+ selectedWholesaler: WholesalerForCreation
+ products: WholesalerProduct[]
+ selectedProducts: SelectedProduct[]
+ onQuantityChange: (productId: string, quantity: number) => void
+ onBack: () => void
+ onCreateSupply: () => void
+ formatCurrency: (amount: number) => string
+ showSummary: boolean
+ setShowSummary: (show: boolean) => void
+ loading: boolean
+}
+
+export function WholesalerProductsPage({
+ selectedWholesaler,
+ products,
+ selectedProducts,
+ onQuantityChange,
+ onBack,
+ onCreateSupply,
+ formatCurrency,
+ showSummary,
+ setShowSummary,
+ loading
+}: WholesalerProductsPageProps) {
+ const { getSidebarMargin } = useSidebar()
+
+ const getSelectedQuantity = (productId: string): number => {
+ const selected = selectedProducts.find(p => p.id === productId && p.wholesalerId === selectedWholesaler.id)
+ return selected ? selected.selectedQuantity : 0
+ }
+
+ const selectedProductsMap = products.reduce((acc, product) => {
+ acc[product.id] = getSelectedQuantity(product.id)
+ return acc
+ }, {} as Record
)
+
+ const getTotalAmount = () => {
+ return selectedProducts.reduce((sum, product) => {
+ const discountedPrice = product.discount
+ ? product.price * (1 - product.discount / 100)
+ : product.price
+ return sum + (discountedPrice * product.selectedQuantity)
+ }, 0)
+ }
+
+ const getTotalItems = () => {
+ return selectedProducts.reduce((sum, product) => sum + product.selectedQuantity, 0)
+ }
+
+ const handleRemoveProduct = (productId: string, wholesalerId: string) => {
+ onQuantityChange(productId, 0)
+ }
+
+ const handleCartQuantityChange = (productId: string, wholesalerId: string, quantity: number) => {
+ onQuantityChange(productId, quantity)
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ Назад
+
+
+
Товары оптовика
+
{selectedWholesaler.name} • {products.length} товаров
+
+
+
+ setShowSummary(!showSummary)}
+ className="text-white/60 hover:text-white hover:bg-white/10"
+ >
+
+ Резюме ({selectedProducts.length})
+
+
+
+
+
setShowSummary(false)}
+ formatCurrency={formatCurrency}
+ visible={showSummary && selectedProducts.length > 0}
+ />
+
+
+
+ setShowSummary(!showSummary)}
+ visible={selectedProducts.length > 0 && !showSummary}
+ />
+
+
+
+ )
+}
\ No newline at end of file