/** * Основной компонент управления контрагентами (Модульная архитектура) * Объединяет все hooks и блоки в единую систему */ 'use client' import { Users, ArrowDownCircle, ArrowUpCircle } from 'lucide-react' import React, { useState } from 'react' import { toast } from 'sonner' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' // Hooks import { CounterpartiesListBlock } from './blocks/CounterpartiesListBlock' import { IncomingRequestsBlock } from './blocks/IncomingRequestsBlock' import { OutgoingRequestsBlock } from './blocks/OutgoingRequestsBlock' import { useCounterpartyActions } from './hooks/useCounterpartyActions' import { useCounterpartyData } from './hooks/useCounterpartyData' import { useCounterpartyFilters } from './hooks/useCounterpartyFilters' // UI Blocks // Types import type { Organization } from './types' interface MarketCounterpartiesProps { className?: string } export default function MarketCounterparties({ className }: MarketCounterpartiesProps) { // Состояние активной вкладки const [activeTab, setActiveTab] = useState('counterparties') // Data Hooks const { counterparties, incomingRequests, outgoingRequests, _searchResults, partnerLink, counterpartiesLoading, incomingLoading, outgoingLoading, _searchLoading, _partnerLinkLoading, _error, refetchAll, _searchOrganizations, } = useCounterpartyData() // Action Hooks const { removeCounterparty, acceptRequest, rejectRequest, cancelRequest, sendRequest, loading: _actionLoading, } = useCounterpartyActions() // Filter Hooks const { _searchQuery, _typeFilter, _debouncedSearch, _handleSearchChange, _handleTypeFilterChange, } = useCounterpartyFilters({ onSearch: _searchOrganizations, }) // Unified loading states for blocks const loading = { counterparties: counterpartiesLoading, incoming: incomingLoading, outgoing: outgoingLoading, search: _searchLoading, } // Обработчики действий с callback для обновления данных const handleRemoveCounterparty = async (id: string) => { try { await removeCounterparty(id) await refetchAll() toast.success('Контрагент удален') } catch { toast.error('Ошибка удаления контрагента') } } const handleAcceptRequest = async (id: string) => { try { await acceptRequest(id) await refetchAll() toast.success('Заявка принята') } catch { toast.error('Ошибка принятия заявки') } } const handleRejectRequest = async (id: string) => { try { await rejectRequest(id) await refetchAll() toast.success('Заявка отклонена') } catch { toast.error('Ошибка отклонения заявки') } } const handleCancelRequest = async (id: string) => { try { await cancelRequest(id) await refetchAll() toast.success('Заявка отменена') } catch { toast.error('Ошибка отмены заявки') } } const _handleSendRequest = async (organizationId: string, message?: string) => { try { await sendRequest(organizationId, message) await refetchAll() toast.success('Заявка отправлена') } catch { toast.error('Ошибка отправки заявки') } } const handleCopyLink = (url: string) => { navigator.clipboard.writeText(url) toast.success('Ссылка скопирована в буфер обмена') } const _handleGenerateLink = async () => { try { // TODO: Реализовать создание партнерской ссылки await refetchAll() toast.success('Партнерская ссылка создана') } catch { toast.error('Ошибка создания ссылки') } } // Обработчик просмотра деталей организации const handleViewDetails = (organization: Organization) => { // TODO: Реализовать модальное окно с деталями организации toast.info(`Детали организации: ${organization.name || organization.fullName}`) } // Подсчет уведомлений для вкладок const pendingIncomingCount = incomingRequests.filter(req => req.status === 'PENDING').length const pendingOutgoingCount = outgoingRequests.filter(req => req.status === 'PENDING').length return (