cb649aac34
Ampel / ampel (push) Successful in 24s
Die Seite verlangte eine technische Weichenstellung, BEVOR man gesagt hat was man will — mit Begriffen aus dem Maschinenraum (BOX / IDE: SIMPEL / IDE: GRUENDLICH). Deshalb klebten 116 Woerter Beipackzettel unter einem einzigen Eingabefeld. Zwei unabhaengige Entscheidungen, vorher in vier sich ausschliessende Knoepfe gepresst: wer — die Box allein, oder ein Repo fuer Zed nurDenken — erst nur ein Konzept (passt zu beidem, jetzt ein Haken) Die Knoepfe nennen das ERGEBNIS statt des Werkzeugs, und der erklaerende Satz steht an der Option statt in einer Legende darunter. Neu: POST /api/ideen/einordnen — das dauerwarme Hirn liest den getippten Text und waehlt vor (gemessen ~500 ms, 5 von 5 Testfaellen richtig, inkl. "Lohnt sich...?" -> nur denken). Bewusst ein VORSCHLAG mit sichtbarem Etikett: er setzt nur die Auswahl, die ohnehin dasteht. Faellt er aus, bleibt schlicht die Voreinstellung — das Tippen wird nie blockiert, es gibt keinen Ladebalken und keine Fehlermeldung. Tiefe und Ziel erscheinen nur noch beim Repo-Weg, weil sie nur dort wirken. Ein Schalter der nichts tut ist schlimmer als keiner. Leerer Zustand zeigt drei anklickbare Beispiele statt "wirf der Box eine Idee zu". Kopfzeile nennt nur noch den Zustand — "Ideen" stand dreimal uebereinander. Die API bleibt unveraendert; die Abbildung passiert in submit(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
31 lines
35 KiB
JavaScript
31 lines
35 KiB
JavaScript
import{c as I,j as e,e as S,ac as be,u as ke,b as je,r as d,g as z,af as Ne,a9 as M,L as D,X as J,M as O,V as de,C as we,D as Q,T as ye,ad as ve,ag as ue,ah as Se,q as De,a3 as xe}from"./index-DI19YZ2i.js";import{S as Ce,H as he}from"./SectionLabel-DJ0JNfWI.js";import{S as ce}from"./send-CpIJWZ5L.js";import{C as X}from"./code-xml-C9b7xGyM.js";import{L as Ke}from"./layers-DQdxWFgI.js";import{R as ze}from"./rotate-ccw-CBUivZG3.js";/**
|
||
* @license lucide-react v0.460.0 - ISC
|
||
*
|
||
* This source code is licensed under the ISC license.
|
||
* See the LICENSE file in the root directory of this source tree.
|
||
*/const Ee=I("ArrowDown",[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]]);/**
|
||
* @license lucide-react v0.460.0 - ISC
|
||
*
|
||
* This source code is licensed under the ISC license.
|
||
* See the LICENSE file in the root directory of this source tree.
|
||
*/const Le=I("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/**
|
||
* @license lucide-react v0.460.0 - ISC
|
||
*
|
||
* This source code is licensed under the ISC license.
|
||
* See the LICENSE file in the root directory of this source tree.
|
||
*/const Pe=I("ClipboardCheck",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2",key:"116196"}],["path",{d:"m9 14 2 2 4-4",key:"df797q"}]]);/**
|
||
* @license lucide-react v0.460.0 - ISC
|
||
*
|
||
* This source code is licensed under the ISC license.
|
||
* See the LICENSE file in the root directory of this source tree.
|
||
*/const Ae=I("GitFork",[["circle",{cx:"12",cy:"18",r:"3",key:"1mpf1b"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["path",{d:"M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9",key:"1uq4wg"}],["path",{d:"M12 12v3",key:"158kv8"}]]);/**
|
||
* @license lucide-react v0.460.0 - ISC
|
||
*
|
||
* This source code is licensed under the ISC license.
|
||
* See the LICENSE file in the root directory of this source tree.
|
||
*/const Be=I("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);function Re({text:s,className:p}){const N=(s||"").split(`
|
||
`),n=[];let x=[],h=null;const u=g=>{x.length&&(n.push(e.jsx("ul",{className:"mb-3 ml-4 list-disc space-y-1",children:x},g)),x=[])};return N.forEach((g,k)=>{const l=`l${k}`;if(h!==null){g.trimEnd()==="```"?(n.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-foreground/85",children:h.join(`
|
||
`)},l)),h=null):h.push(g);return}if(g.trimStart().startsWith("```")){u(l),h=[];return}const j=g.trimEnd();if(!j.trim()){u(l);return}const y=j.match(/^(#{1,4})\s+(.*)$/);if(y){u(l);const w=y[1].length,o=w===1?"text-base font-bold mt-1 mb-2":w===2?"text-sm font-bold mt-4 mb-1.5":"text-xs font-bold mt-3 mb-1 uppercase tracking-wide text-muted-foreground";n.push(e.jsx("p",{className:S(o,"font-space text-foreground"),children:F(y[2],l)},l));return}const f=j.match(/^\s*[-*•]\s+(.*)$/);if(f){x.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:F(f[1],l)},l));return}const i=j.match(/^\s*\d+\.\s+(.*)$/);if(i){x.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:F(i[1],l)},l));return}u(l),n.push(e.jsx("p",{className:"mb-2 text-xs leading-relaxed text-foreground/85",children:F(j,l)},l))}),u("end"),h!==null&&n.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px]",children:h.join(`
|
||
`)},"code-end")),e.jsx("div",{className:S("max-w-3xl",p),children:n})}function F(s,p){return s.split(/(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g).map((n,x)=>{const h=`${p}-${x}`;return/^\*\*[^*]+\*\*$/.test(n)?e.jsx("b",{className:"font-semibold text-foreground",children:n.slice(2,-2)},h):/^\*[^*]+\*$/.test(n)?e.jsx("i",{children:n.slice(1,-1)},h):/^`[^`]+`$/.test(n)?e.jsx("code",{className:"rounded bg-background/50 px-1 font-mono text-[11px] text-foreground/90",children:n.slice(1,-1)},h):e.jsx("span",{children:n},h)})}const We={triage:{label:"wird ausgearbeitet …",cls:"text-violet-300 border-violet-500/40 bg-violet-500/10",spin:!0},todo:{label:"wartet",cls:"text-muted-foreground border-border/60 bg-background/30"},scheduled:{label:"geplant",cls:"text-muted-foreground border-border/60 bg-background/30"},ready:{label:"gleich dran",cls:"text-sky-300/80 border-sky-500/30 bg-sky-500/5"},running:{label:"in Arbeit …",cls:"text-sky-300 border-sky-500/40 bg-sky-500/10",spin:!0},review:{label:"im Review",cls:"text-amber-300 border-amber-500/40 bg-amber-500/10"},blocked:{label:"hängt — braucht dich",cls:"text-red-300 border-red-500/40 bg-red-500/10"},done:{label:"fertig ✓",cls:"text-emerald-300 border-emerald-500/40 bg-emerald-500/10"}},$e={box:{label:"BOX",icon:he,cls:"border-border/60 bg-background/40 text-muted-foreground",title:"Box-Welt: die Werkstatt baut das selbst. Das Ergebnis kommt als Patch-Vorschlag zurück — nichts geht ohne deinen Klick live."},idee:{label:"IDEE",icon:M,cls:"border-sky-500/40 bg-sky-500/10 text-sky-300",title:"Nur durchdacht: die Box hat die Produkt-Idee mit voller Denk-Kaskade zu einem Konzept ausgearbeitet. Kein Gerüst, kein Bau — du liest es und entscheidest, ob ein Projekt draus wird."},projekt:{label:"IDE",icon:X,cls:"border-violet-500/40 bg-violet-500/10 text-violet-300",title:"IDE-Welt: die Box bereitet nur vor (Konzept + Repo + Doku, kein Code). Gebaut wird von dir in Zed."}},Te={needs_input:"Die Box hat eine Frage:",capability:"Die Box kam hier nicht weiter:",transient:"Die Aufgabe hakt:"};function Oe(){var ne,ae;const{data:s,isLoading:p}=be(),N=ke(),{showAlert:n,showConfirm:x,dialogElement:h}=je(),[u,g]=d.useState(""),[k,l]=d.useState("box"),[j,y]=d.useState("schlank"),[f,i]=d.useState(!1),[w,o]=d.useState(!1),P=k==="zed"||f,W=k==="zed"&&!f,[C,me]=d.useState("lxc"),[_,U]=d.useState(!1),[v,E]=d.useState({}),[$,pe]=d.useState(null),[G,ge]=d.useState(null),[q,Y]=d.useState({}),A=(s==null?void 0:s.items)??[],B=()=>N.invalidateQueries({queryKey:De.ideen});d.useEffect(()=>{const t=u.trim();if(t.length<12){o(!1);return}let r=!1;const c=setTimeout(async()=>{try{const m=await z("/api/ideen/einordnen",{method:"POST",body:JSON.stringify({text:t})});if(r||!(m!=null&&m.ok))return;m.wer&&l(m.wer),m.tiefe&&y(m.tiefe),i(!!m.nur_denken),o(!0)}catch{}},700);return()=>{r=!0,clearTimeout(c)}},[u]);const ee=$!==null&&(((ne=s==null?void 0:s.items.find(t=>t.id===$))==null?void 0:ne.status)==="triage"||((ae=s==null?void 0:s.items.find(t=>t.id===$))==null?void 0:ae.status)==="running"),T=Ne($??"",ee);async function te(){const t=u.trim();if(!(t.length<3||_)){U(!0);try{const r=t.length>160?t.slice(0,157)+"…":t;await z("/api/ideen",{method:"POST",body:JSON.stringify({titel:r,notiz:t.length>160?t:"",welt:P?"ide":"box",tiefe:W?j==="gruendlich"?"gruendlich":"simpel":"",ziel:W?C:"",art:f?"idee":"projekt"})}),g(""),o(!1),B()}catch(r){n("Das hat nicht geklappt",String((r==null?void 0:r.message)||r))}finally{U(!1)}}}function re(t,r,c){x(`${r} fertige Karte${r===1?"":"n"} wegräumen?`,`${c} verschwindet aus der Liste. Gelöscht wird nichts — die Karten wandern ins Archiv der Queue und bleiben dort lesbar. Laufende, hängende und wartende Karten bleiben unberührt.`,async()=>{var b;const m="arch:"+(t||"*");E(a=>({...a,[m]:!0}));try{const a=await z("/api/ideen/archivieren-alle",{method:"POST",body:JSON.stringify({projekt:t})});(b=a.fehlgeschlagen)!=null&&b.length&&n("Teilweise erledigt",`${a.archiviert} weggeräumt, ${a.fehlgeschlagen.length} nicht: `+a.fehlgeschlagen.map(L=>L.titel).join(", ")),B()}catch(a){n("Das hat nicht geklappt",String((a==null?void 0:a.message)||a))}finally{E(a=>({...a,[m]:!1}))}})}async function fe(t){E(r=>({...r,[t]:!0}));try{await z("/api/ideen/archivieren",{method:"POST",body:JSON.stringify({id:t})}),B()}catch(r){n("Das hat nicht geklappt",String((r==null?void 0:r.message)||r))}finally{E(r=>({...r,[t]:!1}))}}async function V(t,r,c,m){E(b=>({...b,[t+r]:!0}));try{await z(c,{method:"POST",body:JSON.stringify(m)}),B()}catch(b){n("Das hat nicht geklappt",String((b==null?void 0:b.message)||b))}finally{E(b=>({...b,[t+r]:!1}))}}async function se(t){const r=(q[t]||"").trim();if(!(r.length<1||v["ans:"+t])){E(c=>({...c,["ans:"+t]:!0}));try{await z("/api/ideen/antwort",{method:"POST",body:JSON.stringify({id:t,antwort:r})}),Y(c=>({...c,[t]:""})),B()}catch(c){n("Das hat nicht geklappt",String((c==null?void 0:c.message)||c))}finally{E(c=>({...c,["ans:"+t]:!1}))}}}const Z=t=>{var oe,le;const r=We[t.status]??{label:t.status,cls:"text-muted-foreground border-border/60 bg-background/30"},c=$===t.id,m=t.status==="triage"||t.status==="running"||t.status==="done",b=t.status==="blocked",a=!!v["ans:"+t.id],L=t.status==="running"&&(t.puls_alter??0)>600,ie=t.status==="todo"||t.status==="ready"||t.status==="scheduled";return e.jsxs("li",{className:S("flex flex-col gap-2 rounded-xl border bg-background/30 px-3 py-2",b?"border-red-500/30":L?"border-amber-500/40":"border-border/40"),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:S("flex shrink-0 items-center gap-1.5 rounded-lg border px-2 py-0.5 text-[10px] font-bold",r.cls),children:[r.spin&&e.jsx(D,{className:"h-3 w-3 animate-spin"}),r.label]}),L&&e.jsxs("span",{className:"flex shrink-0 items-center gap-1 rounded-lg border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[10px] font-bold text-amber-300",title:"Der Worker lebt, gibt aber kein Lebenszeichen mehr — vermutlich wartet er auf etwas, das nie kommt. „Neuer Versuch“ startet die Karte frisch.",children:[e.jsx(ye,{className:"h-3 w-3"})," ",Math.round((t.puls_alter??0)/60)," min ohne Regung"]}),(t.prio??0)!==0&&e.jsxs("span",{className:"shrink-0 rounded bg-background/50 px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground",title:"Priorität — höher kommt zuerst dran (bei gleicher Prio: Erstellzeit)",children:["P",t.prio]}),(()=>{const K=$e[t.art||(t.welt==="ide"?"projekt":"box")];if(!K)return null;const H=K.icon;return e.jsxs("span",{className:S("flex shrink-0 items-center gap-1 rounded-lg border px-2 py-0.5 text-[10px] font-bold",K.cls),title:K.title,children:[e.jsx(H,{className:"h-3 w-3"})," ",K.label]})})(),e.jsx("span",{className:"min-w-0 flex-1 truncate text-xs text-foreground",title:t.titel,children:t.titel}),e.jsxs("span",{className:"flex shrink-0 items-center gap-1 text-[10px] text-muted-foreground/70",children:[e.jsx(de,{className:"h-3 w-3"}),ve(t.erstellt)]}),ie&&e.jsxs("span",{className:"flex shrink-0 items-center",children:[e.jsx("button",{disabled:!!v["pr:"+t.id],onClick:()=>V("pr:",t.id,"/api/ideen/prio",{id:t.id,richtung:"hoch"}),title:"Vorziehen (Prio +1)",className:"rounded-md p-1 text-muted-foreground/60 transition-colors hover:text-foreground cursor-pointer disabled:opacity-50",children:e.jsx(Le,{className:"h-3.5 w-3.5"})}),e.jsx("button",{disabled:!!v["pr:"+t.id],onClick:()=>V("pr:",t.id,"/api/ideen/prio",{id:t.id,richtung:"runter"}),title:"Zurückstellen (Prio −1)",className:"rounded-md p-1 text-muted-foreground/60 transition-colors hover:text-foreground cursor-pointer disabled:opacity-50",children:e.jsx(Ee,{className:"h-3.5 w-3.5"})})]}),(t.status==="running"||b)&&e.jsx("button",{disabled:!!v["rt:"+t.id],onClick:()=>x("Neuer Versuch?",t.status==="running"?`Der laufende Worker von '${t.titel.slice(0,60)}' wird beendet (samt gestarteter Test-Prozesse) und die Karte frisch gestartet. Bisheriger Zwischenstand im Workspace bleibt liegen.`:`Die Karte '${t.titel.slice(0,60)}' wird entsperrt und läuft weiter, sobald ein Platz frei ist.`,()=>V("rt:",t.id,"/api/ideen/retry",{id:t.id})),title:"Neuer Versuch — Karte frisch starten",className:S("shrink-0 rounded-md p-1 transition-colors cursor-pointer disabled:opacity-50",L?"text-amber-300 hover:text-amber-200":"text-muted-foreground/60 hover:text-foreground"),children:v["rt:"+t.id]?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(ze,{className:"h-3.5 w-3.5"})}),(t.status==="running"||ie||t.status==="triage")&&e.jsx("button",{disabled:!!v["st:"+t.id],onClick:()=>x("Karte stoppen?",`'${t.titel.slice(0,60)}' wird angehalten${t.status==="running"?" und der laufende Worker beendet":""}. Sie bleibt als gestoppt im Board und kann jederzeit per „Neuer Versuch“ weiterlaufen.`,()=>V("st:",t.id,"/api/ideen/stopp",{id:t.id})),title:"Stoppen — Karte anhalten",className:"shrink-0 rounded-md p-1 text-muted-foreground/60 transition-colors hover:text-red-300 cursor-pointer disabled:opacity-50",children:v["st:"+t.id]?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(Be,{className:"h-3.5 w-3.5"})}),(t.status==="done"||b)&&e.jsx("button",{disabled:!!v[t.id],onClick:()=>fe(t.id),title:b?"Aufgeben und aus der Liste räumen (wandert ins Kanban-Archiv)":"Aus der Liste räumen (wandert ins Kanban-Archiv)",className:"shrink-0 rounded-md p-1 text-muted-foreground/60 transition-colors hover:text-foreground cursor-pointer disabled:opacity-50",children:v[t.id]?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(J,{className:"h-3.5 w-3.5"})}),t.welt==="ide"&&(t.status==="running"||t.status==="done")&&e.jsxs("button",{onClick:()=>ge(G===t.id?null:t.id),title:"Konzept ansehen (das ausgearbeitete KONZEPT.md)",className:S("flex shrink-0 items-center gap-1 rounded-md px-1.5 py-1 text-[10px] font-bold transition-colors cursor-pointer",G===t.id?"text-violet-300":"text-violet-300/70 hover:text-violet-200"),children:[e.jsx(ue,{className:"h-3.5 w-3.5"})," Konzept"]}),m&&e.jsx("button",{onClick:()=>pe(c?null:t.id),title:t.status==="done"?"Ergebnis anzeigen":"Worker-Log anzeigen",className:"shrink-0 rounded-md p-1 text-muted-foreground/60 transition-colors hover:text-foreground cursor-pointer",children:c?e.jsx(Q,{className:"h-3.5 w-3.5"}):e.jsx(O,{className:"h-3.5 w-3.5"})})]}),G===t.id&&e.jsx(Ve,{id:t.id,istIdee:t.art==="idee"&&t.status==="done",onWeiter:B}),t.status==="running"&&t.notiz&&e.jsxs("p",{className:"-mt-1 ml-1 text-[11px] italic leading-relaxed text-sky-200/80",title:"Jüngste Zwischenmeldung des Workers (Heartbeat)",children:["„",t.notiz,"“"]}),(t.status==="todo"||t.status==="scheduled"||t.status==="ready")&&(((oe=t.wartet_auf)==null?void 0:oe.length)??0)>0&&e.jsxs("p",{className:"-mt-1 ml-1 text-[10px] text-muted-foreground/70",children:["→ wartet auf: ",t.wartet_auf.join(" · ")]}),b&&e.jsxs("div",{className:"space-y-2 border-t border-red-500/20 pt-2",children:[e.jsxs("p",{className:"flex items-start gap-1.5 text-[11px] leading-relaxed text-red-200/90",children:[e.jsx(Se,{className:"mt-0.5 h-3.5 w-3.5 shrink-0 text-red-300"}),e.jsxs("span",{children:[e.jsx("b",{children:Te[t.frage_kind||""]??"Die Aufgabe hängt und wartet auf dich:"})," ",t.frage?e.jsx("span",{className:"text-foreground/90",children:t.frage}):e.jsx("span",{className:"text-muted-foreground italic",children:"kein genauer Grund hinterlegt — antworte einfach mit einer Entscheidung, dann läuft sie weiter."})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:q[t.id]||"",onChange:K=>Y(H=>({...H,[t.id]:K.target.value})),onKeyDown:K=>{K.key==="Enter"&&se(t.id)},placeholder:"Deine Antwort — die Box macht damit weiter",maxLength:2e3,className:"h-8 min-w-0 flex-1 rounded-lg border border-border/60 bg-background/60 px-2.5 text-xs text-foreground placeholder:text-muted-foreground/50 focus:border-red-400/50 focus:outline-none"}),e.jsxs("button",{onClick:()=>se(t.id),disabled:a||(q[t.id]||"").trim().length<1,className:"flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-emerald-500/40 bg-emerald-500/10 px-3 text-[10px] font-bold uppercase tracking-wide text-emerald-300 transition-all hover:bg-emerald-500/20 cursor-pointer disabled:opacity-50",children:[a?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(ce,{className:"h-3.5 w-3.5"})," Antworten & weiter"]})]})]}),c&&m&&t.status!=="done"&&e.jsx("div",{className:"ml-2 -mt-1",children:e.jsx("div",{className:"rounded-lg border border-border/50 bg-background/50 p-2",children:ee&&T.isLoading?e.jsx("p",{className:"text-[10px] text-muted-foreground animate-pulse",children:"Log wird geladen …"}):T.error?e.jsx("p",{className:"text-[10px] text-red-400",children:"Log nicht ladbar"}):(le=T.data)!=null&&le.available&&T.data.lines.length>0?e.jsx("pre",{className:"max-h-64 overflow-auto font-mono text-[10px] leading-relaxed text-foreground/80 whitespace-pre-wrap",children:T.data.lines.join(`
|
||
`)}):e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Kein Log verfügbar"})})}),c&&t.status==="done"&&e.jsx(Fe,{id:t.id})]},t.id)};return s&&!s.available?null:e.jsxs("section",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(Ce,{icon:M,children:(()=>{if(!s)return"Ideen-Queue";const t=c=>A.filter(m=>c.includes(m.status)).length,r=[t(["blocked"])>0?`${t(["blocked"])} braucht dich`:"",t(["running","triage","review"])>0?`${t(["running","triage","review"])} in Arbeit`:"",t(["todo","scheduled","ready"])>0?`${t(["todo","scheduled","ready"])} wartet`:"",t(["done"])>0?`${t(["done"])} fertig`:""].filter(Boolean);return r.length?r.join(" · "):"noch nichts in der Queue"})()}),(()=>{const t=A.filter(r=>r.status==="done").length;return t===0?null:e.jsxs("button",{disabled:!!v["arch:*"],onClick:()=>re("",t,`Alle ${t} fertigen Karten`),title:"Räumt ALLE fertigen Karten weg — auch die in abgeschlossenen Projekt-Ketten. Laufende, hängende und wartende bleiben unberührt.",className:"flex shrink-0 items-center gap-1.5 rounded-lg border border-border/60 px-2.5 py-1 text-[11px] font-semibold text-muted-foreground transition-all hover:border-primary/40 hover:text-foreground disabled:opacity-50 cursor-pointer",children:[v["arch:*"]?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(J,{className:"h-3.5 w-3.5"}),t," fertige wegräumen"]})})()]}),e.jsxs("div",{className:"mc-card p-4 space-y-4",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:u,onChange:t=>{g(t.target.value),o(!1)},onKeyDown:t=>{t.key==="Enter"&&te()},placeholder:"Was soll entstehen?",className:"h-10 min-w-0 flex-1 rounded-lg border border-border/60 bg-background/50 px-3 text-sm text-foreground placeholder:text-muted-foreground/50 focus:border-primary/50 focus:outline-none"}),e.jsxs("button",{onClick:te,disabled:_||u.trim().length<3,className:"flex h-10 shrink-0 items-center gap-1.5 rounded-lg border border-primary/40 bg-primary/10 px-4 text-xs font-semibold text-primary transition-all hover:bg-primary/20 disabled:opacity-40 cursor-pointer",children:[_?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(ce,{className:"h-4 w-4"}),"Los"]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"mb-1.5 text-[11px] text-muted-foreground/70",children:"Wer baut das?"}),e.jsx("div",{className:"grid gap-2 sm:grid-cols-2",children:[{id:"box",icon:he,titel:"Die Box, allein",text:"Sie baut es und legt dir das Ergebnis als Vorschlag hin — nichts geht ohne deinen Klick live."},{id:"zed",icon:X,titel:"Ich, in Zed",text:"Du bekommst ein fertiges Repo mit Konzept und Doku. Den Code schreibst du selbst."}].map(t=>{const r=k===t.id;return e.jsxs("button",{onClick:()=>{l(t.id),o(!1)},disabled:f,className:S("rounded-xl border p-3 text-left transition-all cursor-pointer disabled:cursor-default",f?"border-border/30 opacity-40":r?"border-primary/60 bg-primary/5":"border-border/50 hover:border-border"),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(t.icon,{className:S("h-4 w-4 shrink-0",r&&!f?"text-primary":"text-muted-foreground")}),e.jsx("span",{className:"text-xs font-semibold text-foreground",children:t.titel}),r&&w&&!f&&e.jsx("span",{className:"ml-auto shrink-0 rounded border border-primary/40 bg-primary/10 px-1.5 py-0.5 text-[10px] font-bold text-primary",children:"Vorschlag"})]}),e.jsx("p",{className:"mt-1 text-[11px] leading-relaxed text-muted-foreground",children:t.text})]},t.id)})}),f&&e.jsx("p",{className:"mt-1.5 text-[10px] text-muted-foreground/60",children:"Wer baut, entscheidest du, wenn das Konzept da ist."})]}),W&&e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2",children:[e.jsx("span",{className:"text-[11px] text-muted-foreground/70",children:"Wie gründlich?"}),e.jsx("div",{className:"flex rounded-lg border border-border/60 p-0.5",children:[["schlank","schlank"],["gruendlich","gründlich"]].map(([t,r])=>e.jsx("button",{onClick:()=>{y(t),o(!1)},className:S("rounded px-2.5 py-1 text-[10px] font-bold uppercase tracking-wide transition-all cursor-pointer",j===t?"bg-primary/15 text-primary":"text-muted-foreground/60 hover:text-foreground"),children:r},t))}),e.jsx("span",{className:"text-[10px] text-muted-foreground/60",children:j==="gruendlich"?"mehrere Fach-Rollen, bis zu 3 Denk-Runden, mehrfacher Härtetest — dauert entsprechend":"2 Rollen, eine Denk-Runde — ein paar Minuten"}),e.jsxs("span",{className:"ml-auto flex items-center gap-1.5",children:[e.jsx("span",{className:"text-[11px] text-muted-foreground/70",children:"Läuft als"}),e.jsx("div",{className:"flex rounded-lg border border-border/40 p-0.5",children:[["lxc","LXC"],["docker","Docker"]].map(([t,r])=>e.jsx("button",{onClick:()=>me(t),title:t==="lxc"?"Dienst in einem eigenen Proxmox-LXC (systemd, kein Docker). Wird vom Backup-Server automatisch mitgesichert.":"Natives Docker: Dockerfile + compose, portabel und pipeline-tauglich.",className:S("rounded px-2 py-0.5 text-[10px] font-semibold transition-all cursor-pointer",C===t?"bg-foreground/10 text-foreground":"text-muted-foreground/50 hover:text-foreground/80"),children:r},t))})]})]}),e.jsxs("label",{className:"flex cursor-pointer items-start gap-2 border-t border-border/30 pt-3",children:[e.jsx("input",{type:"checkbox",checked:f,onChange:t=>{i(t.target.checked),o(!1)},className:"mt-0.5 h-3.5 w-3.5 shrink-0 accent-sky-400 cursor-pointer"}),e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"text-xs font-semibold text-foreground",children:"Erst nur durchdenken, noch nichts anlegen"}),e.jsx("span",{className:"mt-0.5 block text-[11px] leading-relaxed text-muted-foreground",children:"Die Box arbeitet die Idee mit Produkt-Blick aus — was ist es, für wen, was gibt es schon, was wäre der kleinste sinnvolle Wurf, was spricht dagegen. Ergebnis ist ein Konzept: kein Repo, kein Code, kein Bau-Druck."})]})]}),p&&e.jsxs("p",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"})," Queue wird geladen …"]}),(s==null?void 0:s.fehler)&&e.jsx("p",{className:"text-xs text-amber-300",children:"Queue gerade nicht lesbar — neuer Versuch läuft."}),A.length>0&&e.jsxs("div",{className:"space-y-3",children:[((s==null?void 0:s.projekte)??[]).map(t=>e.jsx(Ie,{projekt:t,karten:A.filter(r=>r.projekt===t.key),zeile:Z,onArchivAlle:re,raeumt:!!v["arch:"+t.key]},t.key)),(()=>{const t=new Set(((s==null?void 0:s.projekte)??[]).map(a=>a.key)),r=A.filter(a=>!a.projekt||!t.has(a.projekt));if(r.length===0)return null;const c=r.filter(a=>R[a.status]!==void 0).sort((a,L)=>R[a.status]-R[L.status]||(a.erstellt??0)-(L.erstellt??0)),m=r.filter(a=>["todo","scheduled"].includes(a.status)),b=r.filter(a=>a.status==="done");return e.jsxs("div",{className:"space-y-2",children:[c.length>0&&e.jsx("ul",{className:"space-y-1.5",children:c.map(a=>Z(a))}),m.length>0&&e.jsxs("details",{className:"group",children:[e.jsxs("summary",{className:"flex cursor-pointer list-none items-center gap-1.5 py-1 text-[11px] text-muted-foreground/70 hover:text-foreground",children:[e.jsx(O,{className:"h-3 w-3 transition-transform group-open:rotate-90"}),e.jsx(de,{className:"h-3 w-3"})," Wartet (",m.length,")"]}),e.jsx("ul",{className:"mt-1.5 space-y-1.5",children:m.map(a=>Z(a))})]}),b.length>0&&e.jsxs("details",{className:"group",children:[e.jsxs("summary",{className:"flex cursor-pointer list-none items-center gap-1.5 py-1 text-[11px] text-muted-foreground/70 hover:text-foreground",children:[e.jsx(O,{className:"h-3 w-3 transition-transform group-open:rotate-90"}),e.jsx(we,{className:"h-3 w-3 text-emerald-400/70"})," Fertig (",b.length,")"]}),e.jsx("ul",{className:"mt-1.5 space-y-1.5",children:b.map(a=>Z(a))})]})]})})()]}),(s==null?void 0:s.available)&&!p&&A.length===0&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-[11px] text-muted-foreground/70",children:"Noch nichts hier. Zum Beispiel:"}),["Ein kleines Werkzeug, das meine Fotos nach Aufnahmedatum in Ordner sortiert","Rippy soll die Untertitel-Spur automatisch auswählen statt zu fragen","Lohnt sich ein Dashboard für die Stromzähler, oder reicht Home Assistant?"].map(t=>e.jsxs("button",{onClick:()=>g(t),className:"flex w-full items-center gap-2 rounded-lg border border-border/40 bg-background/20 px-3 py-2 text-left text-xs text-muted-foreground transition-all hover:border-primary/40 hover:text-foreground cursor-pointer",children:[e.jsx(M,{className:"h-3.5 w-3.5 shrink-0 text-muted-foreground/50"}),t]},t))]})]}),h]})}const R={blocked:0,running:1,review:2,ready:3,triage:4};function Ie({projekt:s,karten:p,zeile:N,onArchivAlle:n,raeumt:x}){const[h,u]=d.useState(!1),[g,k]=d.useState(!1),l=p.filter(i=>R[i.status]!==void 0).sort((i,w)=>R[i.status]-R[w.status]||(i.erstellt??0)-(w.erstellt??0)),j=p.filter(i=>i.status==="todo"||i.status==="scheduled").sort((i,w)=>{var o,P;return((o=i.wartet_auf)!=null&&o.length?1:0)-((P=w.wartet_auf)!=null&&P.length?1:0)||(i.erstellt??0)-(w.erstellt??0)}),y=p.filter(i=>i.status==="done").sort((i,w)=>(w.fertig??0)-(i.fertig??0)),f=s.gesamt>0?Math.round(s.fertig/s.gesamt*100):0;return e.jsxs("div",{className:"space-y-2 rounded-xl border border-border/50 bg-background/20 p-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ke,{className:"h-4 w-4 shrink-0 text-primary/70"}),e.jsx("p",{className:"min-w-0 flex-1 truncate text-xs font-semibold text-foreground",title:s.titel,children:s.titel}),e.jsxs("span",{className:"shrink-0 text-[10px] text-muted-foreground",children:[s.fertig," von ",s.gesamt," fertig"]})]}),e.jsx("div",{className:"h-1 overflow-hidden rounded-full bg-background/60",title:`${f}%`,children:e.jsx("div",{className:"h-1 rounded-full bg-primary/70 transition-all",style:{width:`${f}%`}})}),l.length>0&&e.jsx("ul",{className:"space-y-1.5",children:l.map(i=>N(i))}),j.length>0&&e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>u(i=>!i),className:"flex items-center gap-1.5 text-[11px] font-semibold text-muted-foreground hover:text-foreground transition-colors cursor-pointer",children:[h?e.jsx(Q,{className:"h-3.5 w-3.5"}):e.jsx(O,{className:"h-3.5 w-3.5"}),j.length," Karte",j.length===1?"":"n"," in der Kette — laufen automatisch der Reihe nach"]}),h&&e.jsx("ul",{className:"mt-1.5 space-y-1.5",children:j.map(i=>N(i))})]}),y.length>0&&e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{onClick:()=>k(i=>!i),className:"flex items-center gap-1.5 text-[11px] font-semibold text-emerald-300/70 hover:text-emerald-300 transition-colors cursor-pointer",children:[g?e.jsx(Q,{className:"h-3.5 w-3.5"}):e.jsx(O,{className:"h-3.5 w-3.5"}),y.length," fertig"]}),n&&e.jsxs("button",{disabled:x,onClick:()=>n(s.key,y.length,`„${s.titel}"`),title:"Räumt die fertigen Karten dieser Kette weg (Archiv, nichts wird gelöscht).",className:"flex items-center gap-1 text-[11px] text-muted-foreground/60 transition-colors hover:text-foreground disabled:opacity-50 cursor-pointer",children:[x?e.jsx(D,{className:"h-3 w-3 animate-spin"}):e.jsx(J,{className:"h-3 w-3"}),"wegräumen"]})]}),g&&e.jsx("ul",{className:"mt-1.5 space-y-1.5",children:y.map(i=>N(i))})]})]})}function Ve({id:s,istIdee:p,onWeiter:N}){const[n,x]=d.useState(null),[h,u]=d.useState(!1),[g,k]=d.useState(0);return d.useEffect(()=>{let l=!1;return x(null),u(!1),z(`/api/ideen/${s}/konzept`).then(j=>{l||x(j)}).catch(()=>{l||u(!0)}),()=>{l=!0}},[s,g]),e.jsx("div",{className:"ml-2 -mt-1",children:e.jsxs("div",{className:"rounded-lg border border-violet-500/25 bg-violet-500/[0.04] p-3",children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsxs("p",{className:"flex items-center gap-1.5 text-[10px] font-bold uppercase tracking-wide text-violet-300",children:[e.jsx(ue,{className:"h-3 w-3"})," Konzept"]}),(n==null?void 0:n.repo)&&e.jsxs("a",{href:`https://git.tobisniceshomelab.ddnsfree.com/${n.repo}`,className:"flex items-center gap-1 text-[10px] text-violet-300/70 hover:text-violet-200",children:[e.jsx(Ae,{className:"h-3 w-3"})," ",n.repo]}),!(n!=null&&n.repo)&&(n==null?void 0:n.quelle)==="datei"&&e.jsx("span",{className:"truncate font-mono text-[10px] text-muted-foreground/70",title:"Der Worker hat kein Repo angelegt — das Konzept liegt als Datei auf der Box.",children:n.pfad}),e.jsx("button",{onClick:()=>k(l=>l+1),title:"Neu laden",className:"ml-auto rounded p-0.5 text-muted-foreground/50 hover:text-foreground cursor-pointer",children:e.jsx(xe,{className:"h-3 w-3"})})]}),h?e.jsx("p",{className:"text-[11px] text-red-400",children:"Konzept nicht ladbar — später nochmal versuchen."}):n===null?e.jsx("p",{className:"text-[10px] text-muted-foreground animate-pulse",children:"Konzept wird geladen …"}):n.konzept?e.jsx("div",{className:"max-h-[28rem] overflow-y-auto pr-1",children:e.jsx(Re,{text:n.konzept})}):e.jsx("p",{className:"text-[11px] text-muted-foreground italic",children:n.error||"Noch kein Konzept — das Projekt wird gerade vorbereitet."}),p&&(n==null?void 0:n.konzept)&&e.jsx(Ze,{id:s,onFertig:N})]})})}function Ze({id:s,onFertig:p}){const[N,n]=d.useState("lxc"),[x,h]=d.useState("simpel"),[u,g]=d.useState(!1),[k,l]=d.useState(null),[j,y]=d.useState(""),[f,i]=d.useState(""),w=async(o,P,W)=>{g(!0),y("");try{const C=await z(o,{method:"POST",body:JSON.stringify(P)});l({id:C.id,art:W}),p==null||p()}catch(C){y(String((C==null?void 0:C.message)||C))}finally{g(!1)}};return k?e.jsx("p",{className:"mt-3 border-t border-violet-500/20 pt-2 text-[11px] text-emerald-300",children:k.art==="projekt"?e.jsxs(e.Fragment,{children:["Projekt-Karte ",e.jsx("span",{className:"font-mono",children:k.id})," ist angelegt — die Box bereitet das Repo vor (Konzept übernimmt sie, sie denkt es nicht neu). Danach öffnest du es in Zed."]}):e.jsxs(e.Fragment,{children:["Überarbeitung ",e.jsx("span",{className:"font-mono",children:k.id}),' läuft — die Box arbeitet deine Rückmeldung ein und schreibt die neue Fassung an dieselbe Stelle. Danach hier wieder „Konzept" öffnen.']})}):e.jsxs("div",{className:"mt-3 space-y-3 border-t border-violet-500/20 pt-2.5",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:[e.jsx("b",{className:"text-sky-300/90",children:"Passt etwas nicht?"})," Schreib hin, was anders werden soll — die Box arbeitet es ein und lässt den Rest stehen. Beliebig oft wiederholbar."]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:f,onChange:o=>i(o.target.value),onKeyDown:o=>{o.key==="Enter"&&f.trim().length>=3&&!u&&w("/api/ideen/nachschaerfen",{id:s,hinweis:f},"runde")},placeholder:"z. B. „Punkt 3: kein WebSocket, das ist mir zu fragil — nimm Polling“",maxLength:2e3,className:"h-8 min-w-0 flex-1 rounded-lg border border-border/60 bg-background/60 px-2.5 text-xs text-foreground placeholder:text-muted-foreground/50 focus:border-sky-400/50 focus:outline-none"}),e.jsxs("button",{onClick:()=>w("/api/ideen/nachschaerfen",{id:s,hinweis:f},"runde"),disabled:u||f.trim().length<3,className:"flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-sky-500/40 bg-sky-500/10 px-3 text-[10px] font-bold uppercase tracking-wide text-sky-300 transition-all hover:bg-sky-500/20 cursor-pointer disabled:opacity-50",children:[u?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(xe,{className:"h-3.5 w-3.5"}),"Nachschärfen"]})]})]}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:[e.jsx("b",{className:"text-violet-300/90",children:"Passt es so?"})," Dann macht die Box daraus ein startklares Repo — Konzept wird übernommen (nicht neu gedacht), dazu Roadmap, AGENTS.md & Co. Gebaut wird danach von dir in Zed."]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2",children:[e.jsx("span",{className:"text-[11px] text-muted-foreground/70",children:"Ziel"}),e.jsx("div",{className:"flex rounded-lg border border-border/40 p-0.5",children:["lxc","docker"].map(o=>e.jsx("button",{onClick:()=>n(o),title:o==="lxc"?"Dienst in einem eigenen Proxmox-LXC (systemd, kein Docker) — wird automatisch mitgesichert.":"Natives Docker: Dockerfile + compose, portabel und pipeline-tauglich.",className:S("rounded px-2 py-0.5 text-[10px] font-semibold transition-all cursor-pointer",N===o?"bg-foreground/10 text-foreground":"text-muted-foreground/50 hover:text-foreground/80"),children:o==="lxc"?"LXC":"Docker"},o))}),e.jsx("span",{className:"text-[11px] text-muted-foreground/70",children:"Aufwand"}),e.jsx("div",{className:"flex rounded-lg border border-border/40 p-0.5",children:["simpel","gruendlich"].map(o=>e.jsx("button",{onClick:()=>h(o),title:o==="simpel"?"Konzept ist schon gehärtet — nur kurz auf die Bau-Sicht nachschärfen (empfohlen).":"Nochmal volle Kaskade über die Bau-Sicht: mehrere Rollen, Härtetests. Dauert entsprechend.",className:S("rounded px-2 py-0.5 text-[10px] font-semibold transition-all cursor-pointer",x===o?"bg-foreground/10 text-foreground":"text-muted-foreground/50 hover:text-foreground/80"),children:o==="simpel"?"schlank":"gründlich"},o))}),e.jsxs("button",{onClick:()=>w("/api/ideen/weiterfuehren",{id:s,ziel:N,tiefe:x},"projekt"),disabled:u,className:"ml-auto flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-violet-500/40 bg-violet-500/10 px-3 text-[10px] font-bold uppercase tracking-wide text-violet-300 transition-all hover:bg-violet-500/20 cursor-pointer disabled:opacity-50",children:[u?e.jsx(D,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(X,{className:"h-3.5 w-3.5"}),"Gefällt mir — Projekt daraus machen"]})]}),j&&e.jsx("p",{className:"text-[11px] text-red-400",children:j})]})}function Fe({id:s}){const[p,N]=d.useState(null),[n,x]=d.useState(!1),[h,u]=d.useState(0);d.useEffect(()=>{let k=!1;return x(!1),N(null),z(`/api/ideen/${s}/ergebnis`).then(l=>{k||N(l)}).catch(()=>{k||x(!0)}),()=>{k=!0}},[s,h]);const g=p?p.summary||p.result:"";return e.jsx("div",{className:"ml-2 -mt-1",children:e.jsxs("div",{className:"rounded-lg border border-emerald-500/25 bg-emerald-500/5 p-2.5",children:[e.jsxs("p",{className:"mb-1 flex items-center gap-1.5 text-[10px] font-bold uppercase tracking-wide text-emerald-300",children:[e.jsx(Pe,{className:"h-3 w-3"})," Ergebnis des Workers"]}),n?e.jsx("button",{type:"button",onClick:()=>u(k=>k+1),className:"text-[10px] text-red-400 underline decoration-dotted underline-offset-2 hover:text-red-300",children:"Ergebnis nicht ladbar — nochmal versuchen"}):p===null?e.jsx("p",{className:"text-[10px] text-muted-foreground animate-pulse",children:"Wird geladen …"}):g?e.jsx("p",{className:"max-h-64 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-foreground/85",children:g}):e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:"Der Worker hat keine Abschluss-Zusammenfassung hinterlassen (ältere Karte oder Protokollverstoß)."})]})})}function Qe(){return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Ideen"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Schreib hin, was entstehen soll — die Box arbeitet es aus. Je nach Modus baut sie es selbst, denkt es nur durch, oder legt dir ein startklares Repo fuer Zed an."})]}),e.jsx(Oe,{})]})}export{Qe as IdeenView};
|