4.5 KiB
4.5 KiB
TASK METADATA
- Target Files:
server/routes/events.tsui/components/sessions/SessionsScript.tsxui/components/sessions/EventCockpitDeck.tsxui/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 & EventsUX before moving on to backend relational decoupling and P2P vouching.
2. Architectural Considerations & Risks
Risks
- DOM Ingress Desync: Currently, when an organizer clicks
[ 🔄 Rotate ], the backend successfully updates both thepin_codeand theslug. 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 theironclickhandlers 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. - Guest Drawer Broken Meta Header: The backend endpoint
GET /api/events/:id/attendeesonly returns{ success: true, attendees: [...] }. The client script expectsdata.eventto populate theMax SeatsandExpires Atcountdown. Becausedata.eventis undefined, the header is permanently stuck displaying0 / 0 Claimed Seats · ⏳ 0h 0m left. Risk: Loss of critical event context while managing guests. - Scroll Fatigue: The
[ Delegate Session ]drawer trigger sits at the top ofSessionsPage.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 inSessionsPage.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
idattributes to the Link and CLI copy pills inEventCockpitDeck.tsxsorotatePincan dynamically overwrite theironclickattributes.
3. Proposed Implementation
Phase 1: Fix Backend Attendees Payload
- In
server/routes/events.ts, locateGET /api/events/:id/attendees(around line 125). - Currently, the query selects only
slugto do theLIKEmatch. Update this to fetchmax_seatsandexpires_atas well. - 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
- 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}andid={'cli-copy-' + event.id}.
- In
ui/components/sessions/SessionsScript.tsx(rotatePinfunction):- Check if
data.slugis returned (Jules updated the backend to returnpinCode, slug, link, cli). - If
data.slugis present, locate the link and CLI copy elements and overwrite theironclickhandlers dynamically so they copy the fresh credentials. - E.g.,
linkElem.setAttribute('onclick', "copyText(window.location.origin + '/e/" + data.slug + "')");
- Check if
Phase 3: Section Title Typo
- In
ui/components/sessions/EventCockpitDeck.tsx(around line 8), change<h2>Event Passes</h2>to<h2>Events</h2>.
Phase 4: Sticky Delegation Action Bar
- In
ui/components/SessionsPage.tsx, wrap theDelegate Sessiontab selection block (<div style="display: flex; gap: 0.5rem; margin-bottom: 2rem;">...</div>) in a sticky container. - Example styling:
position: sticky; top: 1rem; z-index: 50; background: var(--surface-bg); padding-top: 1rem; margin-top: -1rem; margin-bottom: 2rem;. - 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
- Run
deno fmt,deno task lint, anddeno task check. - Verify all
ui/ui_scripts.test.tspass and the DOM manipulation syntax is correct. - Author a new test block in
server/tests/events.test.tsforGET /api/events/:id/attendeesto assert that it successfully returns both theattendeesarray and theeventpayload containingmax_seatsandexpires_at.