further rework to the documentation
This commit is contained in:
50
docs/archive/prp/tenant-app-specs/README.md
Normal file
50
docs/archive/prp/tenant-app-specs/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Detaillierte PRP für Tenant Admin App (Capacitor + Framework7)
|
||||
|
||||
## Status
|
||||
- **Aktualisiert**: 2025-10-17 (Onboarding Fusion & QR Revamp)
|
||||
- **Version**: 1.2.0
|
||||
- **Autor**: Core Platform Team (Codex)
|
||||
- **Supersedes**: docs/prp/06-tenant-admin-pwa.md (legacy Framework7 reference)
|
||||
|
||||
## Überblick
|
||||
Diese detaillierte Product Requirement Plan (PRP) beschreibt die Spezifikationen für die Tenant Admin App. Die App ist eine store-ready mobile Anwendung, die mit Capacitor für iOS und Trusted Web Activity (TWA) für Android gepackt wird. Die UI basiert auf Framework7 für ein natives Mobile-Erlebnis. Die App ermöglicht Tenant-Admins (z.B. Event-Organisatoren) die vollständige Verwaltung ihrer Events, Galerien, Mitglieder, Einstellungen und Käufe über eine API-first Backend-Integration.
|
||||
|
||||
Die App ersetzt das frühere Filament-basierte Tenant-Panel und fokussiert auf eine Mobile-First-UX mit Offline-Fähigkeiten, Push-Notifications und sicherer Authentifizierung. Sie respektiert das Multi-Tenancy-Modell und GDPR-Anforderungen. Seit Oktober 2025 wird das UI in React 19 + Vite + Tailwind/shadcn/ui umgesetzt; die alte Framework7-Schicht bleibt nur als historische Referenz erhalten.
|
||||
|
||||
## Aktuelle Highlights (Q4 2025)
|
||||
- **Geführtes Onboarding**: `/event-admin/welcome/*` orchestriert den Welcome Flow (Hero → How-It-Works → Paketwahl → Zusammenfassung → Event Setup). Guarding erfolgt über `onboarding_completed_at`.
|
||||
- **Direkter Checkout**: Paddle sind in die Paketwahl des Welcome Flows eingebettet; Fortschritt wird im Onboarding-Context persistiert.
|
||||
- **Filament Wizard**: Für Super-Admins existiert ein paralleler QR/Join-Token-Wizard in Filament (Token-Generierung, Layout-Downloads, Rotation).
|
||||
- **Join Tokens only**: Gäste erhalten ausschließlich join-token-basierte Links/QRs; slug-basierte URLs wurden deaktiviert. QR-Drucklayouts liegen unter `resources/views/pdf/join-tokens/*`.
|
||||
- **Auth Alignment**: Sanctum-PATs über `/api/v1/tenant-auth/login` + `/tenant-auth/exchange`; siehe `docs/prp/tenant-app-specs/api-usage.md`.
|
||||
|
||||
## Kernziele
|
||||
- **Deliverables**: Voll funktionsfähige App mit CRUD-Operationen für Tenant-Ressourcen (Events, Photos, Tasks, etc.).
|
||||
- **UI/UX**: Framework7-Komponenten für konsistente, native Mobile-Interfaces (iOS/Android).
|
||||
- **Technologie-Stack**: React/Vite (Core), Framework7 (UI), Capacitor (Native), Sanctum PATs (Auth).
|
||||
- **Distribution**: App Store (iOS), Google Play (Android), PWA-Install (Web).
|
||||
|
||||
## Struktur dieser PRP
|
||||
- **README.md**: Dieser Überblick.
|
||||
- **functional-specs.md**: Funktionale Anforderungen, Capabilities und API-Integration.
|
||||
- **pages-ui.md**: Detaillierte Seitenbeschreibungen, Framework7-Komponenten und Wireframe-Ideen.
|
||||
- **settings-config.md**: App- und Tenant-spezifische Einstellungen, Capacitor-Plugins.
|
||||
- **capacitor-setup.md**: Packaging, Distribution und Native-Features.
|
||||
|
||||
## Referenzen
|
||||
- **Haupt-PRP**: docs/prp/README.md
|
||||
- **Tenancy**: docs/prp/02-tenancy.md
|
||||
- **API**: docs/prp/03-api.md
|
||||
- **Bestehende Tenant PWA**: docs/prp/06-tenant-admin-pwa.md
|
||||
- **Addendum**: docs/prp-addendum-2025-09-08-tenant-admin-pwa.md
|
||||
- **ADR**: docs/adr/ADR-0006-tenant-admin-pwa.md
|
||||
- **Billing**: docs/prp/08-billing.md
|
||||
- **Glossar**: docs/prp/99-glossary.md
|
||||
|
||||
## Änderungen und Erweiterungen
|
||||
Diese PRP erweitert die knappe Beschreibung in 06-tenant-admin-pwa.md um:
|
||||
- Spezifische Seiten und UI-Elemente mit Framework7.
|
||||
- Detaillierte Settings und Capacitor-Integration.
|
||||
- Mobile-spezifische Features wie Push-Notifications und Offline-Sync.
|
||||
|
||||
Für Feedback oder Änderungen: Siehe TODO.md oder Issues.
|
||||
278
docs/archive/prp/tenant-app-specs/api-usage.md
Normal file
278
docs/archive/prp/tenant-app-specs/api-usage.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# API-Nutzung der Tenant Admin App
|
||||
|
||||
Diese Dokumentation beschreibt alle API-Endpunkte der Tenant Admin App. Alle Requests sind tenant-scoped und erfordern ein Sanctum Personal Access Token (PAT) mit der Fähigkeit `tenant-admin` bzw. `tenant:\{id\}`.
|
||||
|
||||
## Authentifizierung
|
||||
|
||||
### Passwort-Login (PAT)
|
||||
- **Endpoint**: `POST /api/v1/tenant-auth/login`
|
||||
- **Body** (`application/json`): `{ "login": "username oder email", "password": "••••" }`
|
||||
- **Response**: `{ token, token_type, abilities[], user { ... } }`
|
||||
- **Fehler**: `422` bei ungültigen Daten, `429` bei Rate-Limit (`throttle:tenant-auth`).
|
||||
- **Hinweis**: `login` akzeptiert E-Mail _oder_ Usernamen. Erfolgreiche Logins revoken vorhandene PATs mit Name `tenant-admin`.
|
||||
|
||||
### Session→PAT Exchange (Google/Login-Shell)
|
||||
- **Endpoint**: `POST /api/v1/tenant-auth/exchange`
|
||||
- **Middleware**: Sanctum stateful cookies (`SANCTUM_STATEFUL_DOMAINS`), `throttle:tenant-auth`.
|
||||
- **Use-Case**: Nach Google-Login oder Marketing-Checkout Session wird das PAT ohne erneute Passwort-Eingabe ausgegeben.
|
||||
- **Response**: identisch zum Passwort-Login.
|
||||
|
||||
### Token Status & Logout
|
||||
- **`GET /api/v1/tenant-auth/me`** – liefert `{ user, tenant, abilities }` und spiegelt die PAT-Fähigkeiten wider.
|
||||
- **`POST /api/v1/tenant-auth/logout`** – löscht das aktuelle PAT aus `personal_access_tokens`.
|
||||
|
||||
### Legacy Payload `/tenant/me`
|
||||
- **Endpoint**: `GET /api/v1/tenant/me`
|
||||
- **Response**: historisches Format (`tenant_id`, `remaining_events`, `scopes`), betrieben über denselben PAT.
|
||||
- **Kompatibilität**: Dient älteren Clients als Übergang; neue Features sollten `/tenant-auth/me` verwenden.
|
||||
|
||||
## Dashboard
|
||||
|
||||
### Stats laden
|
||||
- **GET /api/v1/tenant/dashboard**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Response**: `{ active_package, active_events, new_photos, task_progress }`
|
||||
- **Zweck**: Übersicht-Daten für Dashboard-Cards (active_package: current tenant package info)
|
||||
|
||||
## Events
|
||||
|
||||
### Events-Liste
|
||||
- **GET /api/v1/tenant/events**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Params**:
|
||||
- `page=1` (Pagination)
|
||||
- `per_page=50` (max für Mobile)
|
||||
- `status=draft|active|archived` (Filter)
|
||||
- `search=query` (Suche in Titel/Ort)
|
||||
- **Response**: `{ data: Event[], current_page, last_page, total }`
|
||||
- **Event-Shape**: `{ id, title, date, location, status, photoCount, slug }`
|
||||
|
||||
### Event erstellen
|
||||
- **POST /api/v1/tenant/events**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ title, date, location, description, package_id }`
|
||||
- **Response**: 201 Created mit erstelltem Event
|
||||
- **Validierung**: Prüft Tenant-Package (Reseller-Limit) und erstellt Event-Package (Einmalkauf oder Free)
|
||||
|
||||
### Event-Details
|
||||
- **GET /api/v1/tenant/events/\{slug\}**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Response**: Erweitertes Event mit `{ tasks[], members, stats { likes, views, uploads } }`
|
||||
|
||||
### Event updaten
|
||||
- **PATCH /api/v1/tenant/events/\{slug\}**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`, `If-Match: \{etag\}`
|
||||
- **Body**: Partial Event-Daten (title, date, location, description)
|
||||
- **Response**: Updated Event
|
||||
|
||||
### Event archivieren
|
||||
- **DELETE /api/v1/tenant/events/\{slug\}**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `If-Match: \{etag\}`
|
||||
- **Response**: 204 No Content (soft-delete)
|
||||
|
||||
## Photos
|
||||
|
||||
### Photos laden
|
||||
- **GET /api/v1/tenant/events/\{event_id\}/photos**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Params**:
|
||||
- `page=1`, `per_page=50`
|
||||
- `status=pending|approved|rejected|featured`
|
||||
- `sort=date|likes`
|
||||
- `since=cursor` (für Infinite Scroll)
|
||||
- **Response**: `{ data: Photo[], current_page, last_page }`
|
||||
- **Photo-Shape**: `{ id, eventId, url, thumbnail, uploadedAt, status, likes, views, uploader, etag }`
|
||||
|
||||
### Upload-URL anfordern
|
||||
- **POST /api/v1/tenant/events/\{event_id\}/photos**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ file_name, description? }`
|
||||
- **Response**: `{ id, upload_url (S3 signed), thumbnail_url }`
|
||||
|
||||
### Photo moderieren
|
||||
- **PATCH /api/v1/tenant/photos/\{id\}**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`, `If-Match: \{etag\}`
|
||||
- **Body**: `{ status: 'approved'|'rejected'|'featured', featured?, reason? }`
|
||||
- **Response**: Updated Photo
|
||||
|
||||
### Photo löschen
|
||||
- **DELETE /api/v1/tenant/photos/\{id\}**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `If-Match: \{etag\}`
|
||||
- **Response**: 204 No Content
|
||||
|
||||
## Members
|
||||
|
||||
### Mitglieder laden
|
||||
- **GET /api/v1/tenant/events/\{event_id\}/members**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Params**: `page`, `per_page`, `status=pending|active|invited`
|
||||
- **Response**: `{ data: Member[], current_page, last_page }`
|
||||
- **Member-Shape**: `{ id, name, email, role, joinedAt, avatar?, status }`
|
||||
|
||||
### Mitglied einladen
|
||||
- **POST /api/v1/tenant/events/\{event_id\}/members**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ email, role: 'member'|'guest', name? }`
|
||||
- **Response**: 201 Created, E-Mail wird versendet
|
||||
|
||||
## Tasks
|
||||
|
||||
### Tasks laden
|
||||
- **GET /api/v1/tasks**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Params**:
|
||||
- `global=true/false` (globale vs. tenant Tasks)
|
||||
- `tenant_id=me` (nur eigene Tasks)
|
||||
- `category=setup|photo|event|cleanup`
|
||||
- **Response**: `{ data: Task[], global: boolean }`
|
||||
- **Task-Shape**: `{ id, title, description?, category, isGlobal, tenantId?, createdAt, color? }`
|
||||
|
||||
### Event-Tasks laden
|
||||
- **GET /api/v1/tenant/events/\{event_id\}/tasks**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Response**: `{ data: EventTask[], overall_progress }`
|
||||
- **EventTask-Shape**: `{ id, eventId, taskId, task: Task, order, completed, assignedTo?, progress }`
|
||||
|
||||
### Tasks bulk zuweisen
|
||||
- **POST /api/v1/tenant/events/\{event_id\}/tasks/bulk**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ task_ids: string[], order: number[] }`
|
||||
- **Response**: Updated EventTasks mit neuer Reihenfolge
|
||||
|
||||
## Settings
|
||||
|
||||
### Settings laden
|
||||
- **GET /api/v1/tenant/settings**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Response**: `{ primaryColor, tenantName, maxEventsPerMonth, enableTasks, enableEmotions, legalPages { impressumUrl, privacyUrl } }`
|
||||
|
||||
### Settings updaten
|
||||
- **PATCH /api/v1/tenant/settings**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: Partial Settings-Daten
|
||||
- **Response**: Updated Settings
|
||||
|
||||
## Billing
|
||||
|
||||
### Balance laden
|
||||
- **GET /api/v1/tenant/credits/balance**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Response**: `{ balance: number }`
|
||||
|
||||
### Ledger-Verlauf
|
||||
- **GET /api/v1/tenant/credits/ledger**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`
|
||||
- **Params**: `page`, `per_page` (Pagination)
|
||||
- **Response**: `{ data: LedgerEntry[], current_page, last_page }`
|
||||
- **LedgerEntry**: `{ id, type, amount, credits, date, description, transactionId? }`
|
||||
|
||||
### Credits kaufen (In-App)
|
||||
- **POST /api/v1/tenant/credits/purchase**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ package_id: string, credits_added: number, platform?: 'capacitor'|'web', transaction_id?: string, subscription_active?: boolean }`
|
||||
- **Response**: `{ message, balance, subscription_active }`
|
||||
- **Hinweis**: Wird nach erfolgreichen In-App-Kuferfolgen aufgerufen, aktualisiert Balance & Ledger.
|
||||
|
||||
### Credits synchronisieren
|
||||
- **POST /api/v1/tenant/credits/sync**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ balance: number, subscription_active: boolean, last_sync: ISODateString }`
|
||||
- **Response**: `{ balance, subscription_active, server_time }`
|
||||
- **Hinweis**: Client meldet lokalen Stand; Server gibt Quelle-der-Wahrheit zurcck.
|
||||
|
||||
### Kauf-Intent erstellen
|
||||
- **POST /api/v1/tenant/purchases/intent**
|
||||
- **Headers**: `Authorization: Bearer \{token\}`, `Content-Type: application/json`
|
||||
- **Body**: `{ package_id }`
|
||||
- **Response**: `{ checkout_url: string }` (Stripe-Checkout)
|
||||
- **Nach dem Kauf**: Webhook-Handling auf Backend für Balance-Update
|
||||
|
||||
## Allgemeine Headers
|
||||
|
||||
Alle API-Requests enthalten:
|
||||
- **Authorization**: `Bearer \{access_token\}` (Sanctum PAT mit Fähigkeit `tenant:\{id\}`)
|
||||
- **Content-Type**: `application/json` (für POST/PATCH)
|
||||
- **If-Match**: `\{etag\}` (für Concurrency-Control bei Updates)
|
||||
- **Accept**: `application/json`
|
||||
|
||||
## Error-Handling
|
||||
|
||||
**Standard-Error-Response:**
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "PACKAGE_LIMIT_EXCEEDED",
|
||||
"message": "Package-Limit überschritten (z.B. max_photos)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**HTTP Status Codes:**
|
||||
- 200: Erfolg
|
||||
- 201: Created
|
||||
- 400: Bad Request (Validierungsfehler)
|
||||
- 401: Unauthorized (Token-Refresh wird versucht)
|
||||
- 403: Forbidden (RBAC-Verletzung)
|
||||
- 404: Not Found
|
||||
- 422: Unprocessable Entity
|
||||
- 429: Rate Limited (Client retry mit Backoff)
|
||||
|
||||
## Pagination
|
||||
|
||||
Alle Listen-Endpunkte unterstützen:
|
||||
- **page**: Aktuelle Seite (default 1)
|
||||
- **per_page**: Einträge pro Seite (default 20, max 50 für Mobile)
|
||||
- **Response**: `{ data: [], current_page, last_page, per_page, total }`
|
||||
|
||||
## Headers für Concurrency
|
||||
|
||||
Mutierende Endpunkte (PATCH/DELETE) erfordern:
|
||||
- **If-Match**: `\{etag\}` aus GET-Response
|
||||
- **Response**: 412 Precondition Failed bei Conflict
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- **Tenant-Isolation**: Middleware vergleicht PAT-Fähigkeit (`tenant:\{id\}`) mit dem angefragten Tenant
|
||||
- **RBAC**: Nur tenant_admin kann mutieren, member kann nur lesen/hochladen
|
||||
- **Rate Limiting**: 100 Requests/Minute pro Tenant
|
||||
- **ETag**: Automatische Concurrency-Control
|
||||
- **No PII-Logging**: Keine sensiblen Daten in Logs
|
||||
|
||||
## Testing
|
||||
|
||||
### API-Test-Setup
|
||||
1. **Backend starten**: Stelle sicher, dass die Hauptapp läuft und Endpunkte verfügbar sind.
|
||||
2. **Token erzeugen**: Verwende Postman mit gültigem Access-Token.
|
||||
3. **Endpoints testen**: Jeder Endpunkt einzeln mit curl oder Postman.
|
||||
|
||||
### Beispiel curl (mit Token)
|
||||
```bash
|
||||
curl -H "Authorization: Bearer \{token\}" \
|
||||
-H "Content-Type: application/json" \
|
||||
https://api.fotospiel.com/api/v1/tenant/events
|
||||
```
|
||||
|
||||
### Frontend-Test
|
||||
1. `.env` mit korrekter API-URL konfigurieren.
|
||||
2. `npm run dev` starten.
|
||||
3. Browser-Network-Tab überprüfen für API-Calls.
|
||||
|
||||
## Deployment
|
||||
|
||||
### Environment-Variablen
|
||||
- **VITE_API_URL**: Backend-API-URL (Pflicht)
|
||||
- **VITE_ENABLE_TENANT_SWITCHER**: Dev-Flag um Tenants im Header auszuwählen (optional, Default `false`)
|
||||
- **VITE_REVENUECAT_PUBLIC_KEY**: Optional für In-App-Käufe (RevenueCat)
|
||||
- **SANCTUM_STATEFUL_DOMAINS** (Backend): Enthält die Origins des Admin-PWA/TWA, damit der Session→PAT-Exchange funktioniert.
|
||||
- **REVENUECAT_WEBHOOK_SECRET / REVENUECAT_PRODUCT_MAPPINGS / REVENUECAT_APP_USER_PREFIX / REVENUECAT_WEBHOOK_QUEUE**: Backend-Konfiguration für RevenueCat-Webhooks, siehe `config/services.php`.
|
||||
|
||||
### Build & Deploy
|
||||
1. **Development**: `npm run dev`
|
||||
2. **Production**: `npm run build`
|
||||
3. **Vorschau**: `npm run preview`
|
||||
|
||||
### PWA-Installation
|
||||
- App ist PWA-fähig (Manifest, Service Worker).
|
||||
- Installierbar auf Desktop/Mobile via "Zum Startbildschirm hinzufügen".
|
||||
|
||||
Für weitere Details siehe die spezifischen Dokumentationsdateien.
|
||||
155
docs/archive/prp/tenant-app-specs/capacitor-setup.md
Normal file
155
docs/archive/prp/tenant-app-specs/capacitor-setup.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Capacitor Setup für die Tenant Admin App
|
||||
|
||||
## Status
|
||||
- **Version**: 1.0.0 (2025-09-13)
|
||||
- **Fokus**: Mobile Packaging, Distribution und Native-Integration basierend auf ADR-0006.
|
||||
|
||||
## Überblick
|
||||
Die Tenant Admin App wird als Progressive Web App (PWA) entwickelt und mit Capacitor für native Mobile-Distribution gepackt. Dies ermöglicht:
|
||||
- **Android**: Trusted Web Activity (TWA) für Chrome-basierte Installation (Google Play) oder voller Capacitor-Build bei Bedarf an Native APIs.
|
||||
- **iOS**: Capacitor-App für App Store-Distribution mit Push-Notifications und Keychain-Support.
|
||||
- **Web/PWA**: Fallback für Browser-Installation (A2HS) mit Service Worker.
|
||||
|
||||
Der Build-Prozess integriert sich in das bestehende Vite-Setup (resources/js/admin). Nach `npm run build` wird `npx cap sync` ausgeführt, um die Web-Assets in native Projekte zu kopieren.
|
||||
|
||||
## Projektstruktur
|
||||
```
|
||||
apps/admin-pwa/ # React/Vite Source (Haupt-App)
|
||||
├── src/ # Components, Pages, API
|
||||
├── vite.config.ts # Framework7 + Capacitor-Integration
|
||||
├── capacitor.config.ts # Native Config
|
||||
├── android/ # Capacitor Android-Projekt (TWA oder App)
|
||||
├── ios/ # Capacitor iOS-Projekt (Xcode)
|
||||
└── package.json # Dependencies (framework7, @capacitor/*)
|
||||
|
||||
packages/mobile/ # Shared Native-Config (optional)
|
||||
├── fastlane/ # iOS/Android Deployment
|
||||
├── assetlinks.json # TWA Digital Asset Links
|
||||
└── privacy-manifest.json # iOS Privacy
|
||||
```
|
||||
|
||||
## Packaging und Build-Prozess
|
||||
|
||||
### 1. Vite + Framework7 Setup
|
||||
- **Dependencies**: `framework7`, `framework7-react`, `@capacitor/core`, `@capacitor/cli`.
|
||||
- **vite.config.ts** (Auszug):
|
||||
```typescript
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { framework7 } from 'framework7/vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), framework7()],
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: true,
|
||||
},
|
||||
define: {
|
||||
__CAPACITOR__: true, // Enable Capacitor globals
|
||||
},
|
||||
});
|
||||
```
|
||||
- **Build-Skript** (package.json): `"build": "vite build && npx cap sync"`.
|
||||
|
||||
### 2. Capacitor Initialisierung
|
||||
- **Befehle**:
|
||||
```
|
||||
npx cap init com.fotospiel.tenantadmin "Event Photo Admin"
|
||||
npx cap add android
|
||||
npx cap add ios
|
||||
npx cap sync # Kopiert dist/ in native Projekte
|
||||
```
|
||||
- **capacitor.config.ts** (siehe settings-config.md für erweiterte Plugins).
|
||||
|
||||
### 3. Android Packaging (TWA bevorzugt)
|
||||
- **Trusted Web Activity (TWA)**: Für store-ready Distribution ohne vollen Native-Wrapper.
|
||||
- **Voraussetzungen**: App bound an `admin.fotospiel.app` (HTTPS); Digital Asset Links.
|
||||
- **assetlinks.json** (public/.well-known/assetlinks.json):
|
||||
```json
|
||||
[{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "com.fotospiel.tenantadmin",
|
||||
"sha256_cert_fingerprints": ["DE:AD:BE:EF:..."] // Von Play Console
|
||||
}
|
||||
}]
|
||||
```
|
||||
- **Build**: `npx cap open android` → Android Studio → Generate Signed Bundle (AAB für Play Store).
|
||||
- **Vorteile**: Kleiner Footprint, Web-Push via Chrome; Fallback zu Capacitor bei Bedarf (z.B. Biometrie).
|
||||
- **TWA-Tools**: `npm i -g @bubblewrap/cli` → `bubblewrap init --manifest=https://admin.fotospiel.app/manifest.json`.
|
||||
|
||||
- **Vollständiger Capacitor-Build** (falls Native-Plugins benötigt):
|
||||
- `npx cap sync android`
|
||||
- `npx cap open android` → Build APK/AAB mit ProGuard.
|
||||
|
||||
### 4. iOS Packaging (Capacitor)
|
||||
- **Xcode-Setup**: `npx cap open ios` → Signing mit Apple Developer Account.
|
||||
- **Privacy Manifest** (ios/App/App/PrivacyInfo.xcprivacy):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string> <!-- Preferences für Settings -->
|
||||
</array>
|
||||
</dict>
|
||||
<!-- Push, Camera, etc. -->
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
- **Build**: Archive in Xcode → Upload zu App Store Connect.
|
||||
- **Entitlements**: Push-Notifications (APNs), Background App Refresh für Sync.
|
||||
|
||||
### 5. Distribution und CI/CD
|
||||
- **Google Play**:
|
||||
- **TWA**: Internal Testing Track; Target SDK 34+; Feature: Installable.
|
||||
- **Fastlane**: `packages/mobile/fastlane/android` mit `supply` für Metadata/Screenshots.
|
||||
- **Versioning**: Align mit Backend (z.B. 1.0.0); Feature Flags via API.
|
||||
|
||||
- **Apple App Store**:
|
||||
- **Capacitor**: Review-Guidelines beachten (HTTPS-only, No Crash-Reporting ohne Consent).
|
||||
- **Fastlane**: `packages/mobile/fastlane/ios` mit `deliver` für Upload.
|
||||
- **Privacy**: Usage Descriptions in Info.plist (z.B. "Kamera für QR-Scans").
|
||||
|
||||
- **PWA-Fallback** (Web):
|
||||
- **manifest.json**: liegt unter `public/manifest.json` (Scope `/event-admin/`, Theme-Farbe `#f43f5e`, Shortcuts für Welcome & Dashboard).
|
||||
- **Service Worker**: `public/admin-sw.js` cached Shell + Assets, liefert Offline-Fallback `/event-admin` für Navigations-Anfragen.
|
||||
- **Distribution**: Hosting auf `admin.fotospiel.app` mit A2HS-Prompt; Bubblewrap/TWA nutzt `https://admin.fotospiel.app/manifest.json`.
|
||||
|
||||
### Native Features (Erweiterung zu settings-config.md)
|
||||
- **Push-Notifications**:
|
||||
- **Android**: FCM-Integration; Token an Backend (`POST /tenant/push-tokens`).
|
||||
- **iOS**: APNs; Silent-Pushes für Sync-Triggers.
|
||||
- **Cross-Platform**: Capacitor Push-Plugin handhabt Plattform-Unterschiede.
|
||||
|
||||
- **Secure Storage**:
|
||||
- **Tokens**: Capacitor Preferences mit Auto-Encryption.
|
||||
- **Offline Data**: IndexedDB (Web) + Native Storage; Encryption via Web Crypto API.
|
||||
|
||||
- **Background Processing**:
|
||||
- **Sync**: Capacitor App-State-Listener für Foreground/Background; Queue Mutations.
|
||||
- **iOS**: Background Fetch (via Plugin); Android: WorkManager für periodische Syncs.
|
||||
|
||||
- **Biometrie (optional)**: `@capacitor-community/biometric-auth` für App-Lock.
|
||||
|
||||
### Testing und Deployment
|
||||
- **E2E-Tests**: Cypress für Web; Detox/Appium für Native (z.B. Push-Handling).
|
||||
- **CI/CD**: GitHub Actions oder Gogs-Integration (siehe docs/prp/11-ops-ci-cd.md).
|
||||
- Steps: Build → Test → Cap Sync → Fastlane Deploy (Staging → Production).
|
||||
- **Version Alignment**: App-Version matcht Backend-API-Version; Changelog in Store-Listing.
|
||||
|
||||
### Constraints & Red-Lines
|
||||
- **GDPR**: Keine implizite Tracking; Explizite Consent für Push/Camera.
|
||||
- **Security**: HTTPS-only; Token-Rotation alle 24h; No Jailbreak-Detection.
|
||||
- **Performance**: Bundle-Size < 10MB (Web-Assets komprimiert); Lazy-Loading.
|
||||
|
||||
Diese Setup ergänzt die funktionalen Specs und UI-Beschreibungen. Für Repo-Integration siehe ADR-0006.
|
||||
89
docs/archive/prp/tenant-app-specs/functional-specs.md
Normal file
89
docs/archive/prp/tenant-app-specs/functional-specs.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Funktionale Spezifikationen – Tenant-Admin-App
|
||||
|
||||
## Status
|
||||
- **Version**: 1.1.0 (Stand 2025-10-13)
|
||||
- **Ersetzt**: docs/prp/06-tenant-admin-pwa.md, docs/prp-addendum-2025-09-08-tenant-admin-pwa.md (Legacy-Referenz über Git History).
|
||||
|
||||
## Deliverables
|
||||
Die Admin-App muss folgende Kernfunktionen bereitstellen:
|
||||
- **Geführtes Onboarding**: Welcome Flow (Hero, How-It-Works, Paketwahl, Zusammenfassung, Erstes Event). Automatische Weiterleitung für Tenants ohne aktive Events.
|
||||
- **Event-Management**: Erstellen, Bearbeiten, Veröffentlichen, Archivieren; Join-Token-Verwaltung.
|
||||
- **Galerie-Management**: Upload, Moderation, Feature-Flags, Analytics.
|
||||
- **Mitglieder-Verwaltung**: Einladungen, Rollen, Zugriffskontrolle.
|
||||
- **Tasks & Emotions**: Bibliothek, Zuweisung, Fortschritts-Tracking.
|
||||
- **Abrechnung**: Paketübersicht, Paddle Checkout, Ledger.
|
||||
- **Einstellungen**: Branding, Limits, Rechtstexte, Benachrichtigungen.
|
||||
- **Offline-Support**: App-Shell-Caching, Queueing von Mutationen, Sync bei Reconnect.
|
||||
- **Compliance**: Audit-Logging, GDPR-konforme Löschung, ETag-basierte Konfliktlösung.
|
||||
|
||||
## Capabilities
|
||||
### Authentifizierung & Autorisierung
|
||||
- Sanctum Personal Access Tokens (`/api/v1/tenant-auth/login|exchange`) mit Fähigkeiten `tenant-admin`, `tenant:{id}`; Speicherung in IndexedDB sowie Keychain/Keystore für Capacitor.
|
||||
- Rollenbasierte Fähigkeiten: `tenant_admin` (vollständig), `member` (read-only, Upload). Token-Exchange nach Google-Login oder Session-Login via `/tenant-auth/exchange`.
|
||||
|
||||
### Onboarding Journey
|
||||
- Routen `/event-admin/welcome/*` bilden den Flow.
|
||||
- Filament stellt einen korrespondierenden Onboarding-Wizard (QR/Join-Token, Layout-Download) bereit; Abschluss setzt `onboarding_completed_at` serverseitig.
|
||||
- `useOnboardingProgress` persistiert Fortschritt (localStorage) und synchronisiert mit Backend (`onboarding_completed_at`).
|
||||
- Paketwahl nutzt `GET /tenant/packages`; Paddle-Fallbacks informieren bei fehlender Konfiguration.
|
||||
- Dashboard weist per CTA auf offenes Onboarding hin, bis ein erstes Event erstellt wurde.
|
||||
|
||||
### Event Lifecycle
|
||||
- Erstellung prüft Paketverfügbarkeit; generiert Join-Token (EventJoinToken-Service).
|
||||
- QR-Layouts und Token-Rotation erfolgen über `/event-admin/welcome` bzw. das Filament-Panel; slug-basierte QR-Links wurden deaktiviert.
|
||||
- Bearbeiten erlaubt Statuswechsel, Aufgaben, Emotions, Join-Token-Verwaltung.
|
||||
- Veröffentlichen schaltet Guest-PWA frei; Archivieren respektiert Retention-Policy.
|
||||
|
||||
### Medien & Moderation
|
||||
- Direktupload via signed URLs, Thumbnail-Generierung serverseitig.
|
||||
- Moderations-Grid mit Bulk-Aktionen, Filter (Neu, Genehmigt, Featured).
|
||||
- Analytics: Likes, Uploadzahlen, aktive Gäste.
|
||||
|
||||
### Tasks & Emotions
|
||||
- Globale + Tenant-spezifische Bibliothek.
|
||||
- Drag-and-Drop Zuweisung, Fortschritt je Event, Emotion-Tagging.
|
||||
|
||||
### Billing & Checkout
|
||||
- Pakete + Credit-Balance anzeigen.
|
||||
- Stripe PaymentIntent & Paddle Smart Buttons; Fallback-Meldung bei fehlender Konfiguration.
|
||||
- Ledger mit Historie (Paginierung, Filter).
|
||||
|
||||
### Settings
|
||||
- Branding (Logo, Farben), Domain/Links, Legal Pages.
|
||||
- Notification Preferences, Paketlimits, Onboarding-Reset.
|
||||
|
||||
### Offline & Sync
|
||||
- Service Worker `public/admin-sw.js` cached App-Shell `/event-admin` und statische Assets, liefert Offline-Fallback für Navigation.
|
||||
- Mutationen werden gequeued und nach Reconnect synchronisiert.
|
||||
- ETag / If-Match für konfliktfreie Updates, Optimistic UI mit Rollback.
|
||||
|
||||
### Fehlerbehandlung & UX
|
||||
- Rate-Limit (429) → Retry-Hinweis.
|
||||
- Offline-Banner + Retry-Buttons an kritischen Stellen (Checkout, Upload).
|
||||
- i18n via `react-i18next` (de/en); Strings in `public/lang/{locale}/admin.json`.
|
||||
|
||||
## API-Integration
|
||||
Die App nutzt Endpunkte aus `docs/prp/03-api.md`.
|
||||
|
||||
| Bereich | Endpunkte |
|
||||
| --- | --- |
|
||||
| Auth | `POST /tenant-auth/login`, `POST /tenant-auth/exchange`, `POST /tenant-auth/logout` |
|
||||
| Onboarding | `GET /tenant/me` (Progress Flags), `GET /tenant/packages`, `POST /tenant/events` |
|
||||
| Events | `GET/POST/PATCH/DELETE /tenant/events`, `POST /tenant/events/{event}/toggle`, Join-Token Routen |
|
||||
| Medien | `GET /tenant/events/{event}/photos`, `POST /tenant/events/{event}/photos`, `PATCH /tenant/photos/{id}` |
|
||||
| Tasks & Emotions | `GET /tenant/tasks`, `POST /tenant/events/{event}/tasks`, `GET /tenant/emotions` |
|
||||
| Settings | `GET/PATCH /tenant/settings`, `GET /tenant/credits/balance`, `POST /tenant/purchases/intent` |
|
||||
|
||||
## Nicht-funktionale Anforderungen
|
||||
- **Performance**: Ladezeit < 2s; Code-Splitting der Onboarding-Screens.
|
||||
- **Sicherheit**: Keine sensiblen Logs; CSRF abgesichert via Sanctum stateful middleware; Token-Neuausstellung durch erneutes Login oder Exchange.
|
||||
- **Accessibility**: Tastaturbedienung, Fokus-Indikatoren, `prefers-reduced-motion`.
|
||||
- **Internationalisierung**: Sprachumschaltung in Einstellungen; Standard de, Fallback en.
|
||||
|
||||
## Teststrategie
|
||||
- **PHPUnit**: Feature-Tests für Auth-Guards (Tenant ohne Events → Welcome Flow).
|
||||
- **React Testing Library**: `TenantWelcomeLayout`, `PackageSelection`, `OnboardingGuard`, `OrderSummary`.
|
||||
- **Playwright**: `tests/e2e/tenant-onboarding-flow.test.ts` deckt Login, Welcome → Packages → Summary → Event Setup ab; Erweiterung um Paddle Happy Paths und Offline/Retry geplant.
|
||||
- **Smoke Tests**: `npm run test:e2e` in CI mit optionalen Credentials (`E2E_TENANT_EMAIL`, `E2E_TENANT_PASSWORD`, Paddle Keys).
|
||||
|
||||
Für UI-Details siehe `docs/prp/tenant-app-specs/pages-ui.md`. Einstellungen werden in `docs/prp/tenant-app-specs/settings-config.md` beschrieben.
|
||||
9
docs/archive/prp/tenant-app-specs/pages-ui-legacy.md
Normal file
9
docs/archive/prp/tenant-app-specs/pages-ui-legacy.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Legacy-UI-Referenz (Framework7, Stand 2025-09-13)
|
||||
|
||||
Die ursprüngliche Dokumentation zur Framework7-basierten Tenant-Admin-App wurde im Commit-Verlauf abgelegt (`pages-ui.md` bis einschließlich 2025-09-13).
|
||||
|
||||
Sie enthält:
|
||||
- Wireframes für Login, Dashboard, Events, Fotos, Members, Tasks, Settings, Billing.
|
||||
- Hinweise zur Nutzung von Framework7-Komponenten (Toolbar, List, Card, Pull-to-Refresh, Infinite Scroll).
|
||||
|
||||
Für Migrations- oder Vergleichszwecke kann die Version über `git show <commit>:docs/prp/tenant-app-specs/pages-ui.md` abgerufen werden. Die aktuelle Implementierung basiert dagegen auf React + Tailwind (siehe `pages-ui.md`).
|
||||
68
docs/archive/prp/tenant-app-specs/pages-ui.md
Normal file
68
docs/archive/prp/tenant-app-specs/pages-ui.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Seiten- und UI-Design für die Tenant-Admin-App
|
||||
|
||||
## Status
|
||||
- **Version**: 1.1.0 (Stand 2025-10-13)
|
||||
- **Technologie**: React 19, TailwindCSS (shadcn/ui), React Router 7, React Query 5.
|
||||
- **Hinweis**: Die Framework7-Wireframes aus 2025-09 bleiben als historische Referenz erhalten und sind im Anhang dokumentiert.
|
||||
|
||||
## Design-Grundlagen
|
||||
- **Design Tokens**: Farbverlauf `#f43f5e → #6366f1`, Slate-Neutrals für Typografie, Primärschrift `Clash Display`, Fließtext `Inter`.
|
||||
- **Komponentensystem**: shadcn/ui-Basis (Button, Card, Tabs, Sheet, Dialog). Erweiterungen unter `resources/js/admin/components`.
|
||||
- **Navigation**: Obere App-Bar mit Breadcrumb & Quick Actions, mobile Tabbar (Dashboard, Events, Tasks, Einstellungen).
|
||||
- **Responsiveness**: Breakpoints `sm` (375px), `md` (768px), `xl` (1280px). Onboarding-Screens nutzen Full-Height Layouts auf Mobile, Split-Grid auf Desktop.
|
||||
- **Accessibility**: `prefers-reduced-motion`, Fokus-Ringe (Tailwind Plugin), ARIA für Carousel, Tabs, Dialoge.
|
||||
- **Offline UX**: Banner oben rechts (`Offline – deine Änderungen werden synchronisiert, sobald du wieder online bist`) + Retry-CTA.
|
||||
|
||||
## Geführtes Onboarding (Welcome Flow)
|
||||
| Schritt | Route | Komponenten | Besondere Elemente |
|
||||
| --- | --- | --- | --- |
|
||||
| Hero | `/event-admin/welcome` | `TenantWelcomeLayout`, `WelcomeStepCard`, `EmblaCarousel` | CTA „Pakete entdecken“, sekundärer Link „Später entscheiden“ |
|
||||
| How It Works | `/event-admin/welcome` (Carousel Slide) | Icon Cards, Animated Gradients | 3 Vorteile (Fotos festhalten, Aufgaben, Gäste aktivieren) |
|
||||
| Paketwahl | `/event-admin/welcome/packages` | `PackageCard`, `PricingToggle`, `QueryPackageList` | Paddle Pricing, Feature-Badges, Auswahl persistiert im Onboarding-Context |
|
||||
| Zusammenfassung | `/event-admin/welcome/summary` | `OrderSummaryCard`, Stripe Elements, Paddle Buttons | Hinweise bei fehlender Zahlungs-Konfiguration, CTA „Weiter zum Setup“ |
|
||||
| Event Setup | `/event-admin/welcome/event` | `FirstEventForm`, `FormStepper`, Toasts | Formular (Name, Datum, Sprache, Feature-Toggles) + Abschluss CTA „Event erstellen“ |
|
||||
|
||||
### Guards & Fortschritt
|
||||
- `useOnboardingProgress` (Context + localStorage) speichert `activeStep`, ausgewähltes Paket und Event-Entwurf.
|
||||
- Auth-Guard leitet Tenant ohne Events auf `/event-admin/welcome` um; nach Abschluss setzt Backend `onboarding_completed_at`.
|
||||
- Dashboard hero banner zeigt CTA „Geführtes Setup fortsetzen“, solange `onboarding_completed_at` fehlt.
|
||||
- Offlinezustand: Payment-Sektion zeigt Fallback-Karte „Zahlungsdienste offline – bitte erneut versuchen“.
|
||||
|
||||
### Assets & PWA
|
||||
- Manifest: `public/manifest.json` (Scope `/event-admin/`, Theme-Farbe `#f43f5e`, Shortcuts für Welcome & Dashboard).
|
||||
- Service Worker: `public/admin-sw.js` cached Shell `/event-admin` + statische Assets; Navigation requests → Netzwerk-First mit Cache-Fallback.
|
||||
- Registrierung: erfolgt in `resources/js/admin/main.tsx` beim `window.load` Event.
|
||||
|
||||
## Kernseiten nach dem Onboarding
|
||||
- **Dashboard**: Hero-CTA zum Welcome Flow, Statistik-Kacheln (Events aktiv, Uploads, Credits), Quick Actions (Event anlegen, Fotos moderieren, Tasks verwalten).
|
||||
- **Events**: Suchfeld + Filter Pills, Card-Layout mit Status-Badges (`Draft`, `Live`, `Archived`), Detail-Drawer mit Quick Stats.
|
||||
- **Fotos**: Moderationsgrid (Masonry), Filter (Neu, Genehmigt, Featured), Bulk-Aktionen in Sticky-Footer.
|
||||
- **Tasks**: Tabs (Bibliothek, Zuweisungen), Drag-and-Drop (React Beautiful DnD), Inline-Editor für Aufgaben.
|
||||
- **Einstellungen**: Accordion-Struktur (Branding, Legal Pages, Benachrichtigungen, Abrechnung). Preview-Panel für Farben und Logos.
|
||||
- **Abrechnung**: Kreditübersicht, Kauflog (infinite-scroll), Zahlungsoptionen (Stripe Karte, Paddle Checkout).
|
||||
|
||||
## Informationsarchitektur (aktuelle React-Router-Konfiguration)
|
||||
```
|
||||
/event-admin
|
||||
├── dashboard
|
||||
├── events
|
||||
│ ├── :slug (Detailseiten, Tabs: Overview, Tasks, Media, Members, Stats)
|
||||
│ └── :slug/edit
|
||||
├── tasks
|
||||
├── members
|
||||
├── settings
|
||||
├── billing
|
||||
└── welcome
|
||||
├── (index) # Hero + How It Works Carousel
|
||||
├── packages
|
||||
├── summary
|
||||
└── event
|
||||
```
|
||||
|
||||
## Testabdeckung (UI)
|
||||
- **Jest/RTL**: `TenantWelcomeLayout`, `WelcomeStepCard`, `PackageSelection`, `OnboardingGuard`.
|
||||
- **Playwright**: `tests/e2e/tenant-onboarding-flow.test.ts` (Login Guard, Welcome → Packages → Summary → Event Setup). Erweiterbar um Paddle-Happy-Path sowie Offline-/Retry-Szenarien.
|
||||
|
||||
## Legacy-Referenz (Framework7 Entwurf 2025-09)
|
||||
Die ursprünglichen Wireframes für Framework7 (Toolbar, FAB, Infinite Scroll) sind weiterhin im Repo historisiert (`docs/prp/tenant-app-specs/pages-ui-legacy.md`). Für Vergleiche bei Regressionen oder Migrationen bitte dort nachsehen.
|
||||
|
||||
124
docs/archive/prp/tenant-app-specs/settings-config.md
Normal file
124
docs/archive/prp/tenant-app-specs/settings-config.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Settings und Konfiguration für die Tenant Admin App
|
||||
|
||||
## Status
|
||||
- **Version**: 1.0.0 (2025-09-13)
|
||||
- **Fokus**: App-interne und tenant-spezifische Einstellungen; Integration mit Capacitor-Plugins.
|
||||
|
||||
## App-interne Settings
|
||||
Diese Settings werden lokal in der App gespeichert (via Capacitor Preferences oder IndexedDB) und beeinflussen das Verhalten der App:
|
||||
|
||||
### Core App Settings
|
||||
- **language**: String (default: 'de') – UI-Sprache; Sync mit User-Profile und i18next (react-i18next); Fallback 'en'; URL-Prefix (/de/, /en/) für persistente Wechsel.
|
||||
- **themeMode**: String ('system' | 'light' | 'dark') – Dark Mode-Präferenz; Framework7-Theming.
|
||||
- **offlineMode**: Boolean (default: true) – Aktiviert Offline-Caching und Background-Sync.
|
||||
- **pushNotifications**: Boolean (default: true) – Erlaubt Push-Registrierung.
|
||||
- **autoSyncInterval**: Number (default: 300) – Sekunden bis automatischer Sync (min: 60).
|
||||
- **maxPhotoCache**: Number (default: 100) – Anzahl gecachter Photos pro Event.
|
||||
|
||||
### User-spezifische Settings
|
||||
- **notificationPreferences**: Object
|
||||
- `newPhotos`: Boolean – Benachrichtigung bei neuen Uploads.
|
||||
- `eventUpdates`: Boolean – Bei Event-Änderungen (z.B. Veröffentlicht).
|
||||
- `lowCredits`: Boolean – Warnung bei < 2 Credits.
|
||||
- **privacySettings**: Object
|
||||
- `shareAnalytics`: Boolean (default: false) – Anonyme Stats teilen.
|
||||
- `dataRetention`: Number (default: 30) – Tage bis Auto-Delete von Cache.
|
||||
|
||||
**Speicherung**: Capacitor Preferences API (`@capacitor/preferences`) für sichere, persistente Speicherung. Bei Web-Fallback: localStorage mit Encryption (via Crypto API).
|
||||
|
||||
## Tenant-spezifische Optionen
|
||||
Diese werden über API (`GET/PATCH /tenant/settings`) geladen und überschreiben globale Defaults. Sie definieren das Verhalten für den Tenant und seine Events:
|
||||
|
||||
### Theme & Branding
|
||||
- **primaryColor**: String (default: '#007AFF') – Hauptfarbe (iOS-Blau); verwendet in Framework7 CSS-Vars (`--f7-primary`).
|
||||
- **secondaryColor**: String (default: '#5856D6') – Sekundärfarbe für Buttons/Accents.
|
||||
- **logoUrl**: String – Custom Logo für App-Banner (URL zu S3/CDN).
|
||||
- **tenantName**: String – Anzeigename (z.B. "Müller Hochzeit"); in Dashboard-Banner.
|
||||
|
||||
### Event Limits & Features
|
||||
- **maxEventsPerMonth**: Number (default: 5) – Limit pro Monat (enforced via Credits).
|
||||
- **maxPhotosPerEvent**: Number (default: 1000) – Soft-Limit; Warnung bei Überschreitung.
|
||||
- **enableTasks**: Boolean (default: true) – Tasks-System aktivieren.
|
||||
- **enableEmotions**: Boolean (default: true) – Emotions/Reactions erlauben.
|
||||
- **autoApprovePhotos**: Boolean (default: false) – Neue Uploads sofort freigeben (Risiko: Spam).
|
||||
|
||||
### Legal & Compliance
|
||||
- **legalPages**: Object (von Backend geladen, siehe docs/prp/02-tenancy.md)
|
||||
- `impressumUrl`: String – Pflicht in DE; Customizable Link.
|
||||
- `privacyUrl`: String – Datenschutzerklärung.
|
||||
- `agbUrl`: String – Allgemeine Geschäftsbedingungen.
|
||||
- **gdprRetentionDays**: Number (default: 30) – Automatische Löschung alter Photos/Events.
|
||||
- **contactEmail**: String – Support-Email für In-App-Feedback.
|
||||
|
||||
### Notifications & Integration
|
||||
- **pushEnabled**: Boolean – Tenant-weit Push aktivieren (erfordert Plugin-Registrierung).
|
||||
- **stripePublicKey**: String – Für Client-side Checkout (aus Env, nicht persistent).
|
||||
- **eventJoinDomain**: String (default: 'events.fotospiel.app') – Custom Domain für Guest-PWA.
|
||||
|
||||
**API-Handling**: Laden bei Login; Cache mit ETag; Update triggert UI-Refresh (z.B. Theme-Wechsel). Validation: Backend enforct Limits (z.B. Colors als HEX).
|
||||
|
||||
## Capacitor-Plugins
|
||||
Die App integriert folgende Plugins für native Features. Installation via `npx cap add` und Sync nach Build.
|
||||
|
||||
### Essentielle Plugins
|
||||
1. **@capacitor/preferences** (v6+)
|
||||
- **Zweck**: Sichere Speicherung von App- und User-Settings.
|
||||
- **Usage**: `Preferences.set({ key: 'themeMode', value: 'dark' })`; Migrate von localStorage.
|
||||
- **iOS/Android**: Keychain/Keystore für Encryption.
|
||||
|
||||
2. **@capacitor/push-notifications** (v6+)
|
||||
- **Zweck**: Native Push für neue Photos, Event-Updates, Low-Credits.
|
||||
- **Setup**: Registrierung bei App-Start (`PushNotifications.register()`); Token an Backend senden (`POST /tenant/devices`).
|
||||
- **Events**: `registrationToken` (senden), `pushNotificationReceived` (In-App-Handling), `pushNotificationActionPerformed` (Tap-Actions).
|
||||
- **Permissions**: Request bei erstem Login; Fallback zu Web Push in PWA/TWA.
|
||||
|
||||
3. **@capacitor/storage** (v6+)
|
||||
- **Zweck**: Offline-Caching von Events/Photos (als Alternative zu IndexedDB).
|
||||
- **Usage**: `Storage.set({ key: 'event-123', value: JSON.stringify(data) })`; Size-Limit beachten (50MB).
|
||||
- **Fallback**: Für Web; Sync mit Background-Sync.
|
||||
|
||||
4. **@capacitor/camera** (v6+)
|
||||
- **Zweck**: Direkte Kamera-Zugriff für Event-QR-Scans oder schnelle Photo-Uploads (Admin-Selfies).
|
||||
- **Usage**: `Camera.getPhoto({ quality: 90, allowEditing: true })`; Upload via signed URL.
|
||||
- **Permissions**: Camera/Mic; Privacy-Manifest für App Store.
|
||||
|
||||
5. **@capacitor/network** (v6+)
|
||||
- **Zweck**: Connectivity-Status überwachen; Offline-Modus triggern.
|
||||
- **Usage**: `Network.addListener('networkStatusChange', handleOffline)`; UI-Update bei 'offline'.
|
||||
- **Integration**: Deaktiviere Sync-Buttons; Zeige Cached-Data.
|
||||
|
||||
### Optionale Plugins
|
||||
- **@capacitor/haptics** (v6+): Vibration-Feedback bei Actions (z.B. Photo-Approve).
|
||||
- **@capacitor/share** (v6+): Teilen von Event-QR-Codes via Native Share-Sheet.
|
||||
- **@capacitor/device** (v6+): Geräte-Info (Model, OS) für Analytics; Token zu Backend.
|
||||
|
||||
### Plugin-Konfiguration (capacitor.config.ts)
|
||||
```typescript
|
||||
import { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'com.fotospiel.tenantadmin',
|
||||
appName: 'Event Photo Admin',
|
||||
webDir: 'dist',
|
||||
bundledWebRuntime: false,
|
||||
plugins: {
|
||||
PushNotifications: {
|
||||
presentationOptions: ["badge", "sound", "alert"]
|
||||
},
|
||||
Camera: {
|
||||
permissions: {
|
||||
camera: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
### Security & Privacy
|
||||
- **Plugin-Permissions**: Explizite Requests; Erkläre Zweck im Onboarding (z.B. "Push für neue Photos").
|
||||
- **Data Storage**: Kein PII in Preferences; Tokens encrypted (siehe Auth-Specs).
|
||||
- **App Store Compliance**: Privacy Manifest mit Usage-Descriptions (z.B. NSPhotoLibraryUsageDescription).
|
||||
|
||||
Für detailliertes Packaging siehe capacitor-setup.md; UI-Integration in pages-ui.md.
|
||||
Reference in New Issue
Block a user