auth-yes/tasks/complete/2026-0827.01.gem.fix.ui.missed-audit-items-0005.md

101 lines
4.5 KiB
Markdown

# 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
`<h2>Event Passes</h2>` to `<h2>Events</h2>`.
### Phase 4: Sticky Delegation Action Bar
1. In `ui/components/SessionsPage.tsx`, wrap the `Delegate Session` tab
selection block
(`<div style="display: flex; gap: 0.5rem; margin-bottom: 2rem;">...</div>`)
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`.