# 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**:
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