← back to Commercialrealestate
docs/POPUP-COLLISION-FIX-for-crcp-ui.md
39 lines
# CRCP property-popup COLLISION — fix spec for @crcp-ui (TK-10703)
**From:** claude-crcp-popup · **Date:** 2026-08-20 · **Steve's call:** DTD panel 6/6 = **verdict A** + contrarian rider.
## Problem (audited + confirmed LIVE on crcp.agentabrams.com)
A single row click **double-fires two property popups**:
1. **`public/row-notes.js`** (yours) — a `document`-level click handler → inline row-expand + **localStorage** notes ("stored on this device, never shared").
2. **`public/index.html` `#pdOverlay` block** (mine, ~lines 2495–2667, marked `Property detail + notes popup (Steve 2026-08-20)`) → **server** notes (`/api/agent-notes`) + LA County assessor/sold/permit history.
Proven: one click → **both fire** (`bothFired: true`). Both are live in prod. This is the duplicate popup Steve reported.
## The decision
Keep **ONE** popup = **your inline row-expand UX**, but **server-sync the notes** (so Frank's notes follow him across devices instead of being trapped in one browser). You own `index.html`/`row-notes.js` under TK-10703, so **you make both edits in one pass**; I'm **standing down on `index.html`** to stop the thrash.
## The 2 edits
### 1) `public/row-notes.js` — localStorage → server per-user store
- Use the key **`'prop:'+id`** (matches my badge/notesSet scheme so the two systems interoperate).
- **LOAD:** replace `localStorage.getItem(NOTE_KEY(id))` with a `GET /api/agent-notes` → `notes['prop:'+id].note` (fetch the map once, cache it).
- **SAVE** (keep your debounced on-keystroke autosave): replace `localStorage.setItem(...)` with
```js
fetch('/api/agent-notes/'+encodeURIComponent('prop:'+id),
{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({note:ta.value})})
```
- **Relabel** (~line 58): `stored on this device, never shared` → `private to you — syncs across your devices`.
**Endpoint contract (live, session-gated, verified):** `GET /api/agent-notes` → `{notes:{key:{note,updated_at}}}`; `POST /api/agent-notes/:key {note}`. Keys are arbitrary strings. Auth = the session cookie from login `frank`/`arcstone1998` (the new gate I deployed — Basic-auth is gone).
### 2) `public/index.html` — delete my duplicate block (kills the double-fire)
Remove the entire `<!-- Property detail + notes popup (Steve 2026-08-20) -->` `<style>`+`<script>` block (~lines 2495–2667): `#pdOverlay`, `openProperty`, `ensureOverlay`, the `#grid` delegated click handler, and the `.pdt-badge` MutationObserver stamping. That leaves `row-notes.js` as the sole click handler.
### Optional (nice-to-have — my overlay had these; fold into `row-notes.js` if you want)
- **All-fields detail grid** + **LA County history** inline. Fetch `GET /api/property-history?address=<addr>&city=<city>` → `{assessor, sales[], permits[]}`. The `detailRows()` + `histHtml()` renderers are in my (removed) block if you want to lift them.
## Notes
- Deploy is **Steve-gated**.
- The 741 broker-name fixes (`scripts/normalize-broker-names.js`, already applied to `ranked.json` + `.bak`) are unrelated to this and already live.
- Ping `claude-crcp-popup` if you want the history/detail snippet or anything clarified.