Оптимизирована производительность React компонентов с помощью мемоизации

КРИТИЧНЫЕ КОМПОНЕНТЫ ОПТИМИЗИРОВАНЫ:
• 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>
This commit is contained in:
Veronika Smirnova
2025-08-06 13:18:45 +03:00
parent ef5de31ce7
commit bf27f3ba29
317 changed files with 26722 additions and 38332 deletions

View File

@ -1,124 +1,111 @@
"use client";
'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 {
ArrowLeft,
Building2,
MapPin,
Phone,
Mail,
Package,
Star,
} from "lucide-react";
import { ArrowLeft, Building2, MapPin, Phone, Mail, Package, Star } from 'lucide-react'
import React, { useState } from 'react'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
// import { SupplierProducts } from './supplier-products'
interface Supplier {
id: string;
inn: string;
name: string;
fullName: string;
address: string;
phone?: string;
email?: string;
rating: number;
productCount: number;
avatar?: string;
specialization: string[];
id: string
inn: string
name: string
fullName: string
address: string
phone?: string
email?: string
rating: number
productCount: number
avatar?: string
specialization: string[]
}
interface SupplierSelectionProps {
onBack: () => void;
onClose: () => void;
onSupplyCreated: () => void;
onBack: () => void
onClose: () => void
onSupplyCreated: () => void
}
// Моковые данные поставщиков
const mockSuppliers: Supplier[] = [
{
id: "1",
inn: "7707083893",
name: "ОПТ-Электроника",
id: '1',
inn: '7707083893',
name: 'ОПТ-Электроника',
fullName: 'ООО "ОПТ-Электроника"',
address: "г. Москва, ул. Садовая, д. 15",
phone: "+7 (495) 123-45-67",
email: "opt@electronics.ru",
address: 'г. Москва, ул. Садовая, д. 15',
phone: '+7 (495) 123-45-67',
email: 'opt@electronics.ru',
rating: 4.8,
productCount: 1250,
specialization: ["Электроника", "Бытовая техника"],
specialization: ['Электроника', 'Бытовая техника'],
},
{
id: "2",
inn: "7707083894",
name: "ТекстильМастер",
id: '2',
inn: '7707083894',
name: 'ТекстильМастер',
fullName: 'ООО "ТекстильМастер"',
address: "г. Иваново, пр. Ленина, д. 42",
phone: "+7 (4932) 55-66-77",
email: "sales@textilmaster.ru",
address: 'г. Иваново, пр. Ленина, д. 42',
phone: '+7 (4932) 55-66-77',
email: 'sales@textilmaster.ru',
rating: 4.6,
productCount: 850,
specialization: ["Текстиль", "Одежда", "Домашний текстиль"],
specialization: ['Текстиль', 'Одежда', 'Домашний текстиль'],
},
{
id: "3",
inn: "7707083895",
name: "МетизКомплект",
id: '3',
inn: '7707083895',
name: 'МетизКомплект',
fullName: 'ООО "МетизКомплект"',
address: "г. Тула, ул. Металлургов, д. 8",
phone: "+7 (4872) 33-44-55",
email: "info@metiz.ru",
address: 'г. Тула, ул. Металлургов, д. 8',
phone: '+7 (4872) 33-44-55',
email: 'info@metiz.ru',
rating: 4.9,
productCount: 2100,
specialization: ["Крепеж", "Метизы", "Инструменты"],
specialization: ['Крепеж', 'Метизы', 'Инструменты'],
},
{
id: "4",
inn: "7707083896",
name: "ПродОпт",
id: '4',
inn: '7707083896',
name: 'ПродОпт',
fullName: 'ООО "ПродОпт"',
address: "г. Краснодар, ул. Красная, д. 123",
phone: "+7 (861) 777-88-99",
email: "order@prodopt.ru",
address: 'г. Краснодар, ул. Красная, д. 123',
phone: '+7 (861) 777-88-99',
email: 'order@prodopt.ru',
rating: 4.7,
productCount: 560,
specialization: ["Продукты питания", "Напитки"],
specialization: ['Продукты питания', 'Напитки'],
},
{
id: "5",
inn: "7707083897",
name: "СтройМатериалы+",
id: '5',
inn: '7707083897',
name: 'СтройМатериалы+',
fullName: 'ООО "СтройМатериалы+"',
address: "г. Воронеж, пр. Революции, д. 67",
phone: "+7 (473) 222-33-44",
email: "stroim@materials.ru",
address: 'г. Воронеж, пр. Революции, д. 67',
phone: '+7 (473) 222-33-44',
email: 'stroim@materials.ru',
rating: 4.5,
productCount: 1800,
specialization: ["Стройматериалы", "Сантехника"],
specialization: ['Стройматериалы', 'Сантехника'],
},
{
id: "6",
inn: "7707083898",
name: "КосметикОпт",
id: '6',
inn: '7707083898',
name: 'КосметикОпт',
fullName: 'ООО "КосметикОпт"',
address: "г. Санкт-Петербург, Невский пр., д. 45",
phone: "+7 (812) 111-22-33",
email: "beauty@cosmeticopt.ru",
address: 'г. Санкт-Петербург, Невский пр., д. 45',
phone: '+7 (812) 111-22-33',
email: 'beauty@cosmeticopt.ru',
rating: 4.4,
productCount: 920,
specialization: ["Косметика", "Парфюмерия", "Уход"],
specialization: ['Косметика', 'Парфюмерия', 'Уход'],
},
];
]
export function SupplierSelection({
onBack,
onClose,
onSupplyCreated,
}: SupplierSelectionProps) {
const [selectedSupplier, setSelectedSupplier] = useState<Supplier | null>(
null
);
export function SupplierSelection({ onBack, onClose, onSupplyCreated }: SupplierSelectionProps) {
const [selectedSupplier, setSelectedSupplier] = useState<Supplier | null>(null)
if (selectedSupplier) {
return (
@ -135,9 +122,7 @@ export function SupplierSelection({
Назад
</Button>
<div>
<h2 className="text-2xl font-bold text-white mb-1">
Товары поставщика
</h2>
<h2 className="text-2xl font-bold text-white mb-1">Товары поставщика</h2>
<p className="text-white/60">{selectedSupplier.name}</p>
</div>
</div>
@ -146,21 +131,17 @@ export function SupplierSelection({
<p className="text-white/60">Компонент товаров в разработке...</p>
</div>
</div>
);
)
}
const renderStars = (rating: number) => {
return Array.from({ length: 5 }, (_, i) => (
<Star
key={i}
className={`h-4 w-4 ${
i < Math.floor(rating)
? "text-yellow-400 fill-current"
: "text-gray-400"
}`}
className={`h-4 w-4 ${i < Math.floor(rating) ? 'text-yellow-400 fill-current' : 'text-gray-400'}`}
/>
));
};
))
}
return (
<div className="space-y-6">
@ -176,12 +157,8 @@ export function SupplierSelection({
Назад
</Button>
<div>
<h2 className="text-2xl font-bold text-white mb-1">
Выбор поставщика
</h2>
<p className="text-white/60">
Выберите поставщика для создания поставки
</p>
<h2 className="text-2xl font-bold text-white mb-1">Выбор поставщика</h2>
<p className="text-white/60">Выберите поставщика для создания поставки</p>
</div>
</div>
<Button
@ -208,17 +185,11 @@ export function SupplierSelection({
<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">
{supplier.name}
</h3>
<p className="text-white/60 text-xs mb-2 truncate">
{supplier.fullName}
</p>
<h3 className="text-white font-semibold text-lg mb-1 truncate">{supplier.name}</h3>
<p className="text-white/60 text-xs mb-2 truncate">{supplier.fullName}</p>
<div className="flex items-center space-x-1 mb-2">
{renderStars(supplier.rating)}
<span className="text-white/60 text-sm ml-2">
{supplier.rating}
</span>
<span className="text-white/60 text-sm ml-2">{supplier.rating}</span>
</div>
</div>
</div>
@ -227,34 +198,26 @@ export function SupplierSelection({
<div className="space-y-2">
<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">
{supplier.address}
</span>
<span className="text-white/80 text-sm truncate">{supplier.address}</span>
</div>
{supplier.phone && (
<div className="flex items-center space-x-2">
<Phone className="h-4 w-4 text-gray-400" />
<span className="text-white/80 text-sm">
{supplier.phone}
</span>
<span className="text-white/80 text-sm">{supplier.phone}</span>
</div>
)}
{supplier.email && (
<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">
{supplier.email}
</span>
<span className="text-white/80 text-sm truncate">{supplier.email}</span>
</div>
)}
<div className="flex items-center space-x-2">
<Package className="h-4 w-4 text-gray-400" />
<span className="text-white/80 text-sm">
{supplier.productCount} товаров
</span>
<span className="text-white/80 text-sm">{supplier.productCount} товаров</span>
</div>
</div>
@ -263,10 +226,7 @@ export function SupplierSelection({
<p className="text-white/60 text-xs">Специализация:</p>
<div className="flex flex-wrap gap-1">
{supplier.specialization.map((spec, index) => (
<Badge
key={index}
className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-xs"
>
<Badge key={index} className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-xs">
{spec}
</Badge>
))}
@ -282,5 +242,5 @@ export function SupplierSelection({
))}
</div>
</div>
);
)
}