# TASK METADATA - **Target Files:** - `ui/components/SessionsPage.tsx` - `ui/components/sessions/DirectPassDrawer.tsx` - `ui/components/sessions/WorkshopDrawer.tsx` - `ui/components/sessions/SessionsScript.tsx` - `ui/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 `` 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.tsx` must use native vanilla JavaScript DOM APIs. --- ## 2. Architectural Considerations & Risks ### Risks 1. **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 at `z-index: 40`). 2. **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 either `handoffModal` or `eventHandoffState`. Tab navigation is automatically re-enabled when the user clicks `[ Create Another ]` or closes the drawer. 3. **Double Arrow Rendering:** Native `
` elements automatically render disclosure triangles in modern browsers. - _Mitigation:_ Purge all explicit `▸` characters from `` text strings across both drawer templates. ### 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`) 1. Locate the `Sessions & Events` sub-header block in `SessionsPage.tsx`. 2. Update the sticky styling from `top: 0; z-index: 40;` to: ```css 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`) 1. Wrap the Single Pass creation form in `
`. 2. Update the submit button: - Label: **`[ Create Session ]`** (replace `"Mint & Delegate Session"`). - Standardize styling to match `btn-primary`. 3. In the Accordion ``: - Remove the `▸` character. - Label as: **`"Customize App Permissions & Scopes (Optional)"`**. 4. In `#handoffModal`: - Change the 1-Click Link copy button from `btn-primary` to uniform `btn-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()"`) ### Phase 3: Workshop Drawer Parity & Accordion Cleanliness (`ui/components/sessions/WorkshopDrawer.tsx`) 1. Update the submit button: - Label: **`[ Create Event ]`** (replace `"🎟️ Launch Workshop Pass"`). 2. In the Custom Vanity Slug & PIN ``: - Remove the `▸` character. - Label as: **`"Custom Vanity Slug & PIN Code (Optional)"`**. 3. 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()"`) ### Phase 4: Client State Machine & Tab Locking (`ui/components/sessions/SessionsScript.tsx`) 1. **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. 2. **Event Creation Submit Handler (`handleCreateEvent`):** - On success, set `#eventCreateState.style.display = 'none'` and `#eventHandoffState.style.display = 'block'`. - Call `lockDelegationTabs(true)`. 3. **Tab Locking Helpers:** - `lockDelegationTabs(locked)`: Toggles `disabled` state and `opacity: 0.5; pointer-events: none;` on `#tabBtnDirectPass` and `#tabBtnWorkshopPass`. 4. **"Create Another" Handlers:** - `createAnotherSession()`: - Reset `#delegateForm` input values (default back to 1 Hour and Read-Only). - `#handoffModal.style.display = 'none'`. - `#delegateCreateState.style.display = 'block'`. - `lockDelegationTabs(false)`. - Focus `#delegateLabel`. - `createAnotherEvent()`: - Reset `#eventForm` input values (default back to 50 seats and 3 hours). - `#eventHandoffState.style.display = 'none'`. - `#eventCreateState.style.display = 'block'`. - `lockDelegationTabs(false)`. - Focus `#eventName`. 5. **Drawer Open/Close Reset:** - When calling `openDelegateDrawer()`, ensure `lockDelegationTabs(false)` is invoked and both form states are reset to visible State 1. ### Phase 5: Expired Events Accordion & 1-Click Reopen (`ui/components/sessions/EventCockpitDeck.tsx`) 1. **Active vs. Expired Separation:** - Filter `eventPasses` into `activeEvents` and `expiredEvents` (`expires_at <= NOW()` or `is_active = FALSE`). 2. **Collapsible Accordion:** - Below the active deck, render a native `
` block: ```html
📁 Expired Events ({expiredEvents.length}) ...
``` 3. **1-Click Reopen Action:** - For naturally expired events (`is_active = TRUE`), render a dedicated **`[ 🔄 Reopen (+1h) ]`** button calling `POST /api/events/:id/extend` with `extendHours: 1`. ### Phase 6: Quality Gates & Network/Error Mock Testing 1. Run `deno test -A --no-check server/tests/events.test.ts` to assert all extend, attendees, and 404/403 failure paths pass. 2. Run `deno test -A --no-check ui/ui_scripts.test.ts` to verify zero JavaScript syntax or parsing errors. 3. Run `deno fmt`, `deno task lint`, `deno task check`, and `deno test -A --no-check`.