Files
resolutionflow/frontend/src/components/ai-builder/TreePreviewCard.tsx
chihlasm ed4ab059bf feat: AI flow builder, visibility model, dashboard tabs, fork UI (#88)
- 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>
2026-02-24 07:40:44 -05:00

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">
&quot;{assembledTree.suggested_name}&quot; 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>
)
}