"use client"; /** * QuickLaunch — homepage form to fire an investigation in 1 click without * opening the chat. * * Detective dropdown picks the kind; the form swaps the input label based * on what that kind needs (topic, question, hypothesis_id, person_id). * Submit POSTs to /api/bureau/launch which inserts the job + returns the * job_id; the UI then routes to /jobs/[id]. */ import { useState } from "react"; import { useRouter } from "next/navigation"; import { ArrowUpRight } from "lucide-react"; interface DetectiveOption { slug: string; label: string; kind: string; inputLabel: string; placeholder: string; field: "question" | "topic" | "hypothesis_id" | "person_id"; tone: string; } // Single reader-facing option: assemble a case-file narrative on any topic. // The pipeline (multiple internal mind-clones in parallel) is hidden. const OPTIONS: DetectiveOption[] = [ { slug: "case", label: "Investigar um caso", kind: "case_report", inputLabel: "Tópico ou pergunta", placeholder: "as bolas de fogo verdes sobre Sandia", field: "topic", tone: "text-[#e0c080] border-[#e0c080]", }, ]; export function QuickLaunch() { const router = useRouter(); const opt = OPTIONS[0]; const [value, setValue] = useState(""); const [pending, setPending] = useState(false); const [error, setError] = useState(null); async function submit(e: React.FormEvent) { e.preventDefault(); if (!value.trim()) return; setPending(true); setError(null); try { const payload: Record = { kind: opt.kind }; payload[opt.field] = value.trim(); const r = await fetch("/api/bureau/launch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); const data = (await r.json()) as { job_id?: string; error?: string; message?: string }; if (!r.ok || !data.job_id) { setError(data.error || data.message || `HTTP ${r.status}`); setPending(false); return; } router.push(`/jobs/${data.job_id}`); } catch (e) { setError((e as Error).message); setPending(false); } } return (
🛸 Investigar um caso
setValue(e.target.value)} placeholder={opt.placeholder} aria-label={opt.inputLabel} className="bg-[#060a13] border border-[rgba(224,192,128,0.18)] rounded px-3 py-2 text-[13px] text-[#e7ecf3] placeholder:text-[#5a6678] font-sans" />
{opt.inputLabel} {error && · {error}}
); }