Files
resolutionflow/frontend/src/components/tree-editor/AnswerStubCard.tsx
Michael Chihlas d1a56f0529 refactor: migrate remaining components to Design System v4
111 files across 14 directories: common, tree-editor, kb-accelerator,
copilot, assistant, analytics, library, procedural, procedural-editor,
public, script-editor, ui, admin, step-library.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:18:15 -04:00

122 lines
4.6 KiB
TypeScript

import { useState, useRef, useEffect } from 'react'
import { HelpCircle, Zap, CheckCircle, Trash2 } from 'lucide-react'
import { cn } from '@/lib/utils'
import type { TreeStructure } from '@/types'
interface AnswerStubCardProps {
node: TreeStructure // type === 'answer'
fromOption?: string
onSelectType: (nodeId: string, type: 'decision' | 'action' | 'solution') => void
onDelete: (nodeId: string) => void
}
export function AnswerStubCard({ node, fromOption, onSelectType, onDelete }: AnswerStubCardProps) {
const [picking, setPicking] = useState(false)
const [confirming, setConfirming] = useState(false)
const cardRef = useRef<HTMLDivElement>(null)
const label = fromOption || node.title || 'Answer'
// Collapse picker when clicking outside the card
useEffect(() => {
if (!picking) return
const handleOutsideClick = (e: MouseEvent) => {
if (cardRef.current && !cardRef.current.contains(e.target as Node)) {
setPicking(false)
}
}
document.addEventListener('mousedown', handleOutsideClick)
return () => document.removeEventListener('mousedown', handleOutsideClick)
}, [picking])
return (
<div
ref={cardRef}
className={cn(
'relative min-w-[180px] max-w-[280px] rounded-xl border-2 border-dashed border-[#1e2130] bg-[#14161d]/50',
'transition-all duration-150',
!picking && !confirming && 'cursor-pointer hover:border-primary/40 hover:bg-accent/30'
)}
onClick={() => !picking && !confirming && setPicking(true)}
>
{/* Delete button — top-right corner */}
{!picking && !confirming && (
<button
type="button"
onClick={(e) => { e.stopPropagation(); setConfirming(true) }}
className="absolute top-1.5 right-1.5 rounded p-0.5 text-[#848b9b]/40 hover:bg-red-500/10 hover:text-red-400 transition-colors"
title="Delete stub"
>
<Trash2 className="h-3 w-3" />
</button>
)}
{/* Label */}
<div className="px-3 pt-2.5 pb-1 text-sm font-heading font-medium text-[#e2e5eb] text-center">
{label}
</div>
{/* Confirm delete */}
{confirming ? (
<div className="px-2 pb-2.5 text-center space-y-1.5">
<p className="text-[10px] text-[#848b9b]">Delete this stub?</p>
<div className="flex items-center justify-center gap-1.5">
<button
type="button"
onClick={(e) => { e.stopPropagation(); onDelete(node.id) }}
className="rounded-md px-2 py-1 text-[10px] font-sans text-xs border border-red-500/30 bg-red-500/10 text-red-400 hover:bg-red-500/20"
>
Delete
</button>
<button
type="button"
onClick={(e) => { e.stopPropagation(); setConfirming(false) }}
className="rounded-md px-2 py-1 text-[10px] font-sans text-xs border border-[#1e2130] text-[#848b9b] hover:bg-accent"
>
Cancel
</button>
</div>
</div>
) : !picking ? (
<div className="pb-2.5 text-center text-[10px] text-[#848b9b] font-sans text-xs">
+ Choose Type
</div>
) : (
<div className="flex items-center justify-center gap-1.5 pb-2.5 px-2">
<button
type="button"
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'decision') }}
className={cn(
'flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs',
'border border-blue-500/30 bg-blue-500/10 text-blue-400 hover:bg-blue-500/20'
)}
>
<HelpCircle className="h-2.5 w-2.5" /> Decision
</button>
<button
type="button"
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'action') }}
className={cn(
'flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs',
'border border-yellow-500/30 bg-yellow-500/10 text-yellow-400 hover:bg-yellow-500/20'
)}
>
<Zap className="h-2.5 w-2.5" /> Action
</button>
<button
type="button"
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'solution') }}
className={cn(
'flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs',
'border border-green-500/30 bg-green-500/10 text-green-400 hover:bg-green-500/20'
)}
>
<CheckCircle className="h-2.5 w-2.5" /> Solution
</button>
</div>
)}
</div>
)
}
export default AnswerStubCard