"use client"; import { useState, useEffect } from "react"; import { api } from "@/lib/api"; interface WorkspaceOption { id: string; name: string; tier: number; } export function CreateWorkspaceButton() { const [open, setOpen] = useState(false); return ( <> setOpen(true)} className="fixed bottom-6 right-6 z-40 px-5 py-2.5 bg-blue-600 hover:bg-blue-500 active:bg-blue-700 text-sm font-medium rounded-xl text-white shadow-lg shadow-blue-600/20 hover:shadow-xl hover:shadow-blue-500/30 transition-all duration-200 flex items-center gap-2" > New Workspace {open && setOpen(false)} />} > ); } function CreateDialog({ onClose }: { onClose: () => void }) { const [name, setName] = useState(""); const [role, setRole] = useState(""); const [tier, setTier] = useState(1); const [template, setTemplate] = useState(""); const [parentId, setParentId] = useState(""); const [creating, setCreating] = useState(false); const [error, setError] = useState(null); const [workspaces, setWorkspaces] = useState([]); useEffect(() => { api.get("/workspaces") .then((ws) => setWorkspaces(ws)) .catch(() => {}); }, []); const handleCreate = async () => { if (!name.trim()) { setError("Name is required"); return; } setCreating(true); setError(null); try { await api.post("/workspaces", { name: name.trim(), role: role.trim() || undefined, template: template.trim() || undefined, tier, parent_id: parentId || undefined, canvas: { x: Math.random() * 400 + 100, y: Math.random() * 300 + 100 }, }); onClose(); } catch (e) { setError(e instanceof Error ? e.message : "Failed to create workspace"); } finally { setCreating(false); } }; return ( Create Workspace Add a new workspace node to the canvas Tier {[ { value: 1, label: "T1", desc: "Sandboxed" }, { value: 2, label: "T2", desc: "Standard" }, { value: 3, label: "T3", desc: "Full Access" }, ].map((t) => ( setTier(t.value)} className={`py-2 rounded-lg text-center transition-colors ${ tier === t.value ? "bg-blue-600/20 border border-blue-500/50 text-blue-300" : "bg-zinc-800/60 border border-zinc-700/40 text-zinc-400 hover:text-zinc-300 hover:border-zinc-600" }`} > {t.label} {t.desc} ))} Parent Workspace setParentId(e.target.value)} className="w-full bg-zinc-800/60 border border-zinc-700/50 rounded-lg px-3 py-2 text-sm text-zinc-100 focus:outline-none focus:border-blue-500/60 focus:ring-1 focus:ring-blue-500/20 transition-colors" > None (root level) {workspaces.map((ws) => ( T{ws.tier} ยท {ws.name} ))} {error && ( {error} )} Cancel {creating ? "Creating..." : "Create"} ); } function InputField({ label, value, onChange, placeholder, required, autoFocus, mono, }: { label: string; value: string; onChange: (v: string) => void; placeholder?: string; required?: boolean; autoFocus?: boolean; mono?: boolean; }) { return ( {label} {required && *} onChange(e.target.value)} placeholder={placeholder} autoFocus={autoFocus} className={`w-full bg-zinc-800/60 border border-zinc-700/50 rounded-lg px-3 py-2 text-sm text-zinc-100 placeholder-zinc-600 focus:outline-none focus:border-blue-500/60 focus:ring-1 focus:ring-blue-500/20 transition-colors ${mono ? "font-mono text-xs" : ""}`} /> ); }
Add a new workspace node to the canvas