From 3f93daf28e4a7dd43fc5a34422b3e8cf36be5bda Mon Sep 17 00:00:00 2001 From: Keysat Date: Fri, 19 Jun 2026 17:07:29 -0500 Subject: [PATCH] Mobile P3b: investor name + contact-pill editing (update-row) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the editable half of BRIEF §3a's mobile grid set: rename an investor and add/edit/remove its contact pills from the mobile detail sheet. New POST /api/fundraising/update-row is the one-row read-fresh-modify-write twin of log-communication: it mutates only the target row's name/contacts in the canonical grid blob server-side, then bumps the version + re-syncs the relational tables. It never accepts a whole-grid payload, so a stale mobile client can't clobber concurrent edits to other rows (the reason mobile avoids the whole-grid PUT). _sanitize_fundraising_contacts whitelists the known pill fields as the trust boundary; removing a pill is soft on the classic contacts directory (only the grid pill + fundraising_contacts row drop). Frontend: MobileFundraisingGrid gains an Edit bottom-sheet (name input + pill editor with client-side dedup); money stays desktop-only. New CSS is theme-var-only so it flips in light mode. Verified: test_fundraising_update_row.py (24 assertions, real HTTP), full suite 37/37, render-smoke + a 375px jsdom interaction harness green. --- AGENTS.md | 29 +--- backend/server.py | 118 +++++++++++++ backend/test_fundraising_update_row.py | 227 +++++++++++++++++++++++++ frontend/index.html | 89 +++++++++- 4 files changed, 436 insertions(+), 27 deletions(-) create mode 100644 backend/test_fundraising_update_row.py diff --git a/AGENTS.md b/AGENTS.md index fb44755..b0d7bcc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -107,27 +107,12 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude ## Current state -_**Box live at v0.1.0:94**; `main` (pushed through `e6a8945`) ahead by mobile Phases 0–6 + drag-reorder views — **all deploy-pending** (no s9pk built yet). **The fundraising grid + email capture is the canonical system of record.** Active thread: **mobile-first redesign** — **all 4 surfaces + the light theme done (P0–P6)**. **Plan (Grant, 2026-06-19): finish features first — P3b name/pill edit → Phase 7 design-conformance pass, in that order next session — then Grant does device testing + deploy** (NOT before; everything is unverified on a real phone). Per-phase detail + backlog: `ROADMAP.md` / `EVALUATION.md`; history: git log + `start9/0.4/startos/versions/`._ +_**Box live at v0.1.0:94**; `main` ahead by mobile Phases 0–6 + P3b name/pill edit + drag-reorder views — **all deploy-pending** (no s9pk built yet). **The fundraising grid + email capture is the canonical system of record.** Active thread: **mobile-first redesign** — **all 4 surfaces + light theme + P3b (name/pill edit) done; BRIEF §3a editable set complete**. **Plan (Grant, 2026-06-19): finish features first — P3b done → Phase 7 design-conformance pass next — then Grant does device testing + deploy** (NOT before; everything is unverified on a real phone). Per-phase detail + backlog: `ROADMAP.md` / `EVALUATION.md`; history: git log + `start9/0.4/startos/versions/`._ -- **Mobile redesign — all 4 core surfaces built + committed (Grid · Contacts · Pipeline · Reminders).** Each is a rules-of-hooks-safe `useIsMobile()` wrapper → `Mobile*`/`Desktop*` pair (**desktop untouched**), re-authored against the real API on shared primitives ``/`useIsMobile()`/`StageChip`/`MobileDetailRow`. Foundation: bottom-tab bar + `:root` mobile vars (P1); 4-stage enum + read-only derived grid signals (`existing_investor`/`last_activity_at`/`staleness`/`opportunity_id`) injected on GET, **stripped on write at both points** (P0/P3a `_computed_row_values` + `stripComputedRows`). **Mobile writes use one-row endpoints only — never whole-grid PUT** (BRIEF §3a). Per-phase detail in `ROADMAP.md`. -- **This session — P6 light theme (committed `e6a8945`, frontend-only).** App-wide light theme behind - `:root[data-theme="light"]`; **dark stays default** (pre-paint boot script in `` reads - `localStorage.venture_crm_theme`; no `prefers-color-scheme`). **App-wide toggle:** labeled control - in the desktop sidebar footer + sun/moon icon in the mobile top bar, both off one `theme` state in - `App`. Color pairs taken from the **full Claude Design export** (`design/_imports/2026-06-19_zip-file/`, - with the previously-missing `store.js` + `*App.dc.html` `DCLogic` palettes) — exact dark+light for - every stage/recency/note/priority/reminder/money tint. **Method = zero dark regression by - construction:** grew `:root` to 44 themed slots whose **dark values == the originals byte-for-byte** - (verified), then migrated **319 hex→`var()`** (script for structural; targeted edits for semantic/ - chip helpers — `StageChip` now className-based, `PIPELINE_STAGE_CHIP` removed). Mobile surfaces + - chrome are fully var-based → **mobile light complete**. **Desktop light rough edges** (bespoke - `