auth-yes/ui/components/SessionsPage.tsx
google-labs-jules[bot] d057e080d3 feat(ui): implement 2-state workshop drawer machine and refine session page hierarchy
- Moved `EventCockpitDeck` below main header in `SessionsPage.tsx`
- Refactored `WorkshopDrawer.tsx` to strictly use a 2-state display toggle (`#eventCreateState` and `#eventHandoffState`)
- Added `aria-label`s to copy buttons for accessibility
- Configured `#status-banner` with `role="status"` and `aria-live="polite"`
- Fixed mobile title text wrapping on `#createdEventTitle`
- Fixed script emoji injection logic to prevent double emojis
- Added JS reset logic in `closeDelegateDrawer` to restore drawer states and clear form data

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-27 00:12:50 +00:00

178 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { AuthenticatedLayout } from "./AuthenticatedLayout.tsx";
import { EventCockpitDeck } from "./sessions/EventCockpitDeck.tsx";
import { DirectPassDrawer } from "./sessions/DirectPassDrawer.tsx";
import { WorkshopDrawer } from "./sessions/WorkshopDrawer.tsx";
import { ScopeModal } from "./sessions/ScopeModal.tsx";
import { SessionTable } from "./sessions/SessionTable.tsx";
import { SessionDeck } from "./sessions/SessionDeck.tsx";
import { SessionsScript } from "./sessions/SessionsScript.tsx";
export const SessionsPage = ({
sessions,
currentSessionId,
apps = [],
isAdmin = false,
eventPasses = [],
}: {
sessions: any[];
currentSessionId: string;
apps?: any[];
isAdmin?: boolean;
eventPasses?: any[];
}) => {
return (
<AuthenticatedLayout
title="Sessions & Delegations"
currentPath="/dashboard/sessions"
isAdmin={isAdmin}
>
<div
id="status-banner"
role="status"
aria-live="polite"
style="display: none; margin-bottom: 1rem; padding: 0.75rem 1rem; border-radius: var(--radius-md); font-size: 0.9rem;"
/>
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1.5rem; flex-wrap: wrap; gap: 1rem;">
<div>
<h1 style="font-size: 1.75rem; font-weight: 700; margin: 0 0 0.5rem 0; color: var(--text-primary);">
Active Sessions & Passes
</h1>
<p style="color: var(--text-secondary); margin: 0; font-size: 0.95rem;">
Manage logins, mint 1:1 ephemeral links & CLI tokens, or launch
multi-claim workshop event passes.
</p>
</div>
<div style="display: flex; gap: 0.75rem; flex-wrap: wrap;">
<button
type="button"
class="btn-primary"
style="min-height: 42px; box-shadow: var(--shadow-sm); display: inline-flex; align-items: center; gap: 0.4rem;"
onclick="openDelegateDrawer()"
>
<span style="font-size: 1.1rem;">🔑</span>
<span>+ Delegate Session</span>
</button>
</div>
</div>
<EventCockpitDeck eventPasses={eventPasses} />
{/* Delegate Session Drawer */}
<div
id="delegateDrawer"
class="card"
style="display: none; border-left: 4px solid var(--primary); margin-bottom: 1.5rem;"
>
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem;">
<div style="width: 100%;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<h3
id="delegateDrawerTitle"
style="margin: 0 0 0.25rem 0; color: var(--text-primary);"
>
Create New Pass / Session
</h3>
<button
type="button"
onclick="closeDelegateDrawer()"
style="background: none; border: none; font-size: 1.3rem; color: var(--text-muted); cursor: pointer;"
>
&times;
</button>
</div>
<div style="display: flex; background: var(--surface-muted); padding: 4px; border-radius: var(--radius-sm); border: 1px solid var(--border-subtle); gap: 4px; margin-top: 1rem; margin-bottom: 1rem;">
<button
type="button"
id="tabBtnDirectPass"
class="delegate-tab-btn active"
onclick="switchDelegateTab('tabDirectPass')"
>
🔑 1:1 Direct Pass
</button>
<button
type="button"
id="tabBtnWorkshopPass"
class="delegate-tab-btn"
onclick="switchDelegateTab('tabWorkshopPass')"
>
🎟 Multi-Claim Workshop Pass
</button>
</div>
</div>
</div>
<DirectPassDrawer apps={apps} isAdmin={isAdmin} />
<WorkshopDrawer apps={apps} />
</div>
<ScopeModal apps={apps} />
{/* Desktop Table View (≥ 768px) */}
<SessionTable
sessions={sessions}
currentSessionId={currentSessionId}
/>
{/* Mobile Adaptive Cards View (< 768px) */}
<SessionDeck
sessions={sessions}
currentSessionId={currentSessionId}
/>
<style>
{`
@media (min-width: 768px) {
.desktop-only { display: block !important; }
.mobile-only { display: none !important; }
}
@media (max-width: 767px) {
.desktop-only { display: none !important; }
.mobile-only { display: flex !important; }
}
.pill-btn {
background: var(--surface-card);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-full);
padding: 0.4rem 0.85rem;
font-size: 0.85rem;
font-weight: 600;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.15s ease;
}
.pill-btn:hover {
border-color: var(--primary);
color: var(--primary);
}
.pill-btn.active {
background: var(--primary-light);
border-color: var(--primary);
color: var(--primary);
}
.delegate-tab-btn {
flex: 1;
padding: 0.5rem 0.75rem;
border-radius: var(--radius-sm);
border: none;
font-weight: 600;
cursor: pointer;
transition: all 0.15s;
background: transparent;
color: var(--text-secondary);
}
.delegate-tab-btn.active {
background: var(--surface-card);
color: var(--primary);
box-shadow: var(--shadow-xs);
}
`}
</style>
<SessionsScript />
</AuthenticatedLayout>
);
};