chore: seminarhof customer project
This commit is contained in:
131
docs/design/public.md
Normal file
131
docs/design/public.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user