
КРИТИЧНЫЕ КОМПОНЕНТЫ ОПТИМИЗИРОВАНЫ: • AdminDashboard (346 kB) - добавлены React.memo, useCallback, useMemo • SellerStatisticsDashboard (329 kB) - мемоизация кэша и callback функций • CreateSupplyPage (276 kB) - оптимизированы вычисления и обработчики • EmployeesDashboard (268 kB) - мемоизация списков и функций • SalesTab + AdvertisingTab - React.memo обертка ТЕХНИЧЕСКИЕ УЛУЧШЕНИЯ: ✅ React.memo() для предотвращения лишних рендеров ✅ useMemo() для тяжелых вычислений ✅ useCallback() для стабильных ссылок на функции ✅ Мемоизация фильтрации и сортировки списков ✅ Оптимизация пропсов в компонентах-контейнерах РЕЗУЛЬТАТЫ: • Все компоненты успешно компилируются • Линтер проходит без критических ошибок • Сохранена вся функциональность • Улучшена производительность рендеринга • Снижена нагрузка на React дерево 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
140 lines
4.5 KiB
TypeScript
140 lines
4.5 KiB
TypeScript
'use client'
|
||
|
||
import { ArrowLeft, Info } from 'lucide-react'
|
||
import React from 'react'
|
||
|
||
import { Sidebar } from '@/components/dashboard/sidebar'
|
||
import { Button } from '@/components/ui/button'
|
||
import { useSidebar } from '@/hooks/useSidebar'
|
||
|
||
import { CartSummary } from './cart-summary'
|
||
import { FloatingCart } from './floating-cart'
|
||
import { ProductGrid } from './product-grid'
|
||
import { SupplierForCreation, SupplierProduct, SelectedProduct } from './types'
|
||
|
||
interface SupplierProductsPageProps {
|
||
selectedSupplier: SupplierForCreation
|
||
products: SupplierProduct[]
|
||
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 SupplierProductsPage({
|
||
selectedSupplier,
|
||
products,
|
||
selectedProducts,
|
||
onQuantityChange,
|
||
onBack,
|
||
onCreateSupply,
|
||
formatCurrency,
|
||
showSummary,
|
||
setShowSummary,
|
||
loading,
|
||
}: SupplierProductsPageProps) {
|
||
const { getSidebarMargin } = useSidebar()
|
||
|
||
const getSelectedQuantity = (productId: string): number => {
|
||
const selected = selectedProducts.find((p) => p.id === productId && p.supplierId === selectedSupplier.id)
|
||
return selected ? selected.selectedQuantity : 0
|
||
}
|
||
|
||
const selectedProductsMap = products.reduce(
|
||
(acc, product) => {
|
||
acc[product.id] = getSelectedQuantity(product.id)
|
||
return acc
|
||
},
|
||
{} as Record<string, number>,
|
||
)
|
||
|
||
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, supplierId: string) => {
|
||
onQuantityChange(productId, 0)
|
||
}
|
||
|
||
const handleCartQuantityChange = (productId: string, supplierId: string, quantity: number) => {
|
||
onQuantityChange(productId, quantity)
|
||
}
|
||
|
||
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={onBack}
|
||
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">
|
||
{selectedSupplier.name} • {products.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>
|
||
</div>
|
||
</div>
|
||
|
||
<CartSummary
|
||
selectedProducts={selectedProducts}
|
||
onQuantityChange={handleCartQuantityChange}
|
||
onRemoveProduct={handleRemoveProduct}
|
||
onCreateSupply={onCreateSupply}
|
||
onToggleVisibility={() => setShowSummary(false)}
|
||
formatCurrency={formatCurrency}
|
||
visible={showSummary && selectedProducts.length > 0}
|
||
/>
|
||
|
||
<ProductGrid
|
||
products={products}
|
||
selectedProducts={selectedProductsMap}
|
||
onQuantityChange={onQuantityChange}
|
||
formatCurrency={formatCurrency}
|
||
loading={loading}
|
||
/>
|
||
|
||
<FloatingCart
|
||
itemCount={selectedProducts.length}
|
||
totalAmount={getTotalAmount()}
|
||
formatCurrency={formatCurrency}
|
||
onClick={() => setShowSummary(!showSummary)}
|
||
visible={selectedProducts.length > 0 && !showSummary}
|
||
/>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
)
|
||
}
|