'use client' import { useQuery } from '@apollo/client' import { formatDistanceToNow } from 'date-fns' import { ru } from 'date-fns/locale' import { ArrowLeft, Search, Filter, RefreshCw, AlertTriangle, Eye, MessageSquare, Clock, CheckCircle, XCircle, Image as ImageIcon, Play, Calendar, Package, DollarSign, Building2, } from 'lucide-react' import React, { useState } from 'react' import { Alert, AlertDescription } from '@/components/ui/alert' 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, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog' import { Input } from '@/components/ui/input' import { GET_WB_RETURN_CLAIMS } from '@/graphql/queries' // Типы данных interface WbReturnClaim { id: string claimType: number status: number statusEx: number nmId: number userComment: string wbComment?: string dt: string imtName: string orderDt: string dtUpdate: string photos: string[] videoPaths: string[] actions: string[] price: number currencyCode: string srid: string sellerOrganization: { id: string name: string inn: string } } interface WbReturnClaimsResponse { claims: WbReturnClaim[] total: number } // Функции для форматирования const getStatusText = (status: number, statusEx: number) => { const statusMap: { [key: number]: string } = { 1: 'Новая', 2: 'Рассматривается', 3: 'Одобрена', 4: 'Отклонена', 5: 'Возврат завершен', } return statusMap[status] || `Статус ${status}` } const getStatusColor = (status: number) => { const colorMap: { [key: number]: string } = { 1: 'bg-blue-500/20 text-blue-300 border-blue-500/30', 2: 'bg-yellow-500/20 text-yellow-300 border-yellow-500/30', 3: 'bg-green-500/20 text-green-300 border-green-500/30', 4: 'bg-red-500/20 text-red-300 border-red-500/30', 5: 'bg-emerald-500/20 text-emerald-300 border-emerald-500/30', } return colorMap[status] || 'bg-gray-500/20 text-gray-300 border-gray-500/30' } const formatPrice = (price: number) => { return new Intl.NumberFormat('ru-RU').format(price) } interface WbReturnClaimsProps { onBack: () => void } export function WbReturnClaims({ onBack }: WbReturnClaimsProps) { const [searchQuery, setSearchQuery] = useState('') const [isArchive, setIsArchive] = useState(false) const [selectedClaim, setSelectedClaim] = useState(null) const { data, loading, error, refetch } = useQuery<{ wbReturnClaims: WbReturnClaimsResponse }>(GET_WB_RETURN_CLAIMS, { variables: { isArchive, limit: 50, offset: 0, }, pollInterval: 30000, // Обновляем каждые 30 секунд errorPolicy: 'all', notifyOnNetworkStatusChange: true, }) const claims = data?.wbReturnClaims?.claims || [] const total = data?.wbReturnClaims?.total || 0 // Отладочный вывод console.warn('WB Claims Debug:', { isArchive, loading, error: error?.message, total, claimsCount: claims.length, hasData: !!data, }) // Фильтрация заявок по поисковому запросу const filteredClaims = claims.filter( (claim) => claim.imtName.toLowerCase().includes(searchQuery.toLowerCase()) || claim.sellerOrganization.name.toLowerCase().includes(searchQuery.toLowerCase()) || claim.nmId.toString().includes(searchQuery) || claim.userComment.toLowerCase().includes(searchQuery.toLowerCase()), ) return (
{/* Заголовок */}

Заявки покупателей на возврат

Всего заявок: {total} | Показано: {filteredClaims.length} | Режим: {isArchive ? 'Архив' : 'Активные'}

{/* Фильтры и поиск */}
setSearchQuery(e.target.value)} className="pl-10 bg-white/10 border-white/20 text-white placeholder:text-white/40" />
{/* Список заявок */}
{error && (
Ошибка загрузки данных

{error.message || 'Не удалось получить заявки от Wildberries API'}

)} {loading ? (
Загрузка заявок...
) : filteredClaims.length === 0 ? (

Заявки не найдены

{searchQuery ? 'Попробуйте изменить критерии поиска' : 'Новых заявок на возврат пока нет'}

{!searchQuery && total === 0 && (

💡 Заявки отображаются только от партнеров-селлеров с настроенными Wildberries API ключами

)}
) : (
{filteredClaims.map((claim) => ( setSelectedClaim(claim)} >
{getStatusText(claim.status, claim.statusEx)} №{claim.nmId} {formatDistanceToNow(new Date(claim.dt), { addSuffix: true, locale: ru, })}

{claim.imtName}

{claim.sellerOrganization.name} {formatPrice(claim.price)} ₽

{claim.userComment}

{claim.photos.length > 0 && (
{claim.photos.length}
)} {claim.videoPaths.length > 0 && (
{claim.videoPaths.length}
)}
))}
)}
{/* Диалог детального просмотра */} setSelectedClaim(null)}> {selectedClaim && ( <> {getStatusText(selectedClaim.status, selectedClaim.statusEx)} Заявка №{selectedClaim.nmId} {selectedClaim.imtName}
Дата заявки:

{new Date(selectedClaim.dt).toLocaleString('ru-RU')}

Дата заказа:

{new Date(selectedClaim.orderDt).toLocaleString('ru-RU')}

Стоимость:

{formatPrice(selectedClaim.price)} ₽

SRID:

{selectedClaim.srid}

Продавец:

{selectedClaim.sellerOrganization.name} (ИНН: {selectedClaim.sellerOrganization.inn})

Комментарий покупателя:

{selectedClaim.userComment}

{selectedClaim.wbComment && (
Комментарий WB:

{selectedClaim.wbComment}

)} {(selectedClaim.photos.length > 0 || selectedClaim.videoPaths.length > 0) && (
Медиафайлы:
{selectedClaim.photos.map((photo, index) => (
Фото {index + 1}
))} {selectedClaim.videoPaths.map((video, index) => (
Видео {index + 1}
))}
)}
)}
) }