From b1191452d2a9fa3baee6416655002d552769f77c Mon Sep 17 00:00:00 2001 From: nova-rey Date: Sun, 2 Nov 2025 10:37:42 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20Phase=202=20repair=20=E2=80=94=20add=20?= =?UTF-8?q?Spec=20Builder=20MVP=20(types,=20forms,=20normalize,=20autosave?= =?UTF-8?q?,=20map)=20and=20update=20docs=20[v0.3.0-phase2-baseline]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/ARCHITECTURE.md | 8 ++-- src/components/builder/ProfileForm.tsx | 19 ++++----- src/components/builder/RuleForm.tsx | 58 +++++++++----------------- src/components/builder/TableForm.tsx | 4 +- src/routes/Builder.tsx | 32 ++++++-------- src/spec/authoringTypes.ts | 2 +- src/spec/convert.ts | 24 +++++------ src/state/builderStore.ts | 2 +- 9 files changed, 61 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index 15b31d4..b818bdc 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ A modern, browser-based UI for **CrapsSim-Control (CSC)**. - Navigate to `/builder` to author a spec. - Use **Normalize** to validate/pretty-print via CSC. - Use **Import/Export** to move specs in/out. -- Presets available: Molly, Contra (top-left). +- Presets available: Molly, Contra (panel on the left). ## Repo Boundaries diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f4cc94a..e6bbc14 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -28,9 +28,9 @@ - Response shape is normalized to `{ ok, status, data }` or `{ ok:false, status, message }`. - Mock mode serves JSON from `/mock-data/*` when the API is unavailable. ## Spec Builder (Phase 2) -- Authoring types live in `src/spec/`. +- Authoring types in `src/spec/`. - Conversion `authoring → draft` via `src/spec/convert.ts`. -- `/builder` provides a navigator (spec/profiles/rules), editor forms, and an output panel with Normalize. -- Persistence: localStorage autosave under a single workspace key. -- Import/Export: JSON files for authoring or normalized output. +- `/builder` provides navigator, editor forms, and an output panel with Normalize. +- Persistence: localStorage autosave. +- Import/Export: JSON for authoring or normalized output. - Visual map: read-only tree (profiles + rules). diff --git a/src/components/builder/ProfileForm.tsx b/src/components/builder/ProfileForm.tsx index f693b40..a1076b4 100644 --- a/src/components/builder/ProfileForm.tsx +++ b/src/components/builder/ProfileForm.tsx @@ -1,23 +1,22 @@ -import { BaseBet, Profile } from "../../spec/authoringTypes"; +import { AuthoringSpec, BaseBet, Profile } from "../../spec/authoringTypes"; export default function ProfileForm({ + spec, profile, - onChange, -}: { - profile: Profile; - onChange: (p: Profile) => void; -}) { + onChange +}: { spec: AuthoringSpec; profile: Profile; onChange: (p: Profile) => void }) { + void spec; function updateBet(idx: number, patch: Partial) { const copy = { ...profile, - base_bets: profile.base_bets.map((b, i) => (i === idx ? { ...b, ...patch } : b)), + base_bets: profile.base_bets.map((b, i) => (i === idx ? { ...b, ...patch } : b)) }; onChange(copy); } function addBet() { const copy = { ...profile, - base_bets: [...profile.base_bets, { kind: "place", number: 6, amount: 6, working_on_comeout: false }], + base_bets: [...profile.base_bets, { kind: "place", number: 6, amount: 6, working_on_comeout: false }] }; onChange(copy); } @@ -50,7 +49,7 @@ export default function ProfileForm({ onChange({ ...rule, id: e.target.value })} + value={value.id} + onChange={(e) => onChange({ ...value, id: e.target.value })} /> @@ -56,18 +51,8 @@ export default function RuleForm({ value: rule, onChange }: { value: Rule; onCha Arg: delta/factor { - const raw = e.target.value; - const num = Number(raw); - if (raw.trim() === "") { - setArg("delta", undefined); - } else if (Number.isFinite(num)) { - setArg("delta", num); - } else { - setArg("delta", raw); - } - }} + value={String((value.then.args ?? {}).delta ?? (value.then.args ?? {}).factor ?? "")} + onChange={(e) => setArg("delta", Number(e.target.value) || e.target.value)} /> @@ -77,16 +62,16 @@ export default function RuleForm({ value: rule, onChange }: { value: Rule; onCha onChange({ ...rule, cooldown: n(e.target.value) })} + value={value.cooldown ?? ""} + onChange={(e) => onChange({ ...value, cooldown: n(e.target.value) })} /> @@ -111,8 +96,5 @@ function n(v: string) { return Number.isFinite(x) ? x : undefined; } function csv(v: string) { - return v - .split(",") - .map((s) => s.trim()) - .filter(Boolean); + return v.split(",").map((s) => s.trim()).filter(Boolean); } diff --git a/src/components/builder/TableForm.tsx b/src/components/builder/TableForm.tsx index d6ef232..8c0c9eb 100644 --- a/src/components/builder/TableForm.tsx +++ b/src/components/builder/TableForm.tsx @@ -26,9 +26,7 @@ export default function TableForm({ value, onChange }: { value: TableSettings; o