[E05] Events Control Centre — Workspace Landing

Summary

The Events workspace landing. Loads when the user enters the Events workspace — after login (when last context restores them here), via the workspace switcher, or after a tenant switch where the destination tenant’s last workspace was Events. Shows the portfolio of events for the current tenant; per-event detail lives in E01.

Carved out of the C01 design canvas in the 2026-04-27 review — workspace landing content is functional, not structural, and shouldn’t live in C01. Designed in Claude Design 2026-04-27 (round-trip 3); the per-row Recent events anatomy and the Next-up fallback are this session’s substantive new design output.

Actor & Context

Actors:

  • Event organiser — primary user. Wants to see what’s open, what needs attention, what’s been done.

  • Tenant admin — uses E05 as a portfolio view of the tenant’s events.

  • Finance — tracks pending payments and post-event recon items via Recent + Attention queues.

  • Results officer — verifies/publishes results; their items rank higher in Attention.

  • Staff — same layout, action affordances suppressed (rows clickable, bulk actions hidden).

Frequency: every session, multiple times per day during active event seasons.

Precondition: user authenticated, tenant selected, Events workspace active in the C01 sidebar.

Entry points:

  • Default landing after login (when last context = Events workspace, or first login).

  • Sidebar — clicking Events in the workspace switcher.

  • Sidebar — clicking Overview in the Events portfolio nav.

  • After a tenant switch where the destination tenant’s last workspace was Events.

Layout

E05 renders inside C01’s shell — sidebar + topbar are C01’s. E05 owns only the main content area.

Region Content

Topbar

Breadcrumb Tenant ▸ Events ▸ Overview + Jump-to (⌘K) + notifications bell. Provided by C01.

Welcome banner

Welcome back, {firstName} micro-label + Resume where you left off headline (or Here’s what’s next when there’s no last activity).

Resume bar or Next-up panel

Indigo Resume bar when lastContext resolves to a recent event; quieter Next-up panel when not (see Resume / Next-up fallback hierarchy). Mutually exclusive; banner copy matches.

Left column (1.4fr)

Active events panel + Recent events panel stacked beneath it. Recent hides entirely when empty — Active grows to fill the column.

Side column (1fr)

Tenant glance (4-cell metric grid) on top, Needs your attention queue beneath. Always present — these are the cross-portfolio signal.

The two-column grid holds at the design’s reference 1280×820. Below ~1100 px it should collapse into a single column with side-column sections moving below the left column (responsive floor TBD in implementation).

Sidebar — portfolio-only nav (cross-cutting C01 revision)

Locked in this design pass: when E05 is the current screen, the Events sidebar shows only portfolio-level entries: Overview · Events · Reports. Per-event nav items (Categories · Courses · Races · Participants · Start groups · Program · Results) presuppose an event context that does not exist on a workspace landing — they surface only on E01 once the user enters a specific event.

This revises the sidebar definition in C01. C01 needs a follow-up design pass to capture the two sidebar modes (portfolio mode vs event mode) and the transition between them. Tracked as a forward-engineering item (see below).

Main Flow

  1. Render shell. C01 sidebar (portfolio nav) + topbar.

  2. Resolve last-activity context. Read lastContext (localStorage v1; gateway-side later). If lastContext.workspace === 'event', lastContext.entityId resolves to an event the user can access, and lastTouched ⇐ 14 days ago, prepare a Resume bar. Otherwise, prepare a Next-up panel sourced from the topmost upcoming event in the Active list.

  3. Render Welcome banner. Welcome back, {firstName} + headline (Resume where you left off for Resume mode, Here’s what’s next for Next-up mode).

  4. Render Resume bar OR Next-up panel. See Resume / Next-up fallback hierarchy. Both occupy the same row; never both at once. If neither resolves, render the Welcome banner only and proceed.

  5. Render Active events panel (left column). Current + upcoming events, sorted ascending by start date. Each row: dated thumbnail (Mon · DD) + name + status dot + status copy + count or "Not published" + chevron.

  6. Render Recent events panel beneath Active (left column) — only when recentEvents.length > 0.

  7. Render Tenant glance (side column top) — 4 KPI cells (Active events / Participants / Open draft / Results pending).

  8. Render Needs your attention queue (side column bottom) — short list of pending actions across the tenant’s events; severity-coloured icon + title + sub-context. Caps at N rows (5–7) with a View all link if exceeded; the count of red (blocking) items appears as a badge in the panel header.

  9. User proceeds by clicking Resume / Next up’s CTA, an event row (→ E01), an attention item (→ relevant sub-screen), or by switching tenant / workspace.

