/** * CreateSessionWizard — 3-step wizard for creating a team meeting session. * * Step 1: Name & Description * Step 2: Select Personas (drag-style multi-select from available list) * Step 3: Settings (turn mode, agenda) * * Simple, easy-to-use flow modeled after the Agent project wizard. */ import React, { useState, useCallback } from 'react' import { X, ChevronLeft, ChevronRight, Users, Settings, FileText, Check, Zap, MessageSquare, Crown, Activity, Workflow, DollarSign, } from 'lucide-react' import type { PersonaSummary } from './types' import { PersonaSelectorEnterprise } from './PersonaSelectorEnterprise' import { TEAM_BUNDLES } from './teamBundles' // --------------------------------------------------------------------------- // Props // --------------------------------------------------------------------------- export interface CreateSessionWizardProps { personas: PersonaSummary[] backendUrl: string onCancel: () => void onCreate: (params: { name: string description: string participant_ids: string[] turn_mode: string agenda: string[] policy?: { engine?: string; crew?: { profile_id?: string; budget_limit_eur?: number } } }) => Promise } // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- const TURN_MODES = [ { value: 'reactive', label: 'Reactive (Recommended)', description: 'Only relevant personas speak — best for brainstorming and productivity', icon: , }, { value: 'round-robin', label: 'Round Robin', description: 'Each persona responds in order after you speak', icon: , }, { value: 'free-form', label: 'Free Form', description: 'Personas respond naturally as in a real conversation', icon: , }, { value: 'moderated', label: 'Moderated', description: 'You choose which persona speaks next', icon: , }, ] const ENGINE_OPTIONS = [ { value: 'native' as const, label: 'Conversation', description: 'Free-form discussion with smart speaker selection', icon: , }, { value: 'crew' as const, label: 'Task Workflow', description: 'Stage-based collaboration with structured output', icon: , }, ] const CREW_PROFILES = [ { id: 'task_planner_v1', label: 'Task Planner', description: 'Steps, details, review, and finalize' }, { id: 'brainstorm_v1', label: 'Brainstorm', description: 'Ideate, evaluate, and recommend' }, { id: 'draft_and_edit_v1', label: 'Draft & Edit', description: 'Outline, draft, and refine content' }, ] // --------------------------------------------------------------------------- // Component // --------------------------------------------------------------------------- export function CreateSessionWizard({ personas, backendUrl, onCancel, onCreate, }: CreateSessionWizardProps) { const [step, setStep] = useState(1) const totalSteps = 3 // Step 1 const [name, setName] = useState('') const [description, setDescription] = useState('') // Step 2 const [selectedIds, setSelectedIds] = useState>(new Set()) // Step 3 const [engine, setEngine] = useState<'native' | 'crew'>('native') const [crewProfileId, setCrewProfileId] = useState('task_planner_v1') const [budgetLimit, setBudgetLimit] = useState('') const [turnMode, setTurnMode] = useState('reactive') const [agendaText, setAgendaText] = useState('') const [creating, setCreating] = useState(false) const togglePersona = useCallback((id: string) => { setSelectedIds((prev) => { const next = new Set(prev) if (next.has(id)) next.delete(id) else next.add(id) return next }) }, []) const canProceed = step === 1 ? name.trim().length > 0 : step === 2 ? selectedIds.size > 0 : true const handleCreate = useCallback(async () => { if (creating) return setCreating(true) try { const agenda = agendaText .split('\n') .map((l) => l.trim()) .filter(Boolean) const policy = engine === 'crew' ? { engine: 'crew' as const, crew: { profile_id: crewProfileId, ...(budgetLimit ? { budget_limit_eur: parseFloat(budgetLimit) } : {}), }, } : { engine: 'native' as const } await onCreate({ name: name.trim(), description: description.trim(), participant_ids: Array.from(selectedIds), turn_mode: turnMode, agenda, policy, }) } catch (e) { console.error('Failed to create session:', e) } finally { setCreating(false) } }, [creating, name, description, selectedIds, turnMode, agendaText, engine, crewProfileId, budgetLimit, onCreate]) return (
{/* ═══════════════ HEADER ═══════════════ */}
New Team Session
{/* ═══════════════ STEP INDICATOR ═══════════════ */}
{[ { n: 1, label: 'Details', icon: }, { n: 2, label: 'Personas', icon: }, { n: 3, label: 'Settings', icon: }, ].map(({ n, label, icon }) => ( {n > 1 &&
= n ? 'bg-cyan-500/40' : 'bg-white/[0.06]'}`} />}
n ? 'bg-emerald-500/10 text-emerald-300 border border-emerald-500/20' : 'bg-white/[0.03] text-white/30 border border-white/[0.06]' }`} > {step > n ? : icon} {label}
))}
{/* ═══════════════ STEP CONTENT ═══════════════ */}
{/* Step 1: Details */} {step === 1 && (

Name your session

Give your meeting room a name and optional description.

setName(e.target.value)} placeholder="e.g., Morning Standup, Strategy Review..." className="w-full px-3.5 py-2.5 rounded-xl bg-white/[0.04] border border-white/[0.08] text-sm text-white placeholder:text-white/20 focus:outline-none focus:border-cyan-500/40 transition-colors" autoFocus />