Files
fotospiel-app/docs/prp/07-guest-pwa.md
2025-11-20 10:44:29 +01:00

134 lines
9.0 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 07 — Guest PWA
Goal
- Delight guests with a frictionless, installable photo experience that works offline, respects privacy, and requires no account.
Non-Goals (MVP)
- No comments or chat. No facial recognition. No public profiles. No videos.
Personas
- Guest (attendee) — scans QR, uploads photos, browses and likes.
- Host (tenant) — optionally shares event PIN with guests; moderates via Tenant Admin PWA.
Top Journeys
- Join: Scan QR → Open event → Accept terms → Optional PIN → Land on Gallery.
- Upload: Add photos → Review → Submit → Background upload → Success/Retry.
- Browse: Infinite gallery → Filter (emotion/task) → Open photo → Like/Share → Back.
Core Features
- Event access
- Access token embedded in QR/link (short-lived, event-scoped); optional PIN challenge.
- Token refresh if event remains open; server can revoke/close event at any time.
- Offline-first
- App shell + last N gallery items cached; uploads queued with Background Sync.
- Conflict-safe retries; user can pause/cancel queued uploads.
- Capture & upload
- Choose from camera or library; limit file size; show remaining upload cap.
- Client-side resize to sane max (e.g., 2560px longest edge); EXIF stripped client-side if available.
- Assign optional emotion/task before submit; default to “Uncategorized”.
- Upload screen shows quota cards (Photos, Guests) with traffic-light styling and friendly copy when nearing limits.
- When the backend blocks uploads (limit reached, device blocked, gallery expired), surface localized dialogs with actionable hints.
- Gallery
- Masonry grid, lazy-load, pull-to-refresh; open photo lightbox with swipe.
- Like (heart) with optimistic UI; share system sheet (URL to CDN variant).
- Filters: emotion, featured, mine (local-only tag for items uploaded from this device).
- Public share: host can hand out `https://app.domain/g/\{token\}`; guests see a themed, read-only gallery with per-photo downloads.
- Banner on gallery header highlights approaching expiry (D-7/D-1) and offers CTA to upload remaining shots before the deadline.
- Safety & abuse controls
- Rate limits per device and IP; content-length checks; mime/type sniffing.
- Upload moderation state: pending → approved/hidden; show local status.
- Notification Center
- Header bell opens a drawer that merges upload queue stats with server-driven notifications (photo highlights, major achievements, host broadcasts, upload failure hints, feedback reminders).
- Data fetched from `/api/v1/events/\{token\}/notifications` with `X-Device-Id` for per-device read receipts; guests can mark items as read/dismissed and follow CTAs (internal routes or external links).
- Pull-to-refresh + background poll every 90s to keep single-day events reactive without WS infrastructure.
- When push is available (VAPID keys configured) the drawer surfaces a push toggle, persists subscriptions via `/push-subscriptions`, and the service worker refreshes notifications after every push message.
- Operations playbook: see `docs/ops/guest-notification-ops.md` for enabling push, required queues, and cron health checks.
- Privacy & legal
- First run shows legal links (imprint/privacy); consent for push if enabled.
- No PII stored; guest name is optional free text and not required by default.
Screens
- Splash/Loading: event lookup + token validation; friendly skeleton.
- Slug-based deep links are no longer accepted; guests must enter or scan a join token QR.
- Terms & PIN: legal links, optional PIN input; remember choice per event.
- Gallery: grid of approved photos; toolbar with filter, upload, settings.
- Upload Picker: camera/library, selection preview, emotion/task tagging.
- Upload Queue: items with progress, retry, remove; background sync toggle.
- Photo Lightbox: zoom, like, share; show emotion tags.
- Settings Sheet: Gear-Icon im Header oeffnet eine Sheet-Ansicht mit editierbarem Gastnamen, eingebetteten Rechtsdokumenten (inkl. Zurueck-Navigation) und Cache-Leeren; Theme-Umschalter bleibt im Header.
Wireframes
- See wireframes file at docs/wireframes/guest-pwa.md for low-fidelity layouts and flows.
Core Pages (Pflichtseiten)
- Landing / Einstieg
- Purpose: Entry to event via QR/PIN; lowest friction.
- UI: Single input (QR deep link preferred, fallback PIN field) and Join button.
- States: invalid/expired token, event closed, offline (allow PIN entry and queue attempt).
- Profil-Setup (Name/Avatar)
- Purpose: Optional personalisation fuer Likes/Statistiken; Name wird lokal im Browser gespeichert.
- UI: Name-Feld mit Sofort-Validierung; Avatar folgt spaeter.
- Behavior: Nicht verpflichtend, aber empfohlen; Name kann jederzeit im Settings Sheet angepasst oder geloescht werden.
- Startseite (Home/Feed)
- Purpose: Central hub; begruesst Gaeste mit ihrem hinterlegten Namen und fuehrt zu den wichtigsten Aktionen.
- Header: Eventtitel plus Live-Kennzahlen (online Gaeste, geloeste Aufgaben); hero-card zeigt "Hey \{Name\}!".
- Highlights: Drei CTA-Karten fuer Aufgabe ziehen, Direkt-Upload und Galerie sowie ein Button fuer die Upload-Warteschlange.
- Content: EmotionPicker und GalleryPreview bilden weiterhin den Einstieg in Spielstimmung und aktuelle Fotos.
- Aufgaben-Flow
- Aufgaben-Picker: Choose random task or emotion mood.
- Aufgaben-Detail (Karte): Task text, emoji tag, estimated duration, suggested group size; actions: take photo, new task (same mood), change mood.
- Foto-Interaktion
- Kamera/Upload: Capture or pick; progress + success message on completion; background sync.
- Galerie/Übersicht: Grid/Feed; filters: Neueste, Beliebt, Meine; Like hearts.
- Foto-Detailansicht: Fullscreen; likes/reactions; linked task + (optional) uploader name.
- Motivation & Spiel
- Achievements/Erfolge: Badges (e.g., Erstes Foto, 5 Aufgaben, Beliebtestes Foto); personal progress.
- Optionale Ergänzungen
- Slideshow/Präsentationsmodus: Auto-rotating gallery for TV/Beamer with likes/task overlay.
- Onboarding: 1–2 “So funktioniert das Spiel” hints the first time.
- Event-Abschluss: “Danke fürs Mitmachen”, summary stats, link/QR to online gallery.
Technical Notes
- Installability: PWA manifest + service worker; prompt A2HS on supported browsers.
- Storage: IndexedDB for queue + cache; `CacheStorage` for shell/assets.
- Background Sync: use Background Sync API when available; fallback to retry on app open.
- Accessibility: large tap targets, high contrast, keyboard support, reduced motion.
- i18n: react-i18next with JSON files (`public/lang/\{locale\}/guest.json`); default `de`, fallback `en`; path-based detection (/de/, /en/); RTL not in MVP. Strings for UI (e.g., gallery, upload, tasks) extracted via i18next-scanner; integrate with prefixed routing and middleware.
- Media types: Photos only (no videos) — decision locked for MVP and v1.
- Realtime model: periodic polling (no WebSockets). Home counters every 10s; gallery delta every 30s with exponential backoff when tab hidden or offline.
API Touchpoints
- GET `/api/v1/events/\{token\}` — public event metadata (when open) + theme.
- GET `/api/v1/events/\{token\}/photos` — paginated gallery (approved only).
- POST `/api/v1/events/\{token\}/photos` — signed upload initiation; returns URL + fields.
- POST (S3) — direct upload to object storage; then backend finalize call.
- POST `/api/v1/photos/\{id\}/like` — idempotent like with device token.
- GET `/api/v1/events/\{token\}/notifications` — list guest notifications (requires `X-Device-Id`).
- POST `/api/v1/events/\{token\}/notifications/\{notification\}/read|dismiss` — mark/dismiss notification with device identity.
- POST `/api/v1/events/\{token\}/push-subscriptions` — register a browser push subscription (requires `X-Device-Id` + VAPID public key).
- DELETE `/api/v1/events/\{token\}/push-subscriptions` — revoke a stored push subscription by endpoint.
Limits (MVP defaults)
- Max uploads per device per event: 50
- Max file size (after client resize): 6 MB per photo
- Max resolution: 2560px longest edge per photo
Edge Cases
- Token expired/invalid → Show “Event closed/invalid link”; link to retry.
- No connectivity → Queue actions; show badge; retry policy with backoff.
- Storage full → Offer to clear cache or deselect files.
- Permission denied (camera/photos) → Explain and offer system shortcut.
Decisions
- Videos are not supported (capture/upload strictly photos).
Appendix: Page-to-Feature Mapping
- Landing: Access, validation, join; deep-link handling.
- Profile Setup: Local profile persistence; optional avatar assets.
- Home: Header, info bar, CTAs, feed preview.
- Tasks: Picker (random/emotion), detail card actions.
- Capture/Upload: Camera permissions, client resize, queue handling.
- Gallery: Filters, pagination, lightbox.
- Achievements: Local badges (MVP), server-backed later.
- Slideshow (optional): Read-only, auto-advance, idle-safe.