# 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 `

Event Passes

` to `

Events

`. ### Phase 4: Sticky Delegation Action Bar 1. In `ui/components/SessionsPage.tsx`, wrap the `Delegate Session` tab selection block (`
...
`) in a sticky container. 2. Example styling: `position: sticky; top: 1rem; z-index: 50; background: var(--surface-bg); padding-top: 1rem; margin-top: -1rem; margin-bottom: 2rem;`. 3. Add a slight box-shadow or bottom border on scroll (optional polish) to ensure the tabs float cleanly above scrolling session cards. ### Phase 5: Quality Gates 1. Run `deno fmt`, `deno task lint`, and `deno task check`. 2. Verify all `ui/ui_scripts.test.ts` pass and the DOM manipulation syntax is correct. 3. Author a new test block in `server/tests/events.test.ts` for `GET /api/events/:id/attendees` to assert that it successfully returns both the `attendees` array and the `event` payload containing `max_seats` and `expires_at`.