# Registrierungs-Fixes: Redirect, Error-Clearing und Role-Handling (2025-10-02)

## Problem-Beschreibung
- **Redirect-Fehler**: Bei erfolgreicher Registrierung (free oder paid Package) wurde onSuccess in Register.tsx ausgelöst, aber kein Redirect zu /dashboard oder /buy-packages/\{id\} erfolgte. Ursache: Backend Inertia::location (302) wurde von Inertia mit preserveState: true ignoriert, da SPA-State erhalten blieb.
- **Persistente Errors**: Server-Errors (z.B. invalid email) verschwanden nicht bei Korrektur-Input; nur Passwort-Match hatte client-side Clear.
- **Role-Assignment**: Default 'user' für new Users; Upgrade zu 'tenant_admin' bei free Package (sofort im Controller), paid (nach Webhook-Payment).
- **Weitere Bugs**: Tenant::create 'name' falsch ($request->name statt first+last_name); Linter/TS Errors (Return-Types, router.visit unknown).

## Fixes
### Backend (MarketingRegisterController.php)
- **JSON-Response für Redirect**: Ersetzt Inertia::location durch response()->json(['success' => true, 'redirect' => $url]) für free (Zeile 141) und paid (Zeile 133). Kompatibel mit Inertia onSuccess (page.props.success/redirect prüfen).
- **Tenant Name Fix**: 'name' => $request->first_name . ' ' . $request->last_name (Zeile 71); slug entsprechend angepasst.
- **Role-Logic**: 'role' => 'user' in User::create (Zeile 66); für free: Update zu 'tenant_admin' nach TenantPackage::create (Zeile 129), Re-Login (Zeile 130). Für paid: Kein Upgrade bis Webhook (Paddle).
- **Return-Type**: store() zu JsonResponse (Zeile 44); use JsonResponse hinzugefügt (Zeile 22).

### Frontend (Register.tsx)
- **onSuccess-Handling**: Prüfe page.props.success && router.visit(page.props.redirect as string) (Zeile 66-68); Fallback zu data.package_id ? `` `/buy-packages/\${data.package_id}` `` : '/dashboard' (Zeile 71-75); console.log für Debug (Zeile 67, 74).
- **Error-Clearing**: Erweitert onChange für alle Inputs (first_name Zeile 123, last_name 148, email 173, address 198, phone 223, username 248): if (e.target.value.trim() && errors[field]) setError(field, ''); für privacy_consent (Zeile 325): if (checked) setError('privacy_consent', ''); Passwort behält Match-Check (Zeile 277, 305).
- **General Errors Key**: nutze `&lt;div key={"general-errors-" + Object.keys(errors).join('-')}&gt;` (Zeile 347) für Re-Render bei Error-Änderungen.

### Tests (RegistrationTest.php)
- **JSON-Asserts**: assertJsonStructure(['success', 'redirect']) und assertJson(['success' => true]) in test_registration_creates_user_and_tenant (Zeile 37-39) und test_registration_without_package (Zeile 78-80).
- **Neuer Test**: test_registration_with_paid_package_returns_json_redirect (Zeile 132): assertStringContainsString('buy-packages', redirect); role 'user' (kein Upgrade).
- **Validation/Email**: Unverändert, assertSessionHasErrors (Zeile 107).

## Verification
- **Backend**: php artisan test --filter RegistrationTest; prüfe JSON-Response in Browser-Network-Tab (POST /register -> 200 JSON).
- **Frontend**: Registrierung mit free: Redirect zu /verification.notice; paid: zu /buy-packages/10; Errors clear bei Input (z.B. invalid email -> input valid -> error gone).
- **Role**: DB-Check: free -> 'tenant_admin', paid -> 'user' (Upgrade via Webhook).
- **Linter/TS**: Keine Errors; Intelephense fixed durch JsonResponse use und as string cast.

## PRP-Update (docs/prp/13-backend-authentication.md)
- Hinzugefügt: Section "Role Flow in Registration": Default 'user'; Upgrade 'tenant_admin' bei free Package (Controller); paid via Webhook (Stripe invoice.paid, Paddle IPN); JSON-Success für Inertia-Forms (preserveState + onSuccess visit).

## Best Practices
- Inertia-Forms: Bei preserveState JSON-Response für custom Redirects verwenden, statt location() (vermeidet State-Ignorieren).
- Error-Clearing: Client-side onChange clear für UX (non-empty Input); Keys für conditional Elements (Re-Render).
- GDPR: Privacy-Consent required; no PII in Logs.

Date: 2025-10-02
