feat: redesign NodeFormDecision to label-only options, remove NodePicker

Users now type answer labels only. Stub nodes are created automatically
by TreeCanvas when the decision node is saved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-18 01:31:56 -05:00
parent e29aadf8a5
commit 10238f85e2

View File

@@ -1,6 +1,5 @@
import { Play } from 'lucide-react'
import { DynamicArrayField } from './DynamicArrayField'
import { NodePicker } from './NodePicker'
import { useTreeEditorStore } from '@/store/treeEditorStore'
import type { TreeStructure, TreeOption } from '@/types'
import { cn } from '@/lib/utils'
@@ -147,52 +146,34 @@ export function NodeFormDecision({ node, onUpdate }: NodeFormDecisionProps) {
const optionLabelError = validationErrors.find(
e => e.nodeId === node.id && e.field === `options[${index}].label`
)
const optionNextError = validationErrors.find(
e => e.nodeId === node.id && e.field === `options[${index}].next_node_id`
)
const letter = indexToLetter(index)
return (
<div className="rounded-md border border-border bg-accent/50 p-3">
<div className="mb-2 flex items-center gap-2">
{/* Letter badge */}
<span className={cn(
'flex h-6 w-6 items-center justify-center rounded-full text-xs font-bold',
isRootNode
? 'bg-blue-500/20 text-blue-400'
: 'bg-accent text-muted-foreground'
)}>
{letter}
</span>
<div className="flex items-center gap-2">
<span className={cn(
'flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-bold',
isRootNode ? 'bg-blue-500/20 text-blue-400' : 'bg-accent text-muted-foreground'
)}>
{letter}
</span>
<div className="flex-1">
<input
type="text"
value={option.label}
onChange={(e) => handleUpdateOption(index, { label: e.target.value })}
placeholder={isRootNode
? `Branch ${letter}: e.g., "Network Issues", "Application Errors"...`
? `Branch ${letter}: e.g., "Network Issues"...`
: `Option ${letter} label`}
className={cn(
'block flex-1 rounded-md border px-3 py-2 text-sm',
'block w-full rounded-md border px-3 py-2 text-sm',
'bg-background text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary',
optionLabelError ? 'border-red-400' : 'border-border'
)}
/>
</div>
{optionLabelError && (
<p className="mb-2 text-xs text-red-400">{optionLabelError.message}</p>
)}
<div className="pl-8">
<NodePicker
value={option.next_node_id}
onChange={(nodeId) => handleUpdateOption(index, { next_node_id: nodeId })}
parentNodeId={node.id}
excludeNodeId={node.id}
placeholder={isRootNode
? `What happens when user selects "${option.label || `Branch ${letter}`}"?`
: "Select or create next node..."}
error={optionNextError?.message}
/>
{optionLabelError && (
<p className="mt-1 text-xs text-red-400">{optionLabelError.message}</p>
)}
</div>
</div>
)