Merge pull request #50 from mrteye/feat-sessions-drawer-machine-11417224878052948069
feat(ui): implement 2-state workshop drawer machine and refine session page hierarchy Reorganized the Sessions page hierarchy to place the Event Cockpit below the main header. Refactored the Workshop Drawer to utilize a strict 2-state container machine for clean transitions between the creation form and the success handoff modal. Implemented UI accessibility enhancements and fixed mobile text wrapping constraints.
This commit is contained in:
commit
57f5fc7700
@ -28,11 +28,11 @@ export const SessionsPage = ({
|
||||
>
|
||||
<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;"
|
||||
/>
|
||||
|
||||
<EventCockpitDeck eventPasses={eventPasses} />
|
||||
|
||||
<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);">
|
||||
@ -57,6 +57,8 @@ export const SessionsPage = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<EventCockpitDeck eventPasses={eventPasses} />
|
||||
|
||||
{/* Delegate Session Drawer */}
|
||||
<div
|
||||
id="delegateDrawer"
|
||||
@ -66,7 +68,10 @@ export const SessionsPage = ({
|
||||
<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 style="margin: 0 0 0.25rem 0; color: var(--text-primary);">
|
||||
<h3
|
||||
id="delegateDrawerTitle"
|
||||
style="margin: 0 0 0.25rem 0; color: var(--text-primary);"
|
||||
>
|
||||
Create New Pass / Session
|
||||
</h3>
|
||||
<button
|
||||
|
||||
@ -22,6 +22,15 @@ export const SessionsScript = () => {
|
||||
|
||||
function closeDelegateDrawer() {
|
||||
document.getElementById('delegateDrawer').style.display = 'none';
|
||||
// Reset WorkshopDrawer 2-State Machine
|
||||
const eventCreateState = document.getElementById('eventCreateState');
|
||||
if (eventCreateState) eventCreateState.style.display = 'block';
|
||||
const eventHandoffState = document.getElementById('eventHandoffState');
|
||||
if (eventHandoffState) eventHandoffState.style.display = 'none';
|
||||
const eventForm = document.getElementById('eventForm');
|
||||
if (eventForm) eventForm.reset();
|
||||
const drawerTitle = document.getElementById('delegateDrawerTitle');
|
||||
if (drawerTitle) drawerTitle.textContent = 'Create New Pass / Session';
|
||||
}
|
||||
|
||||
function switchDelegateTab(tabId) {
|
||||
@ -150,11 +159,15 @@ export const SessionsScript = () => {
|
||||
const data = await res.json();
|
||||
if (res.ok && data.success) {
|
||||
const ev = data.event;
|
||||
document.getElementById('createdEventTitle').textContent = '🎟️ ' + ev.name + ' Live!';
|
||||
document.getElementById('createdEventTitle').textContent = ev.name + ' Live!';
|
||||
document.getElementById('eventHandoffPin').textContent = ev.pin_code;
|
||||
document.getElementById('eventHandoffLink').textContent = window.location.origin + '/e/' + ev.slug;
|
||||
document.getElementById('eventHandoffCli').textContent = 'curl -sSL ' + window.location.origin + '/join/' + ev.slug + '?format=env | source /dev/stdin';
|
||||
document.getElementById('eventHandoffModal').style.display = 'block';
|
||||
|
||||
document.getElementById('eventCreateState').style.display = 'none';
|
||||
document.getElementById('eventHandoffState').style.display = 'block';
|
||||
document.getElementById('delegateDrawerTitle').textContent = 'Event Pass Active';
|
||||
|
||||
showNotice('Workshop pass created: ' + ev.name, false);
|
||||
} else {
|
||||
showNotice(data.error || 'Failed to create event pass', true);
|
||||
@ -177,7 +190,7 @@ export const SessionsScript = () => {
|
||||
}
|
||||
|
||||
function closeEventHandoffModal() {
|
||||
document.getElementById('eventHandoffModal').style.display = 'none';
|
||||
closeDelegateDrawer();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
return (
|
||||
<div id="tabWorkshopPass" style="display: none;">
|
||||
<div id="eventCreateState" style="display: block;">
|
||||
<p style="color: var(--text-secondary); font-size: 0.9rem; margin: 0 0 1rem 0;">
|
||||
Generate a shared event pass with a universal 6-digit PIN, vanity link
|
||||
(<code style="font-size: 0.8rem;">/e/slug</code>), and CLI 1-liner for
|
||||
@ -195,23 +196,29 @@ export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* Event Launch Success Modal / Card */}
|
||||
{/* Event Launch Success State */}
|
||||
<div
|
||||
id="eventHandoffModal"
|
||||
id="eventHandoffState"
|
||||
style="display: none; margin-top: 1.5rem; padding: 1.25rem; background: var(--surface-card); border: 2px solid var(--success); border-radius: var(--radius-md); box-shadow: var(--shadow-md);"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
<span style="font-size: 1.3rem;">🎟️</span>
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem; flex: 1; min-width: 0;">
|
||||
<span style="font-size: 1.3rem; flex-shrink: 0;">🎟️</span>
|
||||
<strong
|
||||
id="createdEventTitle"
|
||||
style="color: var(--text-primary); font-size: 1.1rem;"
|
||||
style="color: var(--text-primary); font-size: 1.1rem; overflow-wrap: break-word; word-break: break-word; max-width: 100%; display: block;"
|
||||
>
|
||||
Workshop Pass Live!
|
||||
</strong>
|
||||
</div>
|
||||
<span class="badge badge-success">Active Now</span>
|
||||
<span
|
||||
class="badge badge-success"
|
||||
style="flex-shrink: 0; margin-left: 0.5rem;"
|
||||
>
|
||||
Active Now
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p style="font-size: 0.85rem; color: var(--text-secondary); margin: 0 0 1rem 0;">
|
||||
@ -235,6 +242,7 @@ export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
<button
|
||||
type="button"
|
||||
class="btn-primary"
|
||||
aria-label="Copy Universal PIN"
|
||||
style="min-height: 36px; padding: 0 0.85rem; font-size: 0.8rem;"
|
||||
onclick="copyEventHandoff('pin')"
|
||||
>
|
||||
@ -257,6 +265,7 @@ export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
<button
|
||||
type="button"
|
||||
class="btn-outline"
|
||||
aria-label="Copy Direct Link"
|
||||
style="min-height: 36px; padding: 0 0.85rem; font-size: 0.8rem;"
|
||||
onclick="copyEventHandoff('link')"
|
||||
>
|
||||
@ -279,6 +288,7 @@ export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
<button
|
||||
type="button"
|
||||
class="btn-outline"
|
||||
aria-label="Copy Terminal curl command"
|
||||
style="min-height: 36px; padding: 0 0.85rem; font-size: 0.8rem;"
|
||||
onclick="copyEventHandoff('cli')"
|
||||
>
|
||||
@ -294,7 +304,7 @@ export const WorkshopDrawer = ({ apps = [] }: { apps?: any[] }) => {
|
||||
style="width: 100%; min-height: 38px; justify-content: center; font-size: 0.85rem;"
|
||||
onclick="closeEventHandoffModal()"
|
||||
>
|
||||
Done & Refresh Cockpit
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user