Files
2026-07-11 08:06:17 +02:00

256 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Admin Portal — UI Design
Audience: Sarah (owner) and Christina (admin assistant). Christina is the
heaviest user (booking admin all day). Sarah uses it for oversight,
pricing/AGB updates, and high-stakes status decisions.
Theme: shared Mantine tokens with the client portal (dark surface, red
primary), but **denser components** — admin is data-heavy, not card-warm.
## Navigation
Sidebar (collapsible to icons-only on smaller screens):
- Dashboard (default landing)
- Bookings
- Calendar
- Cooks (rota + roster)
- Organisations (incl. Stammgruppen)
- Pricing (year-versioned)
- AGB (versioned PDFs)
- Venues (multi-tenant — switch venue here)
- Settings
## 1. Dashboard (landing)
Static layout for v1. Configurable widget mosaic deferred to v1.5.
```
┌──────────────────────────────────────────────────────────────┐
│ Action queue [N items] │ full-width
│ Overdue Orga-Mails, missing deposits, missing room plans, │
│ missing dietary info. Each row → one-click action. │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────┐ ┌──────────────────────────────┐
│ This week │ │ Recent client activity │
│ Arrivals + departures │ │ Last 48h booking edits │
│ next 7 days, completeness│ │ across all bookings │
│ %, flags │ │ │
└──────────────────────────┘ └──────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐
│ Pipeline / │ │ Cook rota │ │ Quick actions │
│ financial │ │ status │ │ + New booking │
│ KPIs │ │ unassigned │ │ + New enquiry │
└──────────────┘ └──────────────┘ │ + Send Orga-Mail │
└──────────────────────┘
```
12-column CSS Grid. Top hero spans 12. Mid row 6+6. Bottom row 4+4+4.
Mobile collapses to 1 column.
### Widget contracts (v1.5 readiness)
Each section is built as a self-contained React component with a stable
key. When the configurable mosaic ships, these become draggable widgets
with no contract changes.
## 2. Bookings list
Table-first. Replaces the Buchungsübersicht spreadsheet.
- **Library:** Mantine `DataTable` or `mantine-react-table`
- **Columns:** Year · Date range · Group / Organisation · Status pill ·
Persons · Half-house · Orga-Mail sent · Deposit · Final invoice · Notes
(truncated)
- **Filters** (sidebar drawer): status, year, half-house, has-deposit,
has-final-invoice, organisation, missing-info (room plan / dietary /
headcount)
- **Sticky header** + virtualised rows
- **Bulk actions** (with confirmation modals): send Orga-Mail to
selected, export DATEV CSV, mark deposit received
- **Full-text search:** organisation name + course name
- **Default sort:** date ASC, current year first
- **Row click:** opens booking detail in same tab
## 3. Calendar view
Replaces the Belegungsplan spreadsheet.
- **Views:** month (default), quarter, year
- **Status colouring** mapped to theme tokens:
- `enquiry` — pink
- `reserved` — amber
- `form_received` — yellow
- `deposit_paid` — light green
- `confirmed` — green
- `completed` — grey
- `cancelled` — strikethrough red
- **Half-house** rendering: day cell splits visually into top/bottom
halves when two groups overlap
- **Click cell or booking** → open booking detail
- **Drag-and-drop reschedule** opens a modal that surfaces the
cancellation-policy implications (e.g. "this falls within 12 weeks of
arrival — fees may apply")
- **Year header strip:** occupancy %, free-day count
- **Filter chips above:** org, status (multi-select)
## 4. Single booking detail
The workhorse. Tabbed organisation.
### Sticky header
- Group name · status pill · dates (large) · headcount · half-house badge
- Status-transition button (contextual)
- Quick actions: edit, send Orga-Mail, send reminder, attach invoice,
cancel
### Main column (left, ~70%) — tabs
1. **Overview**
- Completeness checklist (Orga-Mail sent · deposit · room plan ·
dietary · headcount · schedule)
- Key dates timeline
- Flags (flying changeover · dogs · wheelchair · individual invoicing)
- Pricing summary (line items + total)
2. **Participants**
- Editable table: name · age · `kind` (overnight | day_guest) ·
dietary tags · allergies · room (if overnight)
3. **Room plan** — split view, grid as primary editor + live floor-plan
visualisation. Both backed by the same `room_assignments` model.
- **Left — assignment grid:** rows = overnight participants;
columns = name · age · dietary tags · room (combobox with live
capacity counter) · notes. Bulk-select participants → assign to a
room. Keyboard-fast (Tab / type-to-search / Enter to commit).
Inline validation: overcapacity, conflicting flags (e.g.
wheelchair user only assignable to Rooms 1 and 2).
- **Right — floor plan visualisation:** SVG overlay on top of
`grundrisse.pdf`, hot-spotted with room rectangles. Each room
shows number, capacity dots filled per occupant, flag icons.
Live-updates as the grid changes. Click a room → highlights its
occupants in the grid. Hover a participant → highlights their room.
- **v1.5 enrichment:** click-room-to-assign-selected (spatial
click-select pattern matching the rest of admin)
- **Post-MVP:** drag a participant card onto a room on the floor plan
4. **Schedule & meals**
- Structured times for Frühstück / Mittagessen / Abendessen
(validated against allowed-window config)
- Free-text daily plan
5. **Extras**
- Booking-time extras (cake, second seminar room, linen, early
arrival, etc.)
- On-site extras logged by staff (sauna, drinks, coffee) with
`payment_method` flag (`cash` default · `invoice`)
6. **Invoices**
- Deposit invoice (PDF + DATEV ref + paid status)
- Final invoice (PDF + DATEV ref + paid status)
- DATEV line-item export button (CSV/JSON)
7. **Audit log**
- Full change history: who · when · field · before → after
### Side column (right, ~30%) — always visible
- Organiser contact (name · email · phone · billing address ·
organisation link)
- Internal notes (Bemerkungen) — markdown, per-booking
- Recent activity (last 5 changes, link to full audit)
- Linked enquiry (if any)
- Assigned KOCH/IN per event day
## 5. Cook rota grid
Replaces the Küchenplan spreadsheet.
- **Layout:** one row per day, one column per cook
- **Left columns** (locked / sticky): day-of-month · seminar room
occupants (Mandala · Yogaraum) · PAX · KOCH/IN · KOMMENTARE
- **Right columns:** one per active staff cook + EXTERN
- **Cells:** edit-on-click, code-aware text input with autocomplete from
the **`shift_code` enum**
- **Shift code enum** (DB-backed, not freeform):
- `F` — Frühstück
- `M` — Mittagessen
- `A` — Abendessen
- `S` — Spät / extra shift
- `R-K` — Reinigung Küche
- `R-HH` — Reinigung Haupthaus
- `R-HH-Zi` — Reinigung Haupthaus Zimmer
- `GR-K` — Grundreinigung Küche
- `nur-A` — only dinner
- `off` — explicit off
- Plus optional explicit time (`HH:mm`) and per-cell free-text note
- **Multiple codes per cell:** combine via `/` (e.g. `F/M`); UI renders
each as a coloured chip
- **Bracket convention (`(...)`)** marking event start/end is
**auto-rendered** by the grid from each booking's start/end dates —
not typed
- **Filters above grid:** month, cook, event
- **Conflict highlighting:** when a cook has overlapping shifts on the
same day, cell shows a warning badge
### Schema implication
```
shift_codes
code text PK -- 'F' | 'M' | 'A' | 'S' | 'R-K' | …
label text
color text -- theme token
cook_assignments
id uuid
venue_id uuid → venues
booking_id uuid → bookings (nullable for non-event days e.g. GR-K)
cook_id uuid → cooks
date date
shift_codes text[] → shift_codes.code
explicit_time time
note text
```
## 6. Auxiliary admin screens (CRUD, low design effort)
- **Organisations** — list + detail; Stammgruppe boolean toggle; merge
duplicates
- **Pricing** — year-versioned editor (one form per year, fields for EZ
/ DZ / MBZ / day guest / kids 310 / cake / sauna / linen / etc.)
- **AGB** — upload PDF per year; list previous versions
- **Venues** — switch active venue (multi-tenant); edit venue settings
(allowed meal-time windows, default Half House split, etc.)
- **Cooks** — roster: name · kind (`staff` | `external_vendor` |
`inactive`) · compensation model + amount · notes
- **Settings** — current user profile, notifications preferences,
language preference, email signature
## Styling & component approach
**Mantine** as the component library. Theme tokens (red primary on dark
surface from the client-portal screenshot) shared across all four
surfaces — same tokens, surface-specific compositions. Admin uses
denser Mantine compositions; client uses warmer card-based ones.
Mantine ecosystem packages used:
- `@mantine/core` — components
- `@mantine/dates` — date pickers (`de` locale via `dayjs`)
- `@mantine/hooks` — utilities
- `mantine-react-table` (or `mantine-datatable`) — bookings list
virtualisation, filtering, bulk select
**No drag-and-drop in MVP.** Interactions previously sketched with DnD
become click-select-then-target. DnD is a post-MVP enrichment, not a
load-bearing primitive — the click pattern works without it.
- **Calendar reschedule** — "Reschedule" button → date-picker modal
that surfaces cancellation-policy implications inline. Drag-to-
reschedule possible later as enrichment.
- **Room plan** — split view: assignment grid + live floor-plan SVG.
Grid is the primary editor; floor plan visualises live. v1.5 adds
click-room-to-assign; post-MVP adds participant drag onto the plan.
- **Cook rota grid** — click cell → autocomplete input for shift codes.
## Non-goals (defer to v1.5+)
- Configurable widget mosaic dashboard
- Real-time websocket updates (polled refresh in v1)
- Per-user dashboard layout
- WhatsApp staff notifications (email + in-app only)
- HR / applicant tracking