'use client' import { CheckCircle2, AlertCircle, Info, BarChart3 } from 'lucide-react' import { cn } from '@/lib/utils' import { debugProps } from '@/lib/debug' export interface IssueItem { category: 'structure' | 'logic' | 'risk' | 'pattern' severity: 'error' | 'warning' | 'info' suggestion: string } export interface ReviewRound { round: number model: string role: string focus: string issues: IssueItem[] score: number plan_diff_lines: number converged: boolean timestamp: string } export interface ReviewLog { plan_file: string created_at: string rounds: ReviewRound[] convergence?: { stable_at_round: number final_diff_pct: number convergence_metric: string } approval: { status: 'pending' | 'approved' | 'rejected' timestamp?: string } summary: string } interface ReviewLogViewerProps { reviewLog: ReviewLog } const SEVERITY_COLORS: Record = { error: 'text-status-blocked bg-status-blocked/10 border-status-blocked/30', warning: 'text-status-in-progress bg-status-in-progress/10 border-status-in-progress/30', info: 'text-status-review bg-status-review/10 border-status-review/30', } const CATEGORY_LABELS: Record = { structure: 'Structuur', logic: 'Logica', risk: 'Risico', pattern: 'Patroon', } const APPROVAL_COLORS: Record = { pending: 'bg-status-in-progress/15 text-status-in-progress border-status-in-progress/30', approved: 'bg-status-done/15 text-status-done border-status-done/30', rejected: 'bg-status-blocked/15 text-status-blocked border-status-blocked/30', } const APPROVAL_LABELS: Record = { pending: 'In behandeling', approved: 'Goedgekeurd', rejected: 'Afgewezen', } function IssueIcon({ severity }: { severity: IssueItem['severity'] }) { switch (severity) { case 'error': return case 'warning': return case 'info': return } } function RoundHeader({ round }: { round: ReviewRound }) { const date = new Date(round.timestamp).toLocaleString('nl-NL', { dateStyle: 'short', timeStyle: 'short', }) return (
Ronde {round.round + 1} {round.model.split('-').pop()?.toUpperCase()}
{round.role} {round.converged && ( Converged )}
{date}
) } function RoundStats({ round }: { round: ReviewRound }) { return (
Score
{round.score}/100
Wijzigingen
{round.plan_diff_lines} regels
) } function IssueBadge({ issue, index }: { issue: IssueItem; index: number }) { return (
{CATEGORY_LABELS[issue.category]}

{issue.suggestion}

) } export function ReviewLogViewer({ reviewLog }: ReviewLogViewerProps) { const approvalDate = reviewLog.approval.timestamp ? new Date(reviewLog.approval.timestamp).toLocaleString('nl-NL', { dateStyle: 'short', timeStyle: 'short', }) : null return (
{/* Summary */}

Plan-beoordeling

{APPROVAL_LABELS[reviewLog.approval.status]}

{reviewLog.summary}

{approvalDate && (

Goedgekeurd op {approvalDate}

)}
{/* Convergence Metrics */} {reviewLog.convergence && (

Convergentie

Stabiel na ronde

{reviewLog.convergence.stable_at_round + 1}

Eindwijziging

{reviewLog.convergence.final_diff_pct.toFixed(1)}%

)} {/* Review Rounds */}

Review-rondes

{reviewLog.rounds.map((round) => (
{/* Issues */} {round.issues.length > 0 ? (

Bevindingen ({round.issues.length})

{round.issues.map((issue, idx) => ( ))}
) : (

Geen bevindingen in deze ronde.

)}
))}
{/* Metadata */}

Bestand: {reviewLog.plan_file}

Gemaakt:{' '} {new Date(reviewLog.created_at).toLocaleString('nl-NL', { dateStyle: 'short', timeStyle: 'short' })}

Rondes: {reviewLog.rounds.length}

) }