| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import React, { useState } from "react"; |
| import { ArrowLeft } from "lucide-react"; |
| import { InteractiveEditor } from "./InteractiveEditor"; |
| import { InteractiveWizard } from "./interactive/Wizard"; |
| import { WizardAuto, type AutoInteractionSelection } from "./interactive/WizardAuto"; |
| import { WizardAutoPreview } from "./interactive/WizardAutoPreview"; |
| import type { PlanAutoResult } from "./interactive/types"; |
| import { SecondaryButton, ToastProvider } from "./interactive/ui"; |
|
|
| export interface InteractiveHostProps { |
| backendUrl: string; |
| apiKey?: string; |
| |
| projectId?: string | null; |
| |
| onExit: () => void; |
| |
| onCreated: (experienceId: string) => void; |
| |
| |
| |
| |
| |
| |
| onPlay?: (experienceId: string) => void; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| type WizardStage = "auto" | "preview" | "advanced"; |
|
|
| export function InteractiveHost({ |
| backendUrl, apiKey, projectId, onExit, onCreated, onPlay, |
| }: InteractiveHostProps) { |
| const [stage, setStage] = useState<WizardStage>("auto"); |
| const [planResult, setPlanResult] = useState<PlanAutoResult | null>(null); |
| const [originalIdea, setOriginalIdea] = useState<string>(""); |
| const [interaction, setInteraction] = useState<AutoInteractionSelection>({ |
| interaction_type: "standard_project", |
| }); |
|
|
| |
| |
| |
| |
| |
| |
| return ( |
| <ToastProvider> |
| <div className="flex flex-col h-screen bg-[#0f0f0f] text-[#f1f1f1]"> |
| <TopBar onExit={onExit} label={projectId ? "Back to projects" : "Cancel"} /> |
| <div className="flex-1 min-h-0 flex flex-col"> |
| {projectId ? ( |
| <InteractiveEditor |
| backendUrl={backendUrl} |
| apiKey={apiKey} |
| projectId={projectId} |
| onPlay={onPlay ? () => onPlay(projectId) : undefined} |
| /> |
| ) : stage === "advanced" ? ( |
| // Classic 5-step wizard stays intact for power users. |
| // Nothing inside it was touched by the AUTO-* batches. |
| <InteractiveWizard |
| backendUrl={backendUrl} |
| apiKey={apiKey} |
| onCreated={onCreated} |
| onCancel={onExit} |
| /> |
| ) : stage === "preview" && planResult ? ( |
| <WizardAutoPreview |
| backendUrl={backendUrl} |
| apiKey={apiKey} |
| initial={planResult} |
| originalIdea={originalIdea} |
| interaction={interaction} |
| onCreated={onCreated} |
| onStartOver={() => { |
| setPlanResult(null); |
| setStage("auto"); |
| }} |
| /> |
| ) : ( |
| <WizardAuto |
| backendUrl={backendUrl} |
| apiKey={apiKey} |
| onPlanned={(result, idea, selection) => { |
| setPlanResult(result); |
| setOriginalIdea(idea); |
| setInteraction(selection); |
| setStage("preview"); |
| }} |
| onSwitchToAdvanced={() => setStage("advanced")} |
| onCancel={onExit} |
| /> |
| )} |
| </div> |
| </div> |
| </ToastProvider> |
| ); |
| } |
|
|
| function TopBar({ onExit, label }: { onExit: () => void; label: string }) { |
| return ( |
| <div className="shrink-0 bg-[#0f0f0f] border-b border-[#3f3f3f]"> |
| <div className="max-w-6xl mx-auto px-6 py-3"> |
| <SecondaryButton |
| onClick={onExit} |
| size="sm" |
| icon={<ArrowLeft className="w-3.5 h-3.5" aria-hidden />} |
| aria-label={label} |
| > |
| {label} |
| </SecondaryButton> |
| </div> |
| </div> |
| ); |
| } |
|
|