# TASK METADATA - **Target Files:** - `server/routes/events.ts` - `ui/components/sessions/SessionsScript.tsx` - `ui/components/sessions/EventCockpitDeck.tsx` - `ui/components/SessionsPage.tsx` - **Core Objective:** Resolve the final 4 untracked discrepancies identified during the Phase 6 UI Audit (DOM desync, missing guest drawer payload, minor typo, and missing sticky action bar). - **Dependencies:** None. - **Additional Important Notes:** This represents the final polish of the `Sessions & Events` UX before moving on to backend relational decoupling and P2P vouching. --- ## 2. Architectural Considerations & Risks ### Risks 1. **DOM Ingress Desync:** Currently, when an organizer clicks `[ 🔄 Rotate ]`, the backend successfully updates both the `pin_code` and the `slug`. However, the frontend JavaScript (`rotatePin`) only targets and updates the PIN on the UI. The copy buttons for "Link" and "CLI" continue to hold the old slug because their `onclick` handlers are hardcoded during SSR. _Risk_: If an organizer rotates the credentials and then clicks "Copy Link", they will mistakenly share the revoked link, leading to confusion and 404s. 2. **Guest Drawer Broken Meta Header:** The backend endpoint `GET /api/events/:id/attendees` only returns `{ success: true, attendees: [...] }`. The client script expects `data.event` to populate the `Max Seats` and `Expires At` countdown. Because `data.event` is undefined, the header is permanently stuck displaying `0 / 0 Claimed Seats · ⏳ 0h 0m left`. _Risk_: Loss of critical event context while managing guests. 3. **Scroll Fatigue:** The `[ Delegate Session ]` drawer trigger sits at the top of `SessionsPage.tsx`. As the user accumulates multiple events or sessions, scrolling down the page hides the primary action. ### Alternatives - For the Sticky Action Bar, we could use CSS `position: sticky; top: 0;` on the delegation tabs block in `SessionsPage.tsx`, ensuring the action is always visible without creating a separate floating action button (FAB) which might clutter mobile views. - For the UI DOM rotation, we must assign `id` attributes to the Link and CLI copy pills in `EventCockpitDeck.tsx` so `rotatePin` can dynamically overwrite their `onclick` attributes. ## 3. Proposed Implementation ### Phase 1: Fix Backend Attendees Payload 1. In `server/routes/events.ts`, locate `GET /api/events/:id/attendees` (around line 125). 2. Currently, the query selects only `slug` to do the `LIKE` match. Update this to fetch `max_seats` and `expires_at` as well. 3. Include the event payload in the JSON response: `return c.json({ success: true, attendees, event: { max_seats: event.max_seats, expires_at: event.expires_at } })`. ### Phase 2: Fix DOM Rotation Desync 1. In `ui/components/sessions/EventCockpitDeck.tsx`: - Locate the Grid and Compact card copy buttons for Link and CLI. - Add explicit IDs, for example: `id={'link-copy-' + event.id}` and `id={'cli-copy-' + event.id}`. 2. In `ui/components/sessions/SessionsScript.tsx` (`rotatePin` function): - Check if `data.slug` is returned (Jules updated the backend to return `pinCode, slug, link, cli`). - If `data.slug` is present, locate the link and CLI copy elements and overwrite their `onclick` handlers dynamically so they copy the fresh credentials. - E.g., `linkElem.setAttribute('onclick', "copyText(window.location.origin + '/e/" + data.slug + "')");` ### Phase 3: Section Title Typo 1. In `ui/components/sessions/EventCockpitDeck.tsx` (around line 8), change `