import React, { useState, useEffect } from 'react'; import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Alert, LinearProgress, Box, Chip, Tooltip, IconButton, } from '@mui/material'; import { History as HistoryIcon, Close as CloseIcon, Refresh as RefreshIcon, Schedule as ScheduleIcon, PriorityHigh as PriorityIcon, } from '@mui/icons-material'; import { documentService, DocumentRetryHistoryItem } from '../services/api'; import { format, formatDistanceToNow } from 'date-fns'; interface RetryHistoryModalProps { open: boolean; onClose: () => void; documentId: string; documentName?: string; } const RETRY_REASON_LABELS: Record = { manual_retry: 'Manual Retry', bulk_retry_all: 'Bulk Retry (All)', bulk_retry_specific: 'Bulk Retry (Selected)', bulk_retry_filtered: 'Bulk Retry (Filtered)', scheduled_retry: 'Scheduled Retry', auto_retry: 'Automatic Retry', }; const STATUS_COLORS: Record = { pending: 'info', processing: 'warning', completed: 'success', failed: 'error', cancelled: 'default', }; export const RetryHistoryModal: React.FC = ({ open, onClose, documentId, documentName, }) => { const [history, setHistory] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [totalRetries, setTotalRetries] = useState(0); const loadRetryHistory = async () => { if (!documentId) return; setLoading(true); setError(null); try { const response = await documentService.getDocumentRetryHistory(documentId); setHistory(response.data?.retry_history || []); setTotalRetries(response.data?.total_retries || 0); } catch (err: any) { setError(err.response?.data?.message || 'Failed to load retry history'); setHistory([]); setTotalRetries(0); } finally { setLoading(false); } }; useEffect(() => { if (open && documentId) { loadRetryHistory(); } }, [open, documentId]); const formatRetryReason = (reason: string) => { return RETRY_REASON_LABELS[reason] || reason.replace(/_/g, ' '); }; const getPriorityLabel = (priority: number) => { if (priority >= 15) return 'Very High'; if (priority >= 12) return 'High'; if (priority >= 8) return 'Medium'; if (priority >= 5) return 'Low'; return 'Very Low'; }; const getPriorityColor = (priority: number): 'default' | 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning' => { if (priority >= 15) return 'error'; if (priority >= 12) return 'warning'; if (priority >= 8) return 'primary'; if (priority >= 5) return 'info'; return 'default'; }; return ( OCR Retry History {documentName && ( {documentName} )} {error && ( {error} )} {loading ? ( Loading retry history... ) : (!history || history.length === 0) ? ( No retry attempts found for this document. This document hasn't been retried yet, or retry history is not available. ) : ( {/* Summary */} {totalRetries} retry attempts found for this document. Most recent attempt: {history && history.length > 0 ? formatDistanceToNow(new Date(history[0].created_at)) + ' ago' : 'No attempts yet'} {/* History Table */} Date & Time Retry Reason Previous Status Priority Queue Status {(history || []).map((item, index) => ( {format(new Date(item.created_at), 'MMM dd, yyyy')} {format(new Date(item.created_at), 'h:mm a')} ({formatDistanceToNow(new Date(item.created_at))} ago) {item.previous_status && ( )} {item.previous_failure_reason && ( {item.previous_failure_reason.replace(/_/g, ' ')} )} {item.previous_error && ( {item.previous_error} )} } label={`${getPriorityLabel(item.priority)} (${item.priority})`} size="small" color={getPriorityColor(item.priority)} /> {item.queue_id ? ( ✓ Queued ID: {item.queue_id.slice(0, 8)}... ) : ( ⚠ Not queued )} ))}
{/* Legend */} Priority Levels: Very High (15-20), High (12-14), Medium (8-11), Low (5-7), Very Low (1-4) Retry Reasons: Manual (user-initiated), Bulk (batch operations), Scheduled (automatic), Auto (system-triggered)
)}
); };