132 lines
5.0 KiB
Markdown
132 lines
5.0 KiB
Markdown
# Public Surfaces — UI Design
|
|
|
|
Audience: prospective clients browsing for dates, returning organisers
|
|
checking the calendar, individual guests of a confirmed event filling in
|
|
their own dietary info via a tokenised link.
|
|
|
|
Theme: same Mantine tokens as admin/client/staff (dark surface, red
|
|
primary), but **lighter compositions** — more whitespace, larger
|
|
typography, hero-style sections. Public is read-only or single-form.
|
|
|
|
All public pages support an `?embed=1` query param that strips the
|
|
shell (header/footer) for WordPress iframe inclusion. Embedded pages
|
|
emit `postMessage('resize', { height })` so the WP iframe wrapper can
|
|
auto-fit content height.
|
|
|
|
DE default, EN toggle in the header. Browser locale auto-detected on
|
|
first visit; preference persisted.
|
|
|
|
## 1. Availability calendar — `/availability`
|
|
|
|
Replaces the public Google Sheet.
|
|
|
|
- 12 months ahead by default, horizontally scrollable
|
|
- Day cells coloured by status (token palette shared with admin):
|
|
- `free` — neutral pale
|
|
- `enquiry` — soft pink (semi-transparent)
|
|
- `reserved` — amber
|
|
- `confirmed` — green
|
|
- **Privacy:** event name visible on hover/tap **only** for bookings
|
|
with `online-ad=true` consent; all other booked days show status
|
|
only, never group name. (Q1 lock: "Status + opt-in event names")
|
|
- Click a `free` day → "Reserve this date" CTA → opens `/enquiry`
|
|
with that date pre-filled
|
|
- View toggle: month · quarter · year
|
|
- Year-header strip: occupancy %, free-day count
|
|
- Embeddable: `/availability?embed=1` returns just the grid
|
|
|
|
## 2. Events page — `/events`
|
|
|
|
Lists upcoming events whose organiser opted into public listing
|
|
(`online-ad=true`).
|
|
|
|
- Card per event:
|
|
- Cover image (organiser-uploaded, optional)
|
|
- Event name
|
|
- Dates
|
|
- Organiser name
|
|
- Short description (`course-info` form field)
|
|
- External link to organiser's website (`your-website`)
|
|
- Filter chips: This year · Next year · All
|
|
- Search (event name / organiser)
|
|
- SEO: server-rendered, meta tags, JSON-LD `Event` schema
|
|
- Empty state: "No events listed at this moment — please check our
|
|
retreat calendar for available dates."
|
|
- Cross-link to `/availability` in header
|
|
|
|
## 3. Booking form — `/enquiry`
|
|
|
|
The iframe-able binding booking form. Replaces the current WordPress
|
|
form long-term; short-term we accept WP webhook posts to the same
|
|
backend (Phase 1 of public-entry plan).
|
|
|
|
### Sections (all sticky on scroll)
|
|
|
|
1. **Your event** — name, description, website, dates, est. participants
|
|
2. **Organiser** — name, email, phone, full legal name, organisation
|
|
3. **Billing** — invoice address, payment preference (cash | transfer)
|
|
4. **Schedule** — desired arrival / departure times, structured meal
|
|
times (Frühstück / Mittag / Abend, validated against venue's
|
|
allowed-window config), free-text daily plan
|
|
5. **Extras** — cake / 2nd seminar room / early arrival / bedlinen /
|
|
massage bench (gross prices)
|
|
6. **Setup** — equipment needed (beamer, flipchart, piano, chair count)
|
|
7. **Public listing consent** — opt in to show on `/events`
|
|
8. **Terms** — AGB acceptance (versioned by event year), privacy
|
|
notice acceptance
|
|
|
|
### Behaviour
|
|
- Inline validation; submit failure highlights incomplete sections
|
|
- On submit:
|
|
- Status = `form_received` (per locked status enum)
|
|
- €300 deposit due notice within 14 days
|
|
- Auto confirmation email in user's locale (DE/EN)
|
|
- Embeddable: `/enquiry?embed=1`, postMessage height resize
|
|
|
|
## 4. Guest self-form — `/d/:token`
|
|
|
|
Tokenised link a guest receives from the organiser to fill in their
|
|
own dietary info — no account required.
|
|
|
|
- Single page: name (pre-filled, editable), dietary tag picker,
|
|
allergy list, free-text "anything else"
|
|
- Token expires when booking is `completed`
|
|
- DE/EN locale-aware, auto-detected from browser
|
|
- One-time submit with confirmation page; re-openable until cutoff
|
|
- Mobile-first (most guests fill from phones)
|
|
|
|
## 5. Authenticated landing — `/`
|
|
|
|
- Unauthenticated users → thin welcome page with links to
|
|
`/availability`, `/events`, sign-in CTA
|
|
- Authenticated users → role-based redirect to their portal
|
|
|
|
No marketing copy on the platform itself — Sarah keeps the WordPress
|
|
site as the brand front door.
|
|
|
|
## SEO and structured data
|
|
|
|
- `/availability` — meta description, no indexable detail
|
|
- `/events` — JSON-LD `Event` schema per event card; `<title>`
|
|
per-card on detail expansion if added later
|
|
- `/enquiry` — `noindex` (form, not content)
|
|
- `/d/:token` — `noindex` (private)
|
|
- `/` — minimal `<title>` and `og:` tags
|
|
|
|
## Components shared with the rest of the platform
|
|
|
|
- Status pill (theme tokens)
|
|
- Day-cell calendar component (admin calendar reuses, with edit
|
|
affordances)
|
|
- AGB / privacy acceptance component (also used in client portal
|
|
on first login)
|
|
- DE/EN locale toggle
|
|
|
|
## Non-goals
|
|
|
|
- No marketing copy / about / blog — handled by WordPress
|
|
- No public booking detail page (events page is summary-only; clients
|
|
see full detail in their portal once authenticated)
|
|
- No public reviews / testimonials in v1
|
|
- No payment processing (deposits are bank transfer, per §6)
|