# Staff Portal — UI Design Two sub-views: **Kitchen** and **Cleaning**. Same mobile-first shell, different content compositions. Audience: kitchen cooks, housekeepers. Read-only. Mobile/tablet first (phones over the counter, tablets in the housekeeping cupboard). Polled refresh, no websockets in v1. Theme: same Mantine tokens as admin/client (red primary on dark surface), but with a simpler layout — large touch targets, generous spacing, fewer columns. ## Auth and routing - Same `js-auth` flow as admin/client - After login, role-based redirect: kitchen → `/staff/kitchen`, cleaning → `/staff/cleaning` - A staff user can hold both roles (small team); UI offers a switcher in the header ## Shell - Top bar: venue name · current date · user avatar · role switcher (if applicable) · refresh button - Body: list / detail - No sidebar (mobile-first) --- ## Kitchen view ### 1. Event list (landing) - One card per upcoming event, chronological - Card content: dates · group name · headcount · today's meal-count badge · "info missing" alert badge if any dietary / headcount fields are still pending - Filter chips: Today · This week · Upcoming - Tap a card → event detail ### 2. Event detail The workhorse. Visual-heavy. #### Sticky header - Group name · course name · headcount · dates - Meal times: Frühstück / Mittagessen / Abendessen (single line) #### Dietary breakdown card (top of body) - `RingProgress` or `DonutChart` showing % per dietary tag (vegan, vegetarian, gluten-free, lactose-free, etc.) - Counts per slice - Same colour tokens reused on the participant list below for visual continuity #### Today's meals card - Small KPI tiles per meal: Frühstück / Mittagessen / Abendessen - Each tile shows: count for today, delta vs. headcount when participants arrive late or leave early ("26 (–2)") - Cake tile shows yes/no for today + €3/person/day total when on #### Allergies & specials card - Flat list grouped by allergen (nuts, soy, strict gluten, dairy, etc.) - Each row: icon · allergen · count · participant initials - Severity tier: - ⚠ standard allergy (avoid in dishes) - ★ requires fully separate prep (the rare 1% that triggers the manual special-diet surcharge) #### Cake days card - Calendar strip (5 days for a 5-night booking) - Cake-on days highlighted; €3/person/day shown #### Notes card - Per-booking admin notes filtered to kitchen-relevant only (`notes.audience=kitchen`). Personnel notes never appear here. #### Daily plan (free-text) - The free-text portion of the schedule the client submitted - Read-only ### Data sources All read-side aggregations on existing tables — no new schema: - Dietary breakdown: `SUM(participants) GROUP BY dietary_tag` for the booking - Today's meals: `participants WHERE booking_id = X AND kind IN (overnight, day_guest) AND arrival_date <= today AND departure_date > today` - Allergies: flat list from `participant_allergies` joined to allergen reference table - Cake days, meal times: from `bookings.extras` and `bookings.meal_times` --- ## Cleaning view ### 1. Event list (landing) - One row per event sorted by changeover date (departure or arrival) - Row content: changeover type icon (`departure` / `arrival` / `flying`) · date · group name · room count · flying-changeover badge - Tap → cleaning detail ### 2. Cleaning detail Spatial / temporal, not dietary. #### Sticky header - Group · dates · room count · flying-changeover badge if applicable ("Rooms cleared by 10:00, ready by 17:00") #### Arrivals / departures card - Arrival time and departure time - Number of rooms in use - Whether the previous group's departure overlaps (flying changeover) #### Room status table (the workhorse) | Room | Type | Beds | Flags | Status | |------|------|------|-------|--------| | 5 | MBZ | 3 | quiet | clean for arrival 15:00 | | 8 | DZ | 2 | shared bath, quiet | clean for arrival 15:00 | | 10 | DZ | 2 | dogs allowed | extra deep clean | - Driven by the booking's room assignments - Flags surfaced as icons (dogs, wheelchair, allergy-friendly, shared bath, double bed 140cm) - "Extra deep clean" auto-shown for `dogs_allowed` rooms when occupied - Per-room admin note shown inline if present #### Notes card - Per-booking admin notes filtered to cleaning-relevant only (`notes.audience=cleaning`) ### Data sources All on existing tables: - Room assignments → which rooms are occupied - Room flags → from `rooms` - Flying changeover → derived from booking start_date == previous booking end_date --- ## Shared shell components - `` — card used in both kitchen and cleaning landing lists - `` — same shell, different content props - `` — filters notes by audience tag ## Non-goals - No editing anywhere in the staff view (read-only by definition) - No real-time updates in v1 — manual refresh button + a "last fetched X minutes ago" indicator - No WhatsApp integration in v1 — handover §6 explicit - No HR features (cook rota assignment is admin-side)