Files
fotospiel-app/docs/prp/07-guest-pwa.md
Codex Agent 64a5411fb9 - Reworked the tenant admin login page
- Updated the User model to implement Filament’s tenancy contracts
- Seeded a ready-to-use demo tenant (user, tenant, active package, purchase)
- Introduced a branded, translated 403 error page to replace the generic forbidden message for unauthorised admin hits
- Removed the public “Register” links from the marketing header
- hardened join event logic and improved error handling in the guest pwa.
2025-10-13 12:50:46 +02:00

119 lines
7.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”.
- 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).
- Safety & abuse controls
- Rate limits per device and IP; content-length checks; mime/type sniffing.
- Upload moderation state: pending → approved/hidden; show local status.
- 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.
- 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.
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.