Resume / Next-up fallback hierarchy

Three-tier fallback. Last-activity wins regardless of stage — if the user spent yesterday closing reports for a past event, today Resume points there:

Tier Condition Surface

1

Last-touched event ≤ 14 days ago AND user has current access AND lastContext.workspace === 'event'

Resume bar (indigo, primary). Icon = event for current-stage events, trophy for post-event. Past-event variants display a Post-event · {section} chip ("Reports", "Results", "Refunds", etc.) so the user knows where Resume is taking them before they click. Dual CTA: secondary Event overview, primary Resume.

2

Tier 1 fails AND tenant has at least one upcoming event

Next-up panel (neutral, quieter). Surfaces the next upcoming event by start date as a soft queue ("Cape Town Marathon — Oct 18, opens for setup tomorrow"). Dual CTA: secondary View all events, primary Open event.

3

Neither tier resolves

Welcome banner only. No bar. Banner copy stays Here’s what’s next so the page does not look broken.

Last-activity is personal, not tenant-wide — Resume and Next-up are user-scoped. Cross-device persistence is trusted only when authenticated; cleared-cache or anonymous-on-new-device cases are treated identically to first login. No pinned-event override.

When the user switches tenants in the sidebar, E05 reloads with the destination tenant’s lastContext. Resume across tenants is filtered by tenant ID — yesterday’s Tenant A activity does not surface as Resume after a switch to Tenant B.

Recent Events Panel — locked design

Past events that still have outstanding post-event work. Past events that closed cleanly do not clutter — the panel hides entirely.

Per-row anatomy

  • Past-toned date thumbnail — greyed (tone="past") so Recent rows visually distinguish from Active rows even on fast scan.

  • Event name + completion meta (Closed N days ago) right-aligned in the title row.

  • Status pills — up to 3 visible, "+N" overflow chip when more. Pills indicate which work is open; vocabulary below.

  • Urgent follow-up sub-line — the single most urgent open item with its deadline (e.g. CSA affiliating-body report due in 4 days). Coloured by severity (amber for in-window, red for past-deadline). Surfaces urgency without needing a deadline column.

  • Chevron — click anywhere on the row navigates to E01’s Post-event stage for that event.

Status pill vocabulary

Pill Severity Meaning

Reports pending

Amber

Affiliating-body report (e.g. CSA), insurance manifest, or other compliance report not filed.

Financials open

Amber

Post-event finance recon not closed.

Refunds pending

Amber

Outstanding refund processing.

Results unverified

Amber

Correction window still open, or results not yet published.

Results overdue

Red

Correction window closed and results still unverified — escalates to red.

Insurance manifest

Amber

Manifest filing outstanding for affiliating body.

Multiple pills per row allowed. Pill click deep-links to the matching section in E01’s Post-event stage (e.g. clicking Reports pending lands on the reports lane).

Sort, limit, empty state

  • Default sort: most recently completed first (completedAt desc).

  • Default visible: 5 rows + "View all" link when more exist. The footer reads "N more events have open follow-ups" with a View all arrow.

  • Empty state: hide the panel entirely. No "All caught up" card. Active expands to fill the left column.

"View all" route

Working placeholder: /events?status=recent&followUpsOpen=true. Final route shape is deferred to E02 — Recent’s "View all" adopts whatever filter vocabulary E02 lands on for the events list page. Re-confirm when E02’s design pass starts.

