From 0df93e1886e9ffc4402456d2f6943868ae41f937 Mon Sep 17 00:00:00 2001 From: Pen Anderson Date: Tue, 3 Mar 2026 20:51:26 -0600 Subject: [PATCH] Combined Schedule and Shifts views. --- README.md | 8 +- docs/USAGE.md | 20 ++- frontend/src/App.svelte | 3 - frontend/src/components/Nav.svelte | 4 +- frontend/src/pages/ScheduleBoard.svelte | 111 +++++++++++- frontend/src/pages/Shifts.svelte | 221 ------------------------ 6 files changed, 123 insertions(+), 244 deletions(-) delete mode 100644 frontend/src/pages/Shifts.svelte diff --git a/README.md b/README.md index cd596c4..88b09ef 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Turnpike handles gate check-in, volunteer scheduling, and department coordinatio ## Features - **Attendee management** — CSV import (CrowdWork/Zeffy auto-detected), party-size tracking, search, check-in -- **Volunteer scheduling** — departments, shifts with capacity, conflict detection, drag-and-drop reordering +- **Volunteer scheduling** — departments, shifts with capacity, conflict detection, reordering - **Public volunteer signup** — self-registration form with email confirmation, auto-attendee linking - **Volunteer kiosk** — token-authenticated self-service shift signup, no login required - **Gate check-in** — full-screen UI with QR scanner, party check-in ("2/3 checked in"), volunteer dual check-in -- **Schedule board** — department leads and coordinators manage shift assignments with conflict awareness +- **Schedule** — create shifts, assign volunteers, manage assignments with conflict awareness - **Role-based access** — admin, coordinator, volunteer lead (department-scoped), gate - **Offline-first PWA** — installs on phones/tablets, full offline check-in with background sync - **Real-time** — check-ins and changes broadcast live via SSE @@ -61,7 +61,7 @@ See [docs/INSTALLATION.md](docs/INSTALLATION.md) for systemd, Docker, NixOS, and | Role | Access | |------|--------| | `admin` | Full access: attendee import, user management, SMTP settings, all departments and shifts | -| `coordinator` | All departments: volunteers, shifts, schedule board. No user management or settings | +| `coordinator` | All departments: volunteers, shifts, schedule. No user management or settings | | `volunteer_lead` | Own department only: volunteers and shifts scoped to assigned department | | `gate` | Full-screen check-in UI with QR scanner. No access to other pages | @@ -91,7 +91,7 @@ The Vite dev server runs on `:5173` and proxies `/api` requests to the Go server ## Documentation -- [Usage Guide](docs/USAGE.md) — event setup, attendee import, volunteer signup, volunteer kiosk, gate check-in, schedule board +- [Usage Guide](docs/USAGE.md) — event setup, attendee import, volunteer signup, volunteer kiosk, gate check-in, schedule - [Installation Guide](docs/INSTALLATION.md) — building, deploying, systemd, Docker, NixOS, reverse proxy, backup ## License diff --git a/docs/USAGE.md b/docs/USAGE.md index 8e0d174..de4e765 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -13,8 +13,8 @@ After logging in, create accounts for your team under **Users**. Each user gets | Role | What they see | What they can do | |------|--------------|------------------| | **admin** | All pages + Settings | Everything: attendee import, user management, SMTP config, departments, shifts, volunteers | -| **coordinator** | Dashboard, Schedule Board, Volunteers, Departments, Shifts | Manage volunteers, departments, and shifts across all departments. Cannot manage users or settings | -| **volunteer_lead** | Schedule Board, Volunteers, Departments | Manage volunteers and shifts within their assigned department only | +| **coordinator** | Dashboard, Schedule, Volunteers, Departments | Manage volunteers, departments, and shifts across all departments. Cannot manage users or settings | +| **volunteer_lead** | Schedule, Volunteers, Departments | Manage volunteers and shifts within their assigned department only | | **gate** | Full-screen Gate UI | Check in attendees (search + QR scan). No access to other pages | Ticketing and ops staff should use the **admin** role. The `ticketing` role exists in the codebase but is effectively unused — admin covers all ticketing functions. @@ -26,7 +26,7 @@ Volunteer leads are scoped to a single department. When creating a volunteer_lea 1. **Configure your event** — go to the Dashboard and set the event name and dates. 2. **Create departments** — under Departments, add each department your event needs (e.g., Gate, Greeters, Rangers, Build, LNT). 3. **Import attendees** — see next section. -4. **Create shifts** — under Shifts, create shifts for each department with day, start/end time, and capacity. +4. **Create shifts** — under Schedule, create shifts for each department with day, start/end time, and capacity. ## Importing Attendees @@ -108,7 +108,7 @@ Volunteers are separate from attendees. A person can be both an attendee (ticket ## Shift Scheduling -Under **Shifts**, create shifts for each department: +Under **Schedule**, create shifts for each department: - **Day** — the date of the shift - **Start/end time** — HH:MM format @@ -116,11 +116,11 @@ Under **Shifts**, create shifts for each department: ### Assigning volunteers -From the Shifts page or the Schedule Board, assign volunteers to shifts. Turnpike checks for conflicts — if a volunteer already has a shift on the same day with overlapping times, you'll see a warning and can choose to force the assignment. +From the Schedule page, assign volunteers to shifts. Turnpike checks for conflicts — if a volunteer already has a shift on the same day with overlapping times, you'll see a warning and can choose to force the assignment. ### Reordering -Shifts can be reordered within a department to reflect priority or sequence. The Schedule Board supports drag-and-drop reordering. +Shifts can be reordered within a department to reflect priority or sequence using the up/down buttons on each shift card. ## Volunteer Kiosk @@ -162,9 +162,9 @@ Users with the **gate** role see a dedicated full-screen UI: Gate devices should install Turnpike as a PWA (Add to Home Screen) for the best experience. Check-ins are stored locally and sync when connectivity is available. -## Schedule Board +## Schedule -The Schedule Board is the primary UI for coordinators and volunteer leads. It shows: +The Schedule page is the primary UI for managing shifts and volunteer assignments. It shows: - Shifts grouped by department and day - Each shift card shows: name, time, capacity (used/total), assigned volunteers @@ -173,10 +173,12 @@ The Schedule Board is the primary UI for coordinators and volunteer leads. It sh **Coordinators and admins** see all departments. **Volunteer leads** see only their assigned department. Actions available: +- Create new shifts (+ Add shift button) +- Edit shift details inline +- Delete shifts - Assign volunteers to shifts from a dropdown - Remove volunteer assignments - Reorder shifts within a department -- Edit shift details inline ## SMTP Configuration diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index e9c0638..0fed314 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -7,7 +7,6 @@ import Attendees from './pages/Attendees.svelte' import Volunteers from './pages/Volunteers.svelte' import Departments from './pages/Departments.svelte' - import Shifts from './pages/Shifts.svelte' import Users from './pages/Users.svelte' import Import from './pages/Import.svelte' import Kiosk from './pages/Kiosk.svelte' @@ -133,8 +132,6 @@ {:else if path.startsWith('/departments')} - {:else if path.startsWith('/shifts')} - {:else if path.startsWith('/schedule')} {:else if path.startsWith('/users')} diff --git a/frontend/src/components/Nav.svelte b/frontend/src/components/Nav.svelte index a0257c8..cef8d7c 100644 --- a/frontend/src/components/Nav.svelte +++ b/frontend/src/components/Nav.svelte @@ -1,5 +1,5 @@ - -
- - - {#if error} -
{error}
- {/if} - - {#if showAdd && canManage} -
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
-
-
- {/if} - - {#if ($allShifts ?? []).length === 0} -
- No shifts yet -

Add shifts to schedule your volunteers.

-
- {:else} - {#each grouped as { dept, days }} -
-
- - {dept.name} -
- {#each days as { day, shifts }} -
-
- {formatDay(day)} -
-
- - - {#each shifts as s (s.id)} - - - - - {#if canManage} - - {/if} - - {/each} - -
{s.name}{formatTime(s.start_time)} – {formatTime(s.end_time)} - {#if s.capacity} - Capacity: {s.capacity} - {:else} - Unlimited - {/if} - - -
-
-
- {/each} -
- {/each} - {#if ungrouped.length > 0} -
- {ungrouped.length} shift(s) with unknown departments -
- {/if} - {/if} -