7.3 KiB
7.3 KiB
TASK METADATA
- Target Files:
ui/components/SessionsPage.tsxui/components/sessions/DirectPassDrawer.tsxui/components/sessions/WorkshopDrawer.tsxui/components/sessions/SessionsScript.tsxui/ui_scripts.test.ts
- Core Objective: Resolve Round 4 UI defects by docking the sticky
sub-header beneath the main app top bar, standardizing single session creation
to full parity with workshop passes, eliminating
<summary>double arrows while preserving(Optional)labels, and implementing a rapid creation flow ([ Create Another ]+[ OK ]) with tab-locking during handoff states. - Dependencies: None.
- Additional Important Notes: Must remain 100% pure React-free Hono SSR JSX.
All state transitions in
SessionsScript.tsxmust use native vanilla JavaScript DOM APIs.
2. Architectural Considerations & Risks
Risks
- Navbar Collision on Mobile Viewports: On narrow screens, the top app bar
height might vary depending on wrapped elements.
- Mitigation: Use
top: var(--top-bar-height, 57px); z-index: 30;with a solid background (var(--surface-bg)) to prevent cards from scrolling through transparent gaps or overlapping the fixed.top-bar(which sits atz-index: 40).
- Mitigation: Use
- State Leakage Across Tabs: If a user mints a Workshop Pass, the handoff
screen appears. If they click the "Single Pass" tab while the event handoff
is still visible, the form displays a dirty or stale state.
- Mitigation: Lock the tab switcher (
pointer-events: none; opacity: 0.5;or visually disable the buttons) while in eitherhandoffModaloreventHandoffState. Tab navigation is automatically re-enabled when the user clicks[ Create Another ]or closes the drawer.
- Mitigation: Lock the tab switcher (
- Double Arrow Rendering: Native
<details><summary>elements automatically render disclosure triangles in modern browsers.- Mitigation: Purge all explicit
▸characters from<summary>text strings across both drawer templates.
- Mitigation: Purge all explicit
Alternatives
- Closing the Drawer Immediately on Creation: We considered closing the drawer right after minting and letting the user copy links from the main page deck. However, showing the 1-click link, PIN, and CLI export immediately upon creation in a dedicated handoff card provides essential visual confirmation and zero-friction copying before returning to the dashboard.
3. Proposed Implementation
Phase 1: Viewport Docking (ui/components/SessionsPage.tsx)
- Locate the
Sessions & Eventssub-header block inSessionsPage.tsx. - Update the sticky styling from
top: 0; z-index: 40;to:position: sticky; top: var(--top-bar-height, 57px); z-index: 30; background: var(--surface-bg, #0f172a); padding: 0.75rem 0; margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-subtle);
Phase 2: Single Pass Drawer Parity & Form Hiding (ui/components/sessions/DirectPassDrawer.tsx)
- Wrap the Single Pass creation form in
<div id="delegateCreateState" style="display: block;">. - Update the submit button:
- Label:
[ Create Session ](replace"Mint & Delegate Session"). - Standardize styling to match
btn-primary.
- Label:
- In the Accordion
<summary>:- Remove the
▸character. - Label as:
"Customize App Permissions & Scopes (Optional)".
- Remove the
- In
#handoffModal:- Change the 1-Click Link copy button from
btn-primaryto uniformbtn-outline. - Update footer actions:
- Replace the single
"Done (Session is Active)"button with a dual-action flex container:[ Create Another ](type="button" class="btn-outline" onclick="createAnotherSession()")[ OK ](type="button" class="btn-primary" onclick="closeDelegateDrawer()")
- Replace the single
- Change the 1-Click Link copy button from
Phase 3: Workshop Drawer Parity & Accordion Cleanliness (ui/components/sessions/WorkshopDrawer.tsx)
- Update the submit button:
- Label:
[ Create Event ](replace"🎟️ Launch Workshop Pass").
- Label:
- In the Custom Vanity Slug & PIN
<summary>:- Remove the
▸character. - Label as:
"Custom Vanity Slug & PIN Code (Optional)".
- Remove the
- In
#eventHandoffState:- Update footer actions to match Single Pass:
[ Create Another ](type="button" class="btn-outline" onclick="createAnotherEvent()")[ OK ](type="button" class="btn-primary" onclick="closeDelegateDrawer()")
- Update footer actions to match Single Pass:
Phase 4: Client State Machine & Tab Locking (ui/components/sessions/SessionsScript.tsx)
- Single Session Submit Handler (
handleDelegateSession):- On success, set
#delegateCreateState.style.display = 'none'and#handoffModal.style.display = 'block'. - Call
lockDelegationTabs(true)to prevent switching tabs while viewing the handoff token.
- On success, set
- Event Creation Submit Handler (
handleCreateEvent):- On success, set
#eventCreateState.style.display = 'none'and#eventHandoffState.style.display = 'block'. - Call
lockDelegationTabs(true).
- On success, set
- Tab Locking Helpers:
lockDelegationTabs(locked): Togglesdisabledstate andopacity: 0.5; pointer-events: none;on#tabBtnDirectPassand#tabBtnWorkshopPass.
- "Create Another" Handlers:
createAnotherSession():- Reset
#delegateForminput values (default back to 1 Hour and Read-Only). #handoffModal.style.display = 'none'.#delegateCreateState.style.display = 'block'.lockDelegationTabs(false).- Focus
#delegateLabel.
- Reset
createAnotherEvent():- Reset
#eventForminput values (default back to 50 seats and 3 hours). #eventHandoffState.style.display = 'none'.#eventCreateState.style.display = 'block'.lockDelegationTabs(false).- Focus
#eventName.
- Reset
- Drawer Open/Close Reset:
- When calling
openDelegateDrawer(), ensurelockDelegationTabs(false)is invoked and both form states are reset to visible State 1.
- When calling
Phase 5: Expired Events Accordion & 1-Click Reopen (ui/components/sessions/EventCockpitDeck.tsx)
- Active vs. Expired Separation:
- Filter
eventPassesintoactiveEventsandexpiredEvents(expires_at <= NOW()oris_active = FALSE).
- Filter
- Collapsible Accordion:
- Below the active deck, render a native
<details>block:<details style="margin-top: 1.5rem; background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: 0.75rem 1rem;"> <summary style="font-weight: 600; font-size: 0.95rem; cursor: pointer; color: var(--text-secondary);"> 📁 Expired Events ({expiredEvents.length}) </summary> ... </details>
- Below the active deck, render a native
- 1-Click Reopen Action:
- For naturally expired events (
is_active = TRUE), render a dedicated[ 🔄 Reopen (+1h) ]button callingPOST /api/events/:id/extendwithextendHours: 1.
- For naturally expired events (
Phase 6: Quality Gates & Network/Error Mock Testing
- Run
deno test -A --no-check server/tests/events.test.tsto assert all extend, attendees, and 404/403 failure paths pass. - Run
deno test -A --no-check ui/ui_scripts.test.tsto verify zero JavaScript syntax or parsing errors. - Run
deno fmt,deno task lint,deno task check, anddeno test -A --no-check.