Alternative Flows

  • AF-1 — No active events. Active panel renders an empty state (No active events) and a Create event CTA gated to EVENT_MANAGER / TENANT_ADMIN. STAFF sees the empty state without the CTA.

  • AF-2 — No recent events with outstanding work. Recent panel hides entirely. Active expands to fill the left column.

  • AF-3 — First login or stale > 14 days. Resume bar hidden; Next-up panel takes its place. Welcome headline becomes Here’s what’s next.

  • AF-4 — No upcoming events either. Both Resume and Next-up are hidden. Welcome banner only. Page does not render an empty hero — it just starts at the columns.

  • AF-5 — Read-only role. STAFF sees the same layout but with action buttons disabled or hidden (no Create event, no bulk actions on Attention items).

  • AF-6 — Cross-tenant switch. When the user switches to a different tenant, E05 reloads. The destination tenant’s lastContext drives the Resume / Next-up tier; Tenant A’s activity does not leak into Tenant B’s surface.

Acceptance Criteria

  • E05 renders inside C01’s shell — sidebar shows the portfolio-only nav (Overview · Events · Reports), no event-scoped items.

  • Welcome banner shows the user’s first name (from /api/session/current).

  • Resume bar renders only when Tier 1 conditions are met (see Resume / Next-up fallback hierarchy). Past-event variants display the Post-event · {section} chip and the trophy icon.

  • Next-up panel renders only when Tier 1 fails and at least one upcoming event exists in the tenant.

  • Welcome-only state renders cleanly when neither Resume nor Next-up resolves.

  • Active events list shows current + upcoming, sorted ascending by start date; row chevron navigates to E01.

  • Recent events panel hidden when no past event has followUpsOpen === true. Active expands to fill the left column when Recent is hidden.

  • Recent rows display past-toned date thumb, name, completion meta, up to 3 pills (+ "+N" overflow), and an urgent sub-line with severity colour.

  • Recent rows cap at 5 visible; overflow renders the View all footer.

  • Recent row click navigates to E01 Post-event stage; pill click deep-links to the matching section.

  • Tenant glance renders the 4 KPI cells; values reload on tenant switch.

  • Needs-attention queue renders rows with severity icons; the count of red items appears as a badge in the panel header.

  • Tenant switch reloads E05 with the destination tenant’s data; no data from the previous tenant remains visible.

  • Pill colours follow the locked vocabulary (Reports / Financials / Refunds / Results-unverified = amber; Results-overdue = red).

API Surface

Call Purpose

GET /api/session/current (gateway, see C01)

Provides user.firstName, currentTenantId, lastContext for the Welcome banner + Resume bar tier-1 check.

GET /api/events?status=active&size=N (admin-service)

Active events list, current + upcoming. Topmost row also drives the Next-up panel (no separate endpoint needed).

GET /api/events?status=recent&followUpsOpen=true&size=5 (admin-service — NEW filter)

Recent events with outstanding post-event work. New filter on existing EventResource. Response defines event.followUpsOpen as a derived boolean and includes a per-event openFollowUps[] array of typed entries ({ kind: 'reports' | 'finance' | 'refunds' | 'resultsAmber' | 'resultsRed' | 'insurance', urgent?: { label, severity, deadline } }) so the row pills + urgent sub-line render without extra calls.

GET /api/admin-portal/tenant-glance (gateway, composite — likely NEW)

4 KPI metrics. Composite of existing per-resource counts (active events / participants / open drafts / results pending). Cached briefly per tenant.

GET /api/admin-portal/attention-queue (gateway or admin-service — likely NEW)

