import { getUser } from '@/auth/authService'; import { POLLING_INTERVALS } from '@/constants'; import { fetchTaskStatus, cancelTask, clearAllTasks } from '@/services'; import { TaskStatus, type TaskResult } from '@/types'; import type { User } from 'oidc-client-ts'; import { useEffect, useState } from 'react'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip'; import { Button } from './ui/button'; import { Loader2, CheckCircle2, XCircle, X, Trash2 } from 'lucide-react'; interface TaskIndicatorProps { taskID: string | null; onTaskCancelled?: () => void; } export function TaskIndicator({ taskID, onTaskCancelled }: TaskIndicatorProps) { const [user, setUser] = useState(null); const [progressPercentage, setProgressPercentage] = useState(0); const [processed, setProcessed] = useState(null); const [total, setTotal] = useState(null); const [taskStatus, setTaskStatus] = useState(null); const [isCancelling, setIsCancelling] = useState(false); const [isClearing, setIsClearing] = useState(false); useEffect(() => { getUser().then(setUser); }, []); useEffect(() => { if (!user || !taskID) { setTaskStatus(null); return; } // Reset state for new task setTaskStatus(TaskStatus.PENDING); setProgressPercentage(0); setProcessed(null); setTotal(null); const pollTaskStatus = async () => { try { const data = await fetchTaskStatus(user, taskID); const status = data.status as TaskStatus; setTaskStatus(status); if (status === TaskStatus.SUCCESS) { setProgressPercentage(100); return true; // Stop polling } if (status === TaskStatus.FAILURE || status === TaskStatus.REVOKED) { return true; // Stop polling } // Parse progress for in-progress tasks if (data.result) { try { const parsedResult: TaskResult = JSON.parse(data.result); setProgressPercentage(parsedResult.progress * 100); if (parsedResult.processed !== undefined) { setProcessed(parsedResult.processed); } if (parsedResult.total !== undefined) { setTotal(parsedResult.total); } } catch { // Ignore parsing errors } } return false; // Continue polling } catch { setTaskStatus(TaskStatus.FAILURE); return true; // Stop polling on error } }; // Initial poll pollTaskStatus(); const interval = setInterval(async () => { const shouldStop = await pollTaskStatus(); if (shouldStop) { clearInterval(interval); } }, POLLING_INTERVALS.TASK_STATUS_MS); return () => clearInterval(interval); }, [taskID, user]); const handleCancel = async () => { if (!user || !taskID || isCancelling) return; setIsCancelling(true); try { const result = await cancelTask(user, taskID); if (result.success) { setTaskStatus(TaskStatus.REVOKED); onTaskCancelled?.(); } } catch { // Ignore cancel errors } finally { setIsCancelling(false); } }; const handleClearAll = async () => { if (!user || isClearing) return; setIsClearing(true); try { const result = await clearAllTasks(user); if (result.success) { setTaskStatus(null); onTaskCancelled?.(); } } catch { // Ignore clear errors } finally { setIsClearing(false); } }; if (!taskID || !taskStatus) { return null; } const isInProgress = taskStatus !== TaskStatus.SUCCESS && taskStatus !== TaskStatus.FAILURE && taskStatus !== TaskStatus.REVOKED; const getStatusIcon = () => { if (isInProgress) { return ; } if (taskStatus === TaskStatus.SUCCESS) { return ; } return ; }; const getProgressText = () => { if (processed !== null && total !== null && total > 0) { return `${processed} / ${total}`; } return `${Math.round(progressPercentage)}%`; }; const getTooltipContent = () => { if (isInProgress) { if (processed !== null && total !== null && total > 0) { return `Processing: ${processed} / ${total} listings (${Math.round(progressPercentage)}%)`; } return `Task running: ${Math.round(progressPercentage)}%`; } if (taskStatus === TaskStatus.SUCCESS) { return 'Task completed successfully'; } if (taskStatus === TaskStatus.REVOKED) { return 'Task was cancelled'; } return 'Task failed'; }; return (
{getStatusIcon()} {isInProgress && (
{getProgressText()}
)} {!isInProgress && ( {taskStatus} )}

{getTooltipContent()}

ID: {taskID.slice(0, 8)}...

{isInProgress && (

Cancel task

)}

Clear all tasks

); }