- AI flow builder: scaffold → branch detail → assemble → review flow - Generate All one-click branch generation with stop/cancel - Regenerate scaffold suggestions button - 3-action review screen: Start Flow, Open in Editor, Build Another - Fix Publish button gated behind !isDirty - Fix visibility column enforcement in tree access filter - Add ?visibility filter and author_name to GET /trees - Dashboard tabbed flows: My Flows / My Team / Public / All - Create button in My Flows tab, window focus reload (stale data fix) - Fork UI with optional reason modal - Fix account_id nullability in User type and schema - Keep is_public and visibility in sync on updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import { GitBranch, Layers, CheckCircle, ArrowRight, RotateCcw, Play } from 'lucide-react'
|
|
import { useAIFlowBuilderStore } from '@/store/aiFlowBuilderStore'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
interface TreePreviewCardProps {
|
|
onOpenInEditor: () => void
|
|
onStartFlow: () => void
|
|
onBuildAnother: () => void
|
|
}
|
|
|
|
export function TreePreviewCard({ onOpenInEditor, onStartFlow, onBuildAnother }: TreePreviewCardProps) {
|
|
const { assembledTree, isLoading } = useAIFlowBuilderStore()
|
|
|
|
if (!assembledTree) return null
|
|
|
|
const { summary } = assembledTree
|
|
|
|
const stats = [
|
|
{ label: 'Nodes', value: summary.node_count, icon: Layers },
|
|
{ label: 'Decisions', value: summary.decision_count, icon: GitBranch },
|
|
{ label: 'Solutions', value: summary.solution_count, icon: CheckCircle },
|
|
{ label: 'Depth', value: summary.depth, icon: Layers },
|
|
]
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="text-center">
|
|
<div className="mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-full bg-green-400/10">
|
|
<CheckCircle className="h-6 w-6 text-green-400" />
|
|
</div>
|
|
<h3 className="text-lg font-semibold text-foreground">
|
|
Tree Assembled
|
|
</h3>
|
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
"{assembledTree.suggested_name}" is ready to review in the editor.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Stats grid */}
|
|
<div className="grid grid-cols-4 gap-2">
|
|
{stats.map(({ label, value, icon: Icon }) => (
|
|
<div
|
|
key={label}
|
|
className="flex flex-col items-center rounded-lg border border-border bg-accent/30 p-2.5"
|
|
>
|
|
<Icon className="mb-1 h-4 w-4 text-muted-foreground" />
|
|
<span className="text-lg font-semibold text-gradient-brand">{value}</span>
|
|
<span className="text-[10px] font-label uppercase tracking-wide text-muted-foreground">
|
|
{label}
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Description */}
|
|
{assembledTree.suggested_description && (
|
|
<div className="rounded-lg border border-border bg-accent/20 p-3">
|
|
<p className="text-xs text-muted-foreground">{assembledTree.suggested_description}</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* Actions */}
|
|
<div className="flex flex-col gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={onStartFlow}
|
|
disabled={isLoading}
|
|
className={cn(
|
|
'flex w-full items-center justify-center gap-2 rounded-lg bg-gradient-brand py-2.5 text-sm font-medium text-white shadow-lg shadow-primary/20',
|
|
'hover:opacity-90 disabled:opacity-50'
|
|
)}
|
|
>
|
|
<Play className="h-4 w-4" />
|
|
Start Flow
|
|
</button>
|
|
<div className="flex gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={onOpenInEditor}
|
|
disabled={isLoading}
|
|
className="flex flex-1 items-center justify-center gap-2 rounded-lg border border-border py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50"
|
|
>
|
|
<ArrowRight className="h-4 w-4" />
|
|
Open in Editor
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={onBuildAnother}
|
|
className="flex items-center gap-2 rounded-lg border border-border px-4 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
>
|
|
<RotateCcw className="h-4 w-4" />
|
|
Build Another
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|