name('home'); Route::middleware(['auth', 'verified'])->group(function () { Route::get('dashboard', function () { return Inertia::render('dashboard'); })->name('dashboard'); }); require __DIR__.'/settings.php'; require __DIR__.'/auth.php'; // Guest PWA shell (served for event and /pwa paths; React handles routing) Route::view('/e/{any?}', 'guest')->where('any', '.*'); Route::view('/pwa/{any?}', 'guest')->where('any', '.*'); Route::view('/legal/{any?}', 'guest')->where('any', '.*'); // Minimal public API for Guest PWA (stateless; no CSRF) Route::prefix('api/v1')->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class])->group(function () { // Public legal pages Route::get('/legal/{slug}', [\App\Http\Controllers\Api\LegalController::class, 'show']); }); // Stripe webhooks (no CSRF, no auth) Route::post('/webhooks/stripe', [\App\Http\Controllers\StripeWebhookController::class, 'handle']); // CSV templates for Super Admin imports Route::get('/super-admin/templates/emotions.csv', function () { $headers = [ 'Content-Type' => 'text/csv', 'Content-Disposition' => 'attachment; filename="emotions_template.csv"', ]; $callback = function () { $out = fopen('php://output', 'w'); fputcsv($out, ['name_de','name_en','icon','color','description_de','description_en','sort_order','is_active','event_types']); fputcsv($out, ['Fröhlich','Happy','😀','#FFD700','Fröhlicher Moment','Happy moment','0','1','wedding|corporate']); fclose($out); }; return response()->stream($callback, 200, $headers); }); // Tenant Admin API (temporary token-based, no hardening) Route::prefix('api/v1/tenant')->group(function () { Route::post('/login', [\App\Http\Controllers\Api\TenantController::class, 'login']); Route::middleware([\App\Http\Middleware\ApiTokenAuth::class])->group(function () { Route::get('/me', [\App\Http\Controllers\Api\TenantController::class, 'me']); Route::get('/events', [\App\Http\Controllers\Api\TenantController::class, 'events']); Route::get('/events/{id}', [\App\Http\Controllers\Api\TenantController::class, 'showEvent']); Route::post('/events', [\App\Http\Controllers\Api\TenantController::class, 'storeEvent']); Route::put('/events/{id}', [\App\Http\Controllers\Api\TenantController::class, 'updateEvent']); Route::post('/events/{id}/toggle', [\App\Http\Controllers\Api\TenantController::class, 'toggleEvent']); Route::get('/events/{id}/photos', [\App\Http\Controllers\Api\TenantController::class, 'eventPhotos']); Route::get('/events/{id}/stats', [\App\Http\Controllers\Api\TenantController::class, 'eventStats']); Route::post('/events/{id}/invites', [\App\Http\Controllers\Api\TenantController::class, 'createInvite']); Route::post('/photos/{id}/feature', [\App\Http\Controllers\Api\TenantController::class, 'featurePhoto']); Route::post('/photos/{id}/unfeature', [\App\Http\Controllers\Api\TenantController::class, 'unfeaturePhoto']); Route::delete('/photos/{id}', [\App\Http\Controllers\Api\TenantController::class, 'deletePhoto']); }); }); // Tenant Admin PWA shell Route::view('/admin/{any?}', 'admin')->where('any', '.*'); Route::get('/admin/qr', [\App\Http\Controllers\Admin\QrController::class, 'png']); Route::get('/super-admin/templates/tasks.csv', function () { $headers = [ 'Content-Type' => 'text/csv', 'Content-Disposition' => 'attachment; filename="tasks_template.csv"', ]; $callback = function () { $out = fopen('php://output', 'w'); fputcsv($out, ['emotion_name','emotion_name_de','emotion_name_en','event_type_slug','title_de','title_en','description_de','description_en','difficulty','example_text_de','example_text_en','sort_order','is_active']); fputcsv($out, ['Happy','','','wedding','Gruppenfoto','Group photo','Sammelt euch fĂŒr ein Foto.','Get together for a photo.','easy','Zeigt eure besten LĂ€cheln.','Show your best smiles.','0','1']); fclose($out); }; return response()->stream($callback, 200, $headers); });