'use client' import { useState } from 'react' import { useAgentRuns } from '@/hooks/use-agent-runs' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Check, X, Loader2, FileCode, Plus, Pencil, Trash2, ChevronDown, ChevronUp, AlertCircle, } from 'lucide-react' import { cn } from '@/lib/utils' import type { Database } from '@/types/database' type AgentRun = Database['public']['Tables']['agent_runs']['Row'] interface ApprovalPanelProps { projectId: string className?: string } export function ApprovalPanel({ projectId, className }: ApprovalPanelProps) { const { pendingRuns, loading, approve, reject } = useAgentRuns(projectId) const [expandedRun, setExpandedRun] = useState(null) const [processing, setProcessing] = useState(null) const handleApprove = async (runId: string) => { setProcessing(runId) try { await approve(runId) } finally { setProcessing(null) } } const handleReject = async (runId: string) => { setProcessing(runId) try { await reject(runId) } finally { setProcessing(null) } } if (loading) { return (
) } if (pendingRuns.length === 0) { return (
No pending approvals

AI-proposed changes will appear here for review

) } return (
{pendingRuns.length} pending
{pendingRuns.map((run) => ( setExpandedRun(expandedRun === run.id ? null : run.id)} onApprove={() => handleApprove(run.id)} onReject={() => handleReject(run.id)} processing={processing === run.id} /> ))}
) } interface ApprovalCardProps { run: AgentRun expanded: boolean onToggle: () => void onApprove: () => void onReject: () => void processing: boolean } function ApprovalCard({ run, expanded, onToggle, onApprove, onReject, processing, }: ApprovalCardProps) { const changes = run.proposed_changes if (!changes) return null const fileCount = changes.files?.length || 0 const operations = changes.files?.reduce( (acc, file) => { acc[file.operation] = (acc[file.operation] || 0) + 1 return acc }, {} as Record ) || {} return (
{run.command} {changes.description}
{fileCount} file{fileCount !== 1 ? 's' : ''} {operations.create && ( {operations.create} )} {operations.update && ( {operations.update} )} {operations.delete && ( {operations.delete} )}
{expanded && changes.files && (
{changes.files.map((file, index) => (
{file.operation === 'create' && } {file.operation === 'update' && } {file.operation === 'delete' && } {file.path}
))}
{changes.estimated_impact && (

Impact: {changes.estimated_impact}

)}
)}
) }