Needs-attention items across the tenant’s events. Best implemented as a reactor on Async Signal & Sweep Framework (Feature #403); synchronous query in the interim.

Out of Scope

  • Single-event drilldown (E01).

  • Event creation flow (a future use case under Exx).

  • Memberships or other workspaces' landings (mirror this pattern when designed).

  • C01 shell concerns (sidebar chrome, topbar, notifications panel).

  • The /events (events list) page that the Recent "View all" links to — that is E02's scope (or a sibling list-screen use case once E02 narrows).

Design Anchors

  • C01 Application Structure — the shell E05 sits inside (and the source of the cross-cutting sidebar revision noted above).

  • E01 Event Overview — what’s behind clicking an event row, and the destination for Recent-row + pill-click navigation.

  • UI Design Principles — Linear/Vercel cool-neutral, Inter, indigo #4f46e5 accent, workspace tints as quiet chips.

  • Design URL (above) — the Claude Design canvas with four frames: full layout, Resume on past event, no Recent, first-login (Next-up).

Open Questions

  1. Cross-device lastContext persistence. localStorage v1 is per-device; cross-device authenticated trust requires server-side storage. Proposal: gateway-side GET/PUT /api/admin-portal/last-context written on entity-screen navigation, read at workspace landing. Defer until a real complaint surfaces — front-end-only is acceptable for v1 per the stale  14 days = first login treatment.

  2. event.followUpsOpen derivation. Concretely, true when any of: results not published past correction window, finance recon not closed, compliance reports not filed, refunds outstanding. Each is currently a separate query; a derived field (or projection) on EventResource saves the round-trips. Backend ticket needed under Epic #533.

  3. Active vs Recent threshold. When does an event move from Active to Recent? At eventDate < today? At eventDate < today - 24h? Likely the same condition that drives event.stage from pre-racepost-event. Confirm during admin-service work on followUpsOpen.

  4. Tenant glance refresh cadence. Reload on tenant switch and on a 60s interval, or only on explicit user action? Lean toward "tenant switch + manual refresh" for v1; revisit if metrics drift becomes user-visible.

  5. Needs-attention sourcing. Sync vs reactive (Async Signal & Sweep, Feature #403). Pick sync for v1; promote to reactor when #403 lands.

  6. "Stale" threshold for Resume → Next-up. Locked at 14 days for the design pass. Revisit if real users find 14 days too long (showing Resume to events they’ve forgotten) or too short (losing context they expect to resume).

  7. "View all" route shape. Placeholder /events?status=recent&followUpsOpen=true; final shape adopts E02’s filter vocabulary. Re-evaluate when E02 design starts.

Forward-Engineering Backlog

  1. C01 sidebar revision (cross-cutting). Capture the two sidebar modes (portfolio mode: Overview · Events · Reports; event mode: full event-scoped nav) and the transition between them. Belongs in the next C01 design pass; flagged here so it’s not lost.

  2. event.followUpsOpen derived flag — admin-service ticket. Drives the Recent panel’s filter and the per-row openFollowUps[] projection. File under Epic #533 when this lands in active work.

  3. Tenant glance composite endpoint — gateway-side composite of existing per-resource counts. Owned by E05, not C01. File when WS5 starts.

  4. Attention queue endpoint — synchronous v1, reactive once Feature #403 lands.

  5. Resume bar + Next-up persistence — localStorage v1; written by every entity-screen navigation; read at workspace landing render. Consumes lastContext written by E01, E02, etc. Server-side persistence is a follow-up if cross-device drift becomes a real complaint.

  6. Recent panel "View all" route — adopt E02’s filter vocabulary once E02 design lands.

  7. Pill deep-link anchors on E01 Post-event stage — E01 Post-event needs section anchors (#reports, #finance, #results, #refunds) for pill-click navigation to land in the right lane. Coordinate when E01 enters implementation.

Change History

Date Change

2026-04-27 (round 3, afternoon)

Designed in Claude Design (URL captured above). Status: design-todo → handoff-ready. Locked decisions: Layout Option A (Recent stacks under Active), Resume = last activity, Next-up panel as Tier-2 fallback, Recent default sort + 5-row limit, status pill vocabulary, portfolio-only sidebar nav (cross-cutting C01 revision flagged). New regions added vs the C01 carve-out brief: per-row Recent anatomy, Next-up panel, sidebar mode revision.

2026-04-27 (morning)

Stub authored. Use case carved out of C01 to keep C01 structural-only. Recent events brief added per user direction. E05 design itself was design-todo — awaiting next Claude Design pass with this page as the brief.