import React, { useState, useEffect } from 'react'; import { FileText, Calendar, User, AlertCircle, CheckCircle2, XCircle, Loader2, ArrowRight } from 'lucide-react'; import { FinancialReport } from '../../types'; import { authFetch } from '../../services/apiClient'; import { readCache, saveCache } from '../../hooks/useCachedFetch'; import { REFRESH_EVENTS } from '../../constants/refreshEvents'; interface ReportsGridProps { onReportClick: (report: FinancialReport) => void; reportTypeFilter?: string; onBack?: () => void; } const reportTypeLabels: Record = { debtors: 'Должники', balance_sheet: 'Оборотная сальдовая ведомость', balance_sheet_76: 'Лицевые счета (ОСВ 76)', other: 'Другие отчеты' }; const reportTypeColors: Record = { debtors: 'bg-red-50 border-red-200 text-red-700', balance_sheet: 'bg-blue-50 border-blue-200 text-blue-700', balance_sheet_76: 'bg-violet-50 border-violet-200 text-violet-700', other: 'bg-slate-50 border-slate-200 text-slate-700' }; const CACHE_KEY = 'mkd_finance_reports_cache'; export const ReportsGrid: React.FC = ({ onReportClick, reportTypeFilter, onBack }) => { const [filterType, setFilterType] = useState(reportTypeFilter || null); const cached = readCache(CACHE_KEY, []); const [reports, setReports] = useState(cached); const [loading, setLoading] = useState(cached.length === 0); const [error, setError] = useState(null); useEffect(() => { if (reportTypeFilter) setFilterType(reportTypeFilter); }, [reportTypeFilter]); useEffect(() => { fetchReports(); }, [filterType]); useEffect(() => { const onRefresh = () => fetchReports(false); window.addEventListener(REFRESH_EVENTS.financeReports, onRefresh); return () => window.removeEventListener(REFRESH_EVENTS.financeReports, onRefresh); }, []); useEffect(() => { const interval = setInterval(() => fetchReports(false), 10 * 1000); return () => clearInterval(interval); }, []); const fetchReports = async (showSpinner = true) => { try { const c = readCache(CACHE_KEY, []); if (showSpinner && c.length === 0) setLoading(true); setError(null); const url = filterType ? `/api/finance/reports?reportType=${encodeURIComponent(filterType)}` : '/api/finance/reports'; console.log('Загрузка отчетов:', url); const response = await authFetch(url); if (!response.ok) { const errorData = await response.json().catch(() => ({ error: 'Неизвестная ошибка' })); console.error('Ошибка ответа сервера:', response.status, errorData); throw new Error(errorData.error || `Ошибка ${response.status}: Не удалось загрузить отчеты`); } const data = await response.json(); console.log('Получены отчеты:', data); // Преобразуем snake_case из API в camelCase для TypeScript const formattedReports: FinancialReport[] = data.map((r: any) => ({ id: r.id, filename: r.filename, fileType: r.file_type, reportType: r.report_type, uploadedAt: r.uploaded_at, uploadedBy: r.uploaded_by, status: r.status, totalRows: r.total_rows, processedRows: r.processed_rows, errorRows: r.error_rows, mappingId: r.mapping_id })); setReports(formattedReports); saveCache(CACHE_KEY, formattedReports); setError(null); } catch (err: any) { console.error('Ошибка загрузки отчетов:', err); setError(err.message || 'Не удалось загрузить отчеты'); } finally { setLoading(false); } }; const getStatusIcon = (status: string) => { switch (status) { case 'completed': return ; case 'failed': return ; case 'processing': return ; default: return ; } }; const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); }; if (loading) { return (

Загрузка отчетов...

); } if (error) { return (

Ошибка: {error}

); } return (
{/* Заголовок и кнопка назад */} {(onBack || reportTypeFilter) && (

{reportTypeFilter ? reportTypeLabels[reportTypeFilter] : 'Загруженные отчеты'}

{onBack && ( )}
)} {/* Фильтры */} {!reportTypeFilter && (
)} {/* Сетка отчетов */} {reports.length === 0 ? (

Нет загруженных отчетов

Загрузите первый отчет на вкладке "Загрузить отчеты из 1С"

) : (
{reports.map((report) => ( ))}
)}
); };