import React, { useState, useEffect } from 'react'; import { Loader2, CheckCircle2, XCircle, AlertTriangle, RefreshCw, Eye, FileText } from 'lucide-react'; import { ProcessingJob, ProcessingError } from '../../types'; interface ReportProcessingProps { jobId: string; reportId?: number; onComplete?: () => void; onViewReports?: () => void; } export const ReportProcessing: React.FC = ({ jobId, reportId, onComplete, onViewReports }) => { const [jobStatus, setJobStatus] = useState(null); const [isPolling, setIsPolling] = useState(true); const [showPreview, setShowPreview] = useState(false); useEffect(() => { if (!jobId || !isPolling) return; const fetchStatus = async () => { try { const response = await fetch(`/api/finance/processing-status/${jobId}`); if (!response.ok) { throw new Error('Не удалось получить статус обработки'); } const status = await response.json(); setJobStatus(status); // Если обработка завершена, останавливаем опрос if (status.status === 'completed' || status.status === 'failed') { setIsPolling(false); if (onComplete) { onComplete(); } } } catch (error) { console.error('Ошибка получения статуса:', error); } }; // Первый запрос сразу fetchStatus(); // Затем опрашиваем каждые 2 секунды const interval = setInterval(fetchStatus, 2000); return () => clearInterval(interval); }, [jobId, isPolling, onComplete]); const handleRetry = () => { setIsPolling(true); setShowPreview(false); }; const getStatusIcon = () => { if (!jobStatus) return ; switch (jobStatus.status) { case 'processing': return ; case 'completed': return ; case 'failed': return ; default: return ; } }; const getStatusText = () => { if (!jobStatus) return 'Ожидание...'; switch (jobStatus.status) { case 'processing': return 'Обработка файла'; case 'completed': return 'Обработка завершена успешно'; case 'failed': return 'Обработка завершена с ошибками'; default: return 'Ожидание...'; } }; if (!jobStatus) { return (
Загрузка статуса обработки...
); } return (
{/* Основной статус */}

Обработка отчета

{getStatusIcon()} {getStatusText()}
{/* Прогресс-бар */}
Прогресс {jobStatus.progress}%
{/* Текущий этап */} {jobStatus.currentStep && (

Текущий этап: {jobStatus.currentStep}

)} {/* Результаты */} {jobStatus.result && (

Результаты обработки:

Всего строк

{jobStatus.result.totalRows}

Обработано

{jobStatus.result.processedRows}

Ошибок

{jobStatus.result.errorRows}

Домов найдено

{jobStatus.result.buildingsFound || 0}

{jobStatus.result.buildingsCreated > 0 && (

Домов создано

{jobStatus.result.buildingsCreated}

)}
)} {/* Предпросмотр результатов */} {jobStatus.status === 'completed' && jobStatus.result && ( )} {/* Кнопка повтора при ошибках */} {jobStatus.status === 'failed' && ( )} {/* Кнопка просмотра отчетов после успешной обработки */} {jobStatus.status === 'completed' && onViewReports && ( )}
{/* Ошибки */} {jobStatus.errors && jobStatus.errors.length > 0 && (

Ошибки обработки ({jobStatus.errors.length})

{jobStatus.errors.map((error: ProcessingError, index: number) => (
Строка {error.row} {error.column && ( Колонка: {error.column} )}

{error.message}

{error.suggestion && (

💡 {error.suggestion}

)} {error.data && (
Показать данные строки
                      {JSON.stringify(error.data, null, 2)}
                    
)}
))}
)} {/* Предупреждения */} {jobStatus.warnings && jobStatus.warnings.length > 0 && (

Предупреждения ({jobStatus.warnings.length})

{jobStatus.warnings.map((warning: any, index: number) => (

{typeof warning === 'string' ? warning : warning.message}

{typeof warning === 'object' && warning.suggestion && (

💡 {warning.suggestion}

)}
))}
)}
); };