256 lines
11 KiB
Markdown
256 lines
11 KiB
Markdown
# 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 3–10 / 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
|