// ======================================== // FixSessionPage Component // ======================================== // Fix session detail page for displaying fix session tasks import * as React from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useIntl } from 'react-intl'; import { ArrowLeft, Wrench, CheckCircle, XCircle, Clock, File, Loader2, } from 'lucide-react'; import { useSessions } from '@/hooks/useSessions'; import { Button } from '@/components/ui/Button'; import { Badge } from '@/components/ui/Badge'; import { Card, CardContent } from '@/components/ui/Card'; type TaskStatusFilter = 'all' | 'pending' | 'in_progress' | 'fixed' | 'failed'; interface FixTask { task_id: string; id?: string; title?: string; status: 'pending' | 'in_progress' | 'completed'; result?: 'fixed' | 'failed'; file?: string; line?: number; finding_title?: string; dimension?: string; attempts?: number; commit_hash?: string; } /** * FixSessionPage component - Display fix session tasks and progress */ export function FixSessionPage() { const { sessionId } = useParams<{ sessionId: string }>(); const navigate = useNavigate(); const { formatMessage } = useIntl(); const { filteredSessions, isLoading, error, refetch } = useSessions({ filter: { location: 'all' }, }); const [statusFilter, setStatusFilter] = React.useState('all'); // Find session const session = React.useMemo( () => filteredSessions.find((s) => s.session_id === sessionId), [filteredSessions, sessionId] ); const tasks = React.useMemo(() => { if (!session?.tasks) return []; return session.tasks as FixTask[]; }, [session?.tasks]); // Calculate statistics const stats = React.useMemo(() => { const total = tasks.length; const fixed = tasks.filter((t) => t.status === 'completed' && t.result === 'fixed').length; const failed = tasks.filter((t) => t.status === 'completed' && t.result === 'failed').length; const pending = tasks.filter((t) => t.status === 'pending').length; const inProgress = tasks.filter((t) => t.status === 'in_progress').length; const completed = fixed + failed; const percentComplete = total > 0 ? Math.round((completed / total) * 100) : 0; return { total, fixed, failed, pending, inProgress, completed, percentComplete }; }, [tasks]); // Filter tasks const filteredTasks = React.useMemo(() => { if (statusFilter === 'all') return tasks; if (statusFilter === 'fixed') { return tasks.filter((t) => t.status === 'completed' && t.result === 'fixed'); } if (statusFilter === 'failed') { return tasks.filter((t) => t.status === 'completed' && t.result === 'failed'); } return tasks.filter((t) => t.status === statusFilter); }, [tasks, statusFilter]); // Get status badge props const getStatusBadge = (task: FixTask) => { if (task.status === 'completed') { if (task.result === 'fixed') { return { variant: 'success' as const, label: formatMessage({ id: 'fixSession.status.fixed' }), icon: CheckCircle }; } if (task.result === 'failed') { return { variant: 'destructive' as const, label: formatMessage({ id: 'fixSession.status.failed' }), icon: XCircle }; } } if (task.status === 'in_progress') { return { variant: 'warning' as const, label: formatMessage({ id: 'fixSession.status.inProgress' }), icon: Loader2 }; } return { variant: 'secondary' as const, label: formatMessage({ id: 'fixSession.status.pending' }), icon: Clock }; }; const handleBack = () => { navigate('/sessions'); }; const handleFilterChange = (filter: TaskStatusFilter) => { setStatusFilter(filter); }; // Loading state if (isLoading) { return (
{Array.from({ length: 4 }).map((_, i) => (
))}
); } // Error state if (error) { return (

{formatMessage({ id: 'common.errors.loadFailed' })}

{error.message}

); } // Session not found if (!session) { return (

{formatMessage({ id: 'fixSession.notFound.title' })}

{formatMessage({ id: 'fixSession.notFound.message' })}

); } return (
{/* Header */}

{session.session_id}

{session.title && (

{session.title}

)}
Fix
{/* Progress Section */}

{formatMessage({ id: 'fixSession.progress.title' })}

{session.phase || formatMessage({ id: 'fixSession.phase.execution' })}
{/* Progress Bar */}
{stats.completed}/{stats.total} {formatMessage({ id: 'common.tasks' })} ( {stats.percentComplete}%)
{/* Summary Cards */}
{stats.total}
{formatMessage({ id: 'fixSession.stats.total' })}
{stats.fixed}
{formatMessage({ id: 'fixSession.stats.fixed' })}
{stats.failed}
{formatMessage({ id: 'fixSession.stats.failed' })}
{stats.pending}
{formatMessage({ id: 'fixSession.stats.pending' })}
{/* Tasks Section */}

{formatMessage({ id: 'fixSession.tasks.title' })}

{[ { key: 'all' as const, label: formatMessage({ id: 'fixSession.filter.all' }) }, { key: 'pending' as const, label: formatMessage({ id: 'fixSession.filter.pending' }) }, { key: 'in_progress' as const, label: formatMessage({ id: 'fixSession.filter.inProgress' }) }, { key: 'fixed' as const, label: formatMessage({ id: 'fixSession.filter.fixed' }) }, { key: 'failed' as const, label: formatMessage({ id: 'fixSession.filter.failed' }) }, ].map((filter) => ( ))}
{/* Tasks List */} {filteredTasks.length === 0 ? (

{formatMessage({ id: 'fixSession.empty.title' })}

{formatMessage({ id: 'fixSession.empty.message' })}

) : (
{filteredTasks.map((task) => { const statusBadge = getStatusBadge(task); const StatusIcon = statusBadge.icon; return (
{task.task_id || task.id || 'N/A'} {statusBadge.label}

{task.title || formatMessage({ id: 'fixSession.task.untitled' })}

{task.finding_title && (

{task.finding_title}

)} {task.file && (
{task.file} {task.line && `:${task.line}`}
)}
{task.dimension && ( {task.dimension} )} {task.attempts && task.attempts > 1 && ( {formatMessage({ id: 'fixSession.task.attempts' }, { count: task.attempts })} )} {task.commit_hash && ( {task.commit_hash.substring(0, 7)} )}
); })}
)}
{/* Session Info */}
{formatMessage({ id: 'fixSession.info.created' })}:{' '} {new Date(session.created_at).toLocaleString()}
{session.updated_at && (
{formatMessage({ id: 'fixSession.info.updated' })}:{' '} {new Date(session.updated_at).toLocaleString()}
)} {session.description && (
{formatMessage({ id: 'fixSession.info.description' })}:{' '} {session.description}
)}
); } export default FixSessionPage;