/** * Chunked Sync Progress Component * Displays animated progress bar for chunked ticket sync operations */ 'use client'; import { useEffect, useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { Badge } from '@/components/ui/badge'; import { CheckCircle2, XCircle, Loader2, Calendar } from 'lucide-react'; interface ChunkInfo { index: number; total: number; description: string; recordsProcessed: number; status: 'pending' | 'in_progress' | 'completed' | 'failed'; } interface ChunkedSyncProgressProps { isActive: boolean; currentChunk?: ChunkInfo; completedChunks?: number; totalChunks?: number; totalRecords?: number; failedChunks?: string[]; } export default function ChunkedSyncProgress({ isActive, currentChunk, completedChunks = 0, totalChunks = 0, totalRecords = 0, failedChunks = [], }: ChunkedSyncProgressProps) { const [animatedProgress, setAnimatedProgress] = useState(0); // Animate progress bar useEffect(() => { if (totalChunks === 0) return; const targetProgress = (completedChunks / totalChunks) * 100; // Smooth animation const step = (targetProgress - animatedProgress) / 10; const interval = setInterval(() => { setAnimatedProgress(prev => { const next = prev + step; if (Math.abs(next - targetProgress) < 0.5) { clearInterval(interval); return targetProgress; } return next; }); }, 50); return () => clearInterval(interval); }, [completedChunks, totalChunks]); if (!isActive && totalChunks === 0) { return null; } const progressPercentage = totalChunks > 0 ? (completedChunks / totalChunks) * 100 : 0; const hasFailures = failedChunks.length > 0; return (
Chunked Ticket Sync Progress
{isActive ? ( Syncing ) : hasFailures ? ( Completed with Errors ) : ( Completed )}
Processing tickets in monthly chunks to prevent timeouts
{/* Progress Bar */}
{currentChunk?.description || 'Preparing...'} {completedChunks} / {totalChunks} chunks
{Math.round(progressPercentage)}% complete {totalRecords.toLocaleString()} records processed
{/* Chunk Details */} {currentChunk && isActive && (
Processing: {currentChunk.description}

Chunk {currentChunk.index} of {currentChunk.total} • {currentChunk.recordsProcessed.toLocaleString()} records so far

)} {/* Failed Chunks */} {failedChunks.length > 0 && (
{failedChunks.length} chunk{failedChunks.length > 1 ? 's' : ''} failed
    {failedChunks.slice(0, 3).map((chunk, idx) => (
  • • {chunk}
  • ))} {failedChunks.length > 3 && (
  • ... and {failedChunks.length - 3} more
  • )}
)} {/* Completion Summary */} {!isActive && totalChunks > 0 && (
Sync completed: {totalRecords.toLocaleString()} records processed across {completedChunks} chunks
)}
); }