From a57437a4b7553bd84846fa2b0023f64f64d5b486 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Fri, 8 May 2026 16:04:00 +0200 Subject: [PATCH] audit(timetable): complete prototype audit for RFC v0.2 Capture inventory, data model, component architecture, interaction patterns, pure logic algorithms (with verbatim excerpts), design tokens, and 20 RFC v0.2 observations from the standalone React prototype at resources/Crewli - Artist Timetable Management/. Read-only audit; no prototype files modified. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../PROTOTYPE-AUDIT-ARTIST-TIMETABLE.md | 1293 +++++++++++++++++ 1 file changed, 1293 insertions(+) create mode 100644 dev-docs/audits/PROTOTYPE-AUDIT-ARTIST-TIMETABLE.md diff --git a/dev-docs/audits/PROTOTYPE-AUDIT-ARTIST-TIMETABLE.md b/dev-docs/audits/PROTOTYPE-AUDIT-ARTIST-TIMETABLE.md new file mode 100644 index 00000000..6009cf53 --- /dev/null +++ b/dev-docs/audits/PROTOTYPE-AUDIT-ARTIST-TIMETABLE.md @@ -0,0 +1,1293 @@ +--- +title: Artist Timetable Prototype Audit +status: complete +audited-at: 2026-05-08 +audited-by: Claude Code +prototype-source: ./resources/Crewli - Artist Timetable Management/ +follows-up: dev-docs/RFC-TIMETABLE-Artist-Timetable-Module.md (v0.1) +feeds-into: dev-docs/RFC-TIMETABLE-Artist-Timetable-Module.md (v0.2 — to be written) +--- + +# Artist Timetable Prototype Audit + +> Read-only audit of the standalone React+Babel prototype shipped in +> `./resources/Crewli - Artist Timetable Management/`. The prototype is a +> single-page demo (no build, no backend, in-memory state) that explores the +> UX/UI for the Artist Timetable module. This document captures **what is** +> in the prototype so RFC-TIMETABLE v0.2 can adopt, adapt, or reject each +> piece deliberately. + +--- + +## §1 File inventory + +The prototype is loaded by a single HTML page that pulls React 18, ReactDOM, +and Babel-standalone from unpkg, then loads five JSX/JS scripts in order. + +| Group | File | LOC | One-line description | +|---|---|---|---| +| App entry | `Crewli Timetable.html` | 28 | HTML shell — loads React 18 / Babel-standalone via unpkg, then `data.js`, `helpers.js`, and the four JSX files. | +| Data / fixtures | `data.js` | 159 | `window.CrewliData` IIFE — `EVENT`, `STAGES`, `STAGE_DAYS`, `ADVANCE_SECTIONS`, `ARTISTS`, `GENRES`, `PERFORMANCES`, `PARKED`, `PENDING`, `TIME` constants. | +| Pure logic / lib | `helpers.js` | 144 | `window.CrewliHelpers` — `STATUS` palette, `fmtTime`, `snap`, `findConflicts`, `findB2B`, `isCapacityWarn`, `assignLanes`, `advanceCount`. | +| Components | `timetable.jsx` | 1133 | `Block`, `TimeAxis`, `GridBg`, `StatusMultiSelect`, `ParkingColumn`, `Timetable`. Owns lane assignment, cascade-bump, drag/resize/create logic. | +| Components | `popover.jsx` | 264 | `Popover` (timetable block), `QueuePopover` (parking item), `StatusDropdown`, `PopoverBody`. Off-screen-safe `pickPos`. | +| Components | `modals.jsx` | 379 | `PerformanceModal` (add/edit), `StageEditor` (create/edit/delete stage), `LineupMatrix` (stages×days bulk toggle), `Backdrop`, `Field`. | +| Components | `app.jsx` | 517 | `App` root — owns all state via `React.useState`, dispatches reducer-style actions, renders `Sidebar`, `Header`, `Timetable`, popovers, modals, `FooterToolbar`, `TweaksPanel`. | +| Components (dev) | `tweaks-panel.jsx` | 759 | Generic vendor-style live-tweak panel: zoom slider, density radio, advancing-% toggle. **Not part of the module surface** — design-time only. | +| Styles | `styles.css` | ~1000 | Light-mode shell, navy sidebar, teal accent. CSS custom properties on `:root`. Status colours live in `helpers.js`, not CSS. | +| Docs | `docs/RFC-TIMETABLE - Artist Timetable Module.md` | 529 | A copy of v0.1 RFC checked into the prototype folder. Identical to (intended) `dev-docs/RFC-TIMETABLE-...` v0.1. | +| Docs | `docs/timetable-module.md` | 470 | Companion narrative doc — overlap with RFC, less authoritative. | +| Other | `.DS_Store`, `uploads/pasted-...png` | — | Mac filesystem cruft + a screenshot embedded for design context. Ignore. | + +The prototype has **no node_modules, no package.json, no bundler config, no +tests**. State is in-memory and resets on reload. + +--- + +## §2 Data model + +The prototype's authoritative data shapes live in `data.js`. Field names +match Crewli `SCHEMA.md` §3.5.7 conventions where possible (snake_case, +ULID-shaped string IDs prefixed by entity letter — `s_`, `a_`, `p_`, `pk_`, +`pa_`, `d_`). + +### §2.1 `EVENT` + +| Field | Type | Sample | Nullable | Notes | +|---|---|---|---|---| +| `id` | string | `"ezf_2026"` | no | Free-form string in prototype; production uses ULID. | +| `name` | string | `"Echt Zomer Feesten"` | no | | +| `edition` | string | `"2026"` | no | Prototype-only convenience; not in SCHEMA. | +| `sub_event_label` | string | `"dag"` | no | i18n knob — header reads "Stages per {sub_event_label}". | +| `days` | array | — | no | Inline pivot (no `event_id` FK in fixture; single-event PoC). | + +### §2.2 `Day` (inline in `EVENT.days`) + +| Field | Type | Sample | Nullable | Notes | +|---|---|---|---|---| +| `id` | string | `"d_fr"` | no | | +| `date` | ISO date | `"2026-07-10"` | no | | +| `label` | string | `"Vrijdag"` | no | Long form. | +| `short` | string | `"Vr"` | no | Two-char form (unused in current UI; carried for future tabs). | + +### §2.3 `STAGES` + +| Field | Type | Sample | Nullable | Notes | +|---|---|---|---|---| +| `id` | string | `"s_hardstyle"` | no | | +| `name` | string | `"Hardstyle District"` | no | | +| `color` | string (hex) | `"#e85d75"` | no | Drives left-edge swatch on stage row + popover header tint. | +| `capacity` | int | `4500` | no | Drives `isCapacityWarn(artist, stage) = artist.draw > stage.capacity * 1.1`. | +| `__draft` | bool | `true` | yes | Transient flag set by `handleAddStage` so `StageEditor` knows it is committing a brand-new row vs editing an existing one. Stripped in `app.jsx:323` before dispatch. | + +### §2.4 `STAGE_DAYS` (pivot) + +| Field | Type | Sample | Notes | +|---|---|---|---| +| `stage_id` | string FK | `"s_hardstyle"` | | +| `day_id` | string FK | `"d_fr"` | Prototype joins to `EVENT.days[].id`, not `date`. | + +No PK column — pure pivot. Production schema (SCHEMA §3.5.7) uses +`(stage_id, day_date)` with an int AI PK and unique constraint. + +### §2.5 `ADVANCE_SECTIONS` + +| Field | Type | Sample | Notes | +|---|---|---|---| +| `key` | string | `"tour"` | Map key, not ULID. | +| `label` | string | `"Tourmanager"` | Displayed in popover checklist. | + +Closed list of 5 in prototype: `tour, hosp, travel, flight, rider`. In +production these are `advance_sections` rows per artist (not a global list). + +### §2.6 `GENRES` + +```js +["Hardstyle", "Techno", "House", "Hollands", "Pop", "Urban", "Disco", "Aprés"] +``` + +A flat string array, used to (a) populate the genre `