'use client' import { useMutation } from '@apollo/client' import { Calendar, Package, Truck, User, CheckCircle, Clock, XCircle, MapPin, Phone, Mail, Building, Hash, ChevronDown, ChevronUp, MessageCircle, Loader2, } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Textarea } from '@/components/ui/textarea' import { SUPPLIER_APPROVE_ORDER, SUPPLIER_REJECT_ORDER, SUPPLIER_SHIP_ORDER } from '@/graphql/mutations' import { GET_SUPPLY_ORDERS } from '@/graphql/queries' interface SupplierOrderCardProps { order: { id: string organizationId: string partnerId: string deliveryDate: string status: | 'PENDING' | 'SUPPLIER_APPROVED' | 'CONFIRMED' | 'LOGISTICS_CONFIRMED' | 'SHIPPED' | 'IN_TRANSIT' | 'DELIVERED' | 'CANCELLED' totalAmount: number totalItems: number createdAt: string organization: { id: string name?: string fullName?: string type: string inn?: string } fulfillmentCenter?: { id: string name?: string fullName?: string type: string } logisticsPartner?: { id: string name?: string fullName?: string type: string } items: Array<{ id: string quantity: number price: number totalPrice: number product: { id: string name: string article: string description?: string category?: { id: string name: string } } }> } } export function SupplierOrderCard({ order }: SupplierOrderCardProps) { const [isExpanded, setIsExpanded] = useState(false) const [showRejectModal, setShowRejectModal] = useState(false) const [rejectReason, setRejectReason] = useState('') // Мутации для действий поставщика const [supplierApproveOrder, { loading: approving }] = useMutation(SUPPLIER_APPROVE_ORDER, { refetchQueries: [{ query: GET_SUPPLY_ORDERS }], onCompleted: (data) => { if (data.supplierApproveOrder.success) { toast.success(data.supplierApproveOrder.message) } else { toast.error(data.supplierApproveOrder.message) } }, onError: (error) => { console.error('Error approving order:', error) toast.error('Ошибка при одобрении заказа') }, }) const [supplierRejectOrder, { loading: rejecting }] = useMutation(SUPPLIER_REJECT_ORDER, { refetchQueries: [{ query: GET_SUPPLY_ORDERS }], onCompleted: (data) => { if (data.supplierRejectOrder.success) { toast.success(data.supplierRejectOrder.message) } else { toast.error(data.supplierRejectOrder.message) } setShowRejectModal(false) setRejectReason('') }, onError: (error) => { console.error('Error rejecting order:', error) toast.error('Ошибка при отклонении заказа') }, }) const [supplierShipOrder, { loading: shipping }] = useMutation(SUPPLIER_SHIP_ORDER, { refetchQueries: [{ query: GET_SUPPLY_ORDERS }], onCompleted: (data) => { if (data.supplierShipOrder.success) { toast.success(data.supplierShipOrder.message) } else { toast.error(data.supplierShipOrder.message) } }, onError: (error) => { console.error('Error shipping order:', error) toast.error('Ошибка при отправке заказа') }, }) const handleApproveOrder = async () => { try { await supplierApproveOrder({ variables: { id: order.id }, }) } catch (error) { console.error('Error in handleApproveOrder:', error) } } const handleRejectOrder = async () => { if (!rejectReason.trim()) { toast.error('Укажите причину отклонения заявки') return } try { await supplierRejectOrder({ variables: { id: order.id, reason: rejectReason, }, }) } catch (error) { console.error('Error in handleRejectOrder:', error) } } const handleShipOrder = async () => { try { await supplierShipOrder({ variables: { id: order.id }, }) } catch (error) { console.error('Error in handleShipOrder:', error) } } const getStatusBadge = (status: string) => { switch (status) { case 'PENDING': return 🟡 ОЖИДАЕТ case 'SUPPLIER_APPROVED': return 🟢 ОДОБРЕНО case 'CONFIRMED': case 'LOGISTICS_CONFIRMED': return 🔵 В РАБОТЕ case 'SHIPPED': case 'IN_TRANSIT': return 🟠 В ПУТИ case 'DELIVERED': return ✅ ДОСТАВЛЕНО default: return {status} } } const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric', }) } const getInitials = (name: string) => { return name .split(' ') .map((word) => word[0]) .join('') .toUpperCase() .slice(0, 2) } const calculateVolume = () => { // Примерный расчет объема - можно улучшить на основе реальных данных о товарах return (order.totalItems * 0.02).toFixed(1) // 0.02 м³ на единицу товара } return ( <> {/* Основная информация - структура согласно правилам */}
{/* Шапка заявки */}
СФ-{order.id.slice(-8)}
{formatDate(order.createdAt)}
{getStatusBadge(order.status)}
{/* Информация об участниках */}
{/* Заказчик */}
Заказчик:
{getInitials(order.organization.name || order.organization.fullName || 'ОРГ')}

{order.organization.name || order.organization.fullName}

{order.organization.inn &&

ИНН: {order.organization.inn}

}
{/* Фулфилмент */} {order.fulfillmentCenter && (
Фулфилмент:

{order.fulfillmentCenter.name || order.fulfillmentCenter.fullName}

)} {/* Логистика */} {order.logisticsPartner && (
Логистика:

{order.logisticsPartner.name || order.logisticsPartner.fullName}

)}
{/* Краткая информация о заказе */}
{order.items.length} вид {order.items.length === 1 ? '' : order.items.length < 5 ? 'а' : 'ов'} товаров
{order.totalItems} единиц
📏 {calculateVolume()} м³
💰 {order.totalAmount.toLocaleString()}₽
{/* Кнопки действий */}
{/* Действия для PENDING */} {order.status === 'PENDING' && ( <> )} {/* Действие для LOGISTICS_CONFIRMED */} {order.status === 'LOGISTICS_CONFIRMED' && ( )} {/* Кнопка связаться всегда доступна */}
{/* Срок доставки */}
Доставка: Склад фулфилмента
Срок: {formatDate(order.deliveryDate)}
{/* Расширенная детализация */} {isExpanded && (

📋 ДЕТАЛИ ЗАЯВКИ #{order.id.slice(-8)}

{/* Товары в заявке */}
📦 ТОВАРЫ В ЗАЯВКЕ:
{order.items.map((item) => (
{item.product.name} • {item.quantity} шт • {item.price} ₽/шт = {item.totalPrice.toLocaleString()}₽
Артикул: {item.product.article} {item.product.category && ` • ${item.product.category.name}`}
))}
Общая стоимость: {order.totalAmount.toLocaleString()}₽
{/* Логистическая информация */}
📍 ЛОГИСТИЧЕСКАЯ ИНФОРМАЦИЯ:
• Объем груза: {calculateVolume()} м³
• Предварительная стоимость доставки: ~ {Math.round(parseFloat(calculateVolume()) * 3500).toLocaleString()}₽
• Маршрут: Склад поставщика → {order.fulfillmentCenter?.name || 'Фулфилмент-центр'}
{/* Контактная информация */}
📞 КОНТАКТЫ:
• Заказчик: {order.organization.name || order.organization.fullName} {order.organization.inn && ` (ИНН: ${order.organization.inn})`}
{order.fulfillmentCenter && (
• Фулфилмент: {order.fulfillmentCenter.name || order.fulfillmentCenter.fullName}
)}
)}
{/* Модал отклонения заявки */} Отклонить заявку