- Update `DELETE /api/sessions/:id` in `server/routes/sessions.ts` to allow event creators to delete guests' sessions. - Update page hierarchy and top headings in `ui/components/SessionsPage.tsx`. - Refactor `EventAttendeesDrawer.tsx` to `EventGuestsDrawer.tsx` as a fixed slide-over overlay. - Add multi-event compact view toggle with `localStorage` persistence in `EventCockpitDeck.tsx`. - Standardize dynamic countdown pills across `EventCockpitDeck.tsx`, `EventGuestsDrawer.tsx`, `SessionDeck.tsx`, and `SessionTable.tsx`. - Optimize mobile session deck in `SessionDeck.tsx`. Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
7.6 KiB
7.6 KiB
TASK METADATA
- Target Files:
server/routes/sessions.ts,server/routes/events.ts,ui/components/SessionsPage.tsx,ui/components/sessions/EventCockpitDeck.tsx,ui/components/sessions/EventAttendeesDrawer.tsx(refactored/renamed toEventGuestsDrawer.tsx),ui/components/sessions/SessionDeck.tsx,ui/components/sessions/SessionTable.tsx,ui/components/sessions/SessionsScript.tsx,server/tests/events.test.ts,server/tests/scopes.test.ts,ui/ui_scripts.test.ts - Core Objective: Implement Phase 5 Overhaul: Fix backend attendee session revocation permission checks, build a true fixed slide-over Guest Drawer, standardize dynamic countdown pills, add multi-event compact density toggle, and clean up page/session visual hierarchy.
- Dependencies: None.
- Additional Important Notes: Must remain 100% pure React-free Hono SSR JSX.
All client interactions in
SessionsScript.tsxmust use native vanilla JavaScript DOM APIs.
2. Architectural Considerations & Risks
-
Risks:
- Zero-Trust Revocation Leakage: When allowing event creators to
delete/revoke attendee sessions via
DELETE /api/sessions/:id, ensure the query strictly verifies that the session belongs to a guest user claimed under an event pass created byauth.userId(or that caller is global admin). Never allow arbitrary session deletions across different event creators. - DOM Stacking & Focus Trapping: A fixed slide-over drawer must properly
layer (
z-index: 1050) over the background page and support backdrop dismissal andEscapekey capture without disrupting background table states. - Mobile Density Regressions: Ensure the mobile slide-up bottom sheet does not block necessary viewport scrolling or clip action buttons on small mobile viewports (320px–375px).
- Zero-Trust Revocation Leakage: When allowing event creators to
delete/revoke attendee sessions via
-
Alternatives:
- In-Page Expandable Row vs. Fixed Slide-Over Panel: In-page expandable cards cause massive vertical jumping and layout disruption when 5–10 events are active. A dedicated fixed slide-over drawer (right panel on desktop, bottom sheet on mobile) provides isolated context, independent scrolling, and a pinned summary header without disturbing the background dashboard.
3. Proposed Implementation
Phase 1: Backend Revocation Permission Fix (server/routes/sessions.ts)
- Authorize Event Creators in
DELETE /api/sessions/:id:- Update
DELETE /api/sessions/:idto check whether the target session is owned byauth.userId, or if caller isisGlobalAdmin, OR if the session belongs to a guest user of an event pass created byauth.userId:SELECT s.id FROM sessions s JOIN users u ON s.user_id = u.id WHERE s.id = ${targetSessionId} AND ( s.user_id = ${auth.userId} OR ${isAdmin} OR EXISTS ( SELECT 1 FROM event_passes ep WHERE ep.created_by = ${auth.userId} AND u.username LIKE 'guest_' || ep.slug || '_%' ) ) - If found, delete the session from Valkey cache (
valkey.del) and PostgreSQL (DELETE FROM sessions WHERE id = ${targetSessionId}), logging the audit event. - Return
{ success: true }.
- Update
Phase 2: Page Hierarchy & Section Titles (ui/components/SessionsPage.tsx)
- Page Title:
- Update top
<h1>inSessionsPage.tsxfromActive Sessions & PassestoSessions & Passes.
- Update top
- Missing Section Headings:
- Section 1:
<h2>Event Passes</h2>(with compact density toggle). - Section 2: Add a prominent
<h2>Sessions</h2>heading directly aboveSessionTableandSessionDeckwith subtitle "Direct device logins, passkey authentications, and delegated agent tokens."
- Section 1:
Phase 3: True Fixed Slide-Over Panel (EventGuestsDrawer.tsx & SessionsScript.tsx)
- Drawer Component Overhaul
(
ui/components/sessions/EventAttendeesDrawer.tsx->EventGuestsDrawer.tsx):- Refactor the component from an in-line
<div class="card">into a fixed slide-over overlay:- Desktop:
position: fixed; top: 0; right: 0; width: 420px; height: 100vh; background: var(--surface-card); box-shadow: var(--shadow-lg); z-index: 1050; display: flex; flex-direction: column; - Mobile: Full-width slide-up bottom sheet
(
width: 100vw; height: 80vh; bottom: 0; right: 0; border-radius: 16px 16px 0 0;). - Backdrop: Dimmed backdrop overlay
(
position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1040;) closing on click.
- Desktop:
- Refactor the component from an in-line
- Pinned Contextual Header:
- Title:
<h2 id="guestDrawerTitle" style="margin: 0; font-size: 1.25rem;">[Event Name] Guests</h2> - Subheader Context Bar:
<div id="guestDrawerContext" style="font-size: 0.8rem; color: var(--text-secondary); margin-top: 0.25rem;">Event Pass · [N] / [Max] Claimed Seats · ⏳ [Xh Ym left] · (Expires [Time])</div> - Close Button: Accessible close button in top right.
- Title:
- Streamlined Roster Rows (
SessionsScript.tsx):- Discard repeated static expiration timestamps from individual rows.
- Render clean, distinct cards for each guest seat:
- Left:
Seat #[N](guest_<slug>_<N>) + relative join timestamp (Joined 5m ago). - Status Badge:
🟢 Active/⏸️ Paused. - Right Actions: Compact
[ ⏸️ Pause ]/[ ▶️ Resume ]toggle and[ 🗑️ Revoke ]trigger.
- Left:
- Standardize Terminology:
- Use
Event GuestsandClaimed Seatsacross all drawer titles, buttons ([ 👥 Manage Guests (N) ]), and notices.
- Use
Phase 4: Dynamic Countdown Standardization & Density Polish (EventCockpitDeck.tsx, SessionDeck.tsx, SessionTable.tsx)
- Standardized Countdown Pill:
- Create a reusable countdown formatter rendering:
⏳ 2h 45m left · (Expires 10:39 PM)(or⏳ 29d left · (Expires Sep 25)). - Dynamic status coloring: Green (healthy) -> Amber (<1h remaining) -> Red (expired).
- Apply consistently across Event Pass Cards and the Sessions Table/Deck.
- Create a reusable countdown formatter rendering:
- Multi-Event Compact Density Toggle (
EventCockpitDeck.tsx):- Add a
[ 🗂️ Grid ]/[ 📋 Compact ]density toggle at the top of theEvent Passessection. - In Compact Mode, collapse each event card into a sleek 1-row summary
strip
(
Title · 🟢 Active · ⏳ 2h 45m left · 12/50 Seats · PIN: 749-123 · [ 👥 Guests (12) ] · [ ▸ Details ]), fitting 10+ active events in a single screen.
- Add a
- Mobile Session Card Optimization (
SessionDeck.tsx):- Remove the dedicated full-width bottom row on remote session cards.
- Move
[ 🗑️ Revoke ]inline into the top card header row next to the status badge as a compact button (btn-outline-danger), reducing card height by 50% and fitting 4–5 more sessions per screen.
Phase 5: Quality Gates & Testing
- Unit Tests (
server/tests/events.test.ts&scopes.test.ts):- Test event host revoking a guest attendee session via
DELETE /api/sessions/:idsucceeds (200 OK). - Test non-owner unauthorized user attempting to revoke an attendee session is rejected (404/403).
- Test guest list API returns active claimed seats.
- Test event host revoking a guest attendee session via
- Hermetic UI Validation (
ui/ui_scripts.test.ts):- Verify all vanilla JavaScript drawer controllers, density toggles, and
countdown scripts in
SessionsScript.tsxparse and evaluate cleanly with zero syntax errors.
- Verify all vanilla JavaScript drawer controllers, density toggles, and
countdown scripts in
- Formatting & Linting:
- Ensure
deno fmt,deno task lint,deno task check, anddeno test --allow-allexecute with 100% green status.
- Ensure