import { useState } from 'react' import { Copy, Check, SkipForward, Terminal, ChevronDown, ChevronUp, Send, Clipboard, Loader2, AlertCircle } from 'lucide-react' import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' import type { ActionItem } from '@/types/ai-session' type CardState = 'pending' | 'pasting' | 'typing' | 'skipped' | 'done' interface CardResponse { label: string state: CardState value: string } interface ActionCardGroupProps { actions: ActionItem[] onSubmit: (responses: CardResponse[]) => void disabled?: boolean stale?: boolean } export function ActionCardGroup({ actions, onSubmit, disabled, stale }: ActionCardGroupProps) { const [responses, setResponses] = useState( actions.map(a => ({ label: a.label, state: 'pending', value: '' })) ) const [showRunAll, setShowRunAll] = useState(false) const [submitting, setSubmitting] = useState(false) const [submitted, setSubmitted] = useState(false) const [submitError, setSubmitError] = useState(false) const [expanded, setExpanded] = useState(false) const anyPending = responses.some(r => r.state === 'pending') const isCollapsed = stale && anyPending && !expanded const updateCard = (idx: number, updates: Partial) => { setResponses(prev => prev.map((r, i) => i === idx ? { ...r, ...updates } : r)) } const allHandled = responses.every(r => r.state !== 'pending' && r.state !== 'pasting' && r.state !== 'typing') const anyInteracted = responses.some(r => r.state !== 'pending') const handleSubmit = async () => { setSubmitting(true) setSubmitError(false) try { onSubmit(responses) setSubmitted(true) } catch { setSubmitError(true) } finally { setSubmitting(false) } } const handleCopyCommand = (command: string) => { navigator.clipboard.writeText(command) toast.success('Copied to clipboard') } // Build combined script for "Run All" const commandActions = actions.filter(a => a.command) const combinedScript = commandActions.map((a, i) => ( `# ── ${i + 1}. ${a.label} ──\n${a.command}` )).join('\n\n') const doneCount = responses.filter(r => r.state === 'done').length const skippedCount = responses.filter(r => r.state === 'skipped').length // ── Collapsed state (stale cards from earlier in conversation) ── if (isCollapsed) { const pendingCount = responses.filter(r => r.state === 'pending').length return ( ) } // ── Submitted state ── if (submitted) { return (
{doneCount} checked, {skippedCount} skipped
{responses.map((r, i) => (
{r.state === 'done' ? ( ) : ( )} {r.label}
))}
) } return (
{/* Run All button — only if multiple commands exist */} {commandActions.length > 1 && (
{showRunAll && (
Combined diagnostic script
                {combinedScript}
              
)}
)} {/* Individual action cards */} {actions.map((action, idx) => { const response = responses[idx] const isExpanded = response.state === 'pasting' || response.state === 'typing' return (
{/* Card header */}
{action.label}
{action.description && (
{action.description}
)}
{/* Status badge for handled cards */} {response.state === 'done' && ( Done )} {response.state === 'skipped' && ( Skipped )}
{/* Command with copy button */} {action.command && response.state !== 'skipped' && (
{action.command}
)} {/* Action buttons — only for pending cards */} {response.state === 'pending' && !disabled && (
)} {/* Expanded input area */} {isExpanded && (