exists('web.'.$theme)) { return view('web.'.$theme); } // Fallback to the default home view return view('web.home'); })->name('home'); // Weitere gemeinsame Webseiten hier... Route::get('/about', function () { return view('web.about'); })->name('about'); Route::get('/ecosystem', function () { return redirect('/partner', 301); })->name('ecosystem'); $loadAziziContent = fn (): array => json_decode( file_get_contents(resource_path('lang/de/immobilien-azizi.json')), true, 512, JSON_THROW_ON_ERROR, ); $isAziziSourcePreview = function (Request $request): bool { if (! $request->query->has('dev')) { return false; } return ! in_array(strtolower((string) $request->query('dev')), ['0', 'false', 'off', 'no'], true); }; Route::get('/immobilien', function (Request $request) use ($isAziziSourcePreview, $loadAziziContent) { $content = $loadAziziContent(); $dev = $isAziziSourcePreview($request); $devQuery = $dev; $overviewRouteName = 'immobilien'; $detailRouteName = 'immobilien.show'; return view('web.dev.immobilien-azizi', compact('content', 'dev', 'devQuery', 'overviewRouteName', 'detailRouteName')); })->name('immobilien'); // Immobilien-Welt: eigenes Magazin, eigene Über-uns-Seite und eigene FAQ. Muessen vor der // Projekt-Detailroute stehen, sonst wuerde diese die Pfade als Projekt-Slug lesen. Route::get('/immobilien/magazin', function () { return view('web.magazin', ['world' => 'immobilien']); })->name('immobilien.magazin'); Route::get('/immobilien/ueber-b2in', function () { return view('web.immobilien-about'); })->name('immobilien.about'); Route::get('/immobilien/faq', function () { return view('web.faq', ['section' => 'faq_immobilien']); })->name('immobilien.faq'); Route::get('/immobilien/kontakt', function () { return view('web.contact', ['world' => 'immobilien']); })->name('immobilien.contact'); Route::get('/immobilien/{slug}', function (Request $request, string $slug) use ($isAziziSourcePreview, $loadAziziContent) { $content = $loadAziziContent(); $dev = $isAziziSourcePreview($request); $devQuery = $dev; $overviewRouteName = 'immobilien'; $project = collect($content['projects'] ?? [])->firstWhere('slug', $slug); abort_unless($project, 404); return view('web.dev.immobilien-azizi-show', compact('content', 'project', 'dev', 'devQuery', 'overviewRouteName')); })->name('immobilien.show'); // Die Netzwerk-Seite geht im Abschnitt "Mehr als Marken: unser Netzwerk" auf /marken auf. // Alte Links und Rankings laufen per 301 dorthin; die View liegt seit 06.10.2026 in // dev/2026-08-28/archiv-2026-10-06/. Route::get('/netzwerk', function () { return redirect('/marken', 301); })->name('netzwerk'); Route::get('/interior', function () { return redirect('/marken', 301); })->name('interior'); Route::get('/partner', function () { return redirect('/marken', 301); })->name('partner'); Route::get('/magazin', function () { return view('web.magazin'); })->name('magazin'); // Alte numerische Magazin-URLs (/magazin/1 … /magazin/5) dauerhaft auf den Slug umleiten. // Muss vor der Slug-Route stehen, sonst wuerde diese die Ziffern selbst schlucken. Route::get('/magazin/{id}', function (string $id) { $slug = \App\Models\CmsArticle::slugForLegacyId($id); abort_unless($slug !== null, 404); return redirect()->route('magazin.detail', ['slug' => $slug], 301); })->whereNumber('id')->name('magazin.detail.legacy'); Route::get('/magazin/{slug}', function (string $slug) { // Die Detailseite rendert in der Welt ihres Beitrags (Dubai-Themen bleiben blau). Die Welt // muss vor dem Rendern feststehen, weil Kopf- und Fusszeile sie in mount() festhalten. $article = \App\Models\CmsArticle::forFrontend()[$slug] ?? null; abort_unless($article !== null, 404); b2in_world_set($article['world'] ?? 'interior'); return view('web.magazin-detail', compact('slug')); })->name('magazin.detail'); // Kernmarken: Uebersichtsseite und Detailseite je Marke. Route::get('/marken', function () { return view('web.marken'); })->name('marken'); Route::get('/marken/{slug}', function (string $slug) { $brands = \App\Models\CmsBrand::forFrontend(); abort_unless(isset($brands[$slug]), 404); $brand = $brands[$slug]; $brandTitle = $brand['name'].' – '.$brand['tagline'].' | B2in Interior'; $brandDescription = trim(strip_tags((string) $brand['teaser'])); return view('web.marken-show', compact('slug', 'brandTitle', 'brandDescription')); })->name('marken.show'); // Referenzen: realisierte Projekte aus den Markengalerien plus der Showroom-Feed. // Lässt sich im CMS-Modul „Referenzen“ ausblenden – dann 404 und kein Menüpunkt. Route::get('/referenzen', function () { abort_unless(references_page_enabled(), 404); return view('web.referenzen'); })->name('referenzen'); // Schreibgeschuetzte Einbettung eines Displays (nur veroeffentlichte Playlists, kein Token). Route::get('/embed/display/{display}', [\App\Http\Controllers\DisplayEmbedController::class, 'show']) ->name('display.embed'); Route::get('/contact', function () { return view('web.contact'); })->name('contact'); // Verwaiste Seiten: ihre Content-Sektionen (hero_image, content_section_left/right, portfolio) // existieren in keiner Lang-Datei mehr und die Seiten liefern seitdem 500. Sie werden wie die // anderen stillgelegten Seiten dauerhaft umgeleitet; die Views liegen in dev/2026-08-28/archiv-2026-10-06/. Route::get('/service', function () { return redirect('/marken', 301); })->name('service'); Route::get('/portfolio', function () { return redirect('/immobilien', 301); })->name('portfolio'); Route::get('/faq', function () { return view('web.faq'); })->name('faq'); // Rechtliche Seiten Route::get('/impressum', function () { return view('web.impressum'); })->name('impressum'); Route::get('/privacy', function () { return view('web.privacy'); })->name('privacy'); Route::get('/terms', function () { return view('web.terms'); })->name('terms'); Route::get('/cookie-policy', function () { return view('web.cookie-policy'); })->name('cookie-policy'); // Theme Demo Route Route::get('/theme-demo', function () { return view('web.theme-demo'); })->name('theme-demo'); // Dev: Sitemap und Quellvorschau der Immobilien-Seite Route::prefix('dev')->group(function () use ($loadAziziContent) { Route::get('/sitemap', fn () => view('web.dev.sitemap'))->name('dev.sitemap'); Route::get('/immobilien-azizi', function () use ($loadAziziContent) { $content = $loadAziziContent(); $dev = true; $devQuery = false; $overviewRouteName = 'dev.immobilien-azizi'; $detailRouteName = 'dev.immobilien-azizi.show'; return view('web.dev.immobilien-azizi', compact('content', 'dev', 'devQuery', 'overviewRouteName', 'detailRouteName')); })->name('dev.immobilien-azizi'); Route::get('/immobilien-azizi/{slug}', function (string $slug) use ($loadAziziContent) { $content = $loadAziziContent(); $project = collect($content['projects'] ?? [])->firstWhere('slug', $slug); abort_unless($project, 404); $dev = true; $devQuery = false; $overviewRouteName = 'dev.immobilien-azizi'; return view('web.dev.immobilien-azizi-show', compact('content', 'project', 'dev', 'devQuery', 'overviewRouteName')); })->name('dev.immobilien-azizi.show'); }); // Pfad-basierte Theme-Routen für lokale Entwicklung wurden entfernt // Die Themensauswahl wird nun über den ThemeServiceProvider gesteuert (Domain oder ?theme=... GET-Parameter) Route::get('/partner/invitation/expired/{token}', function (string $token) { $invitation = \App\Models\PartnerInvitation::with('role')->where('token', $token)->firstOrFail(); return view('partner.invitation-expired', compact('invitation')); })->name('partner.invitation.expired'); Route::get('/partner/invitation/used/{token}', function (string $token) { $invitation = \App\Models\PartnerInvitation::with('role')->where('token', $token)->firstOrFail(); return view('partner.invitation-used', compact('invitation')); })->name('partner.invitation.used'); Volt::route('/partner/invitation/{token}', 'partner.invitation-accept') ->name('partner.invitation.accept'); Volt::route('/partner/create-account', 'partner.create-account') ->name('partner.create.account'); // Öffentliche Registrierung per QR-/Code (Landing, code-check) Volt::route('/reg/{role}', 'reg.landing') ->name('registration.landing'); Volt::route('/registration/thank-you', 'reg.thank-you') ->name('registration.thank-you'); // Partner Setup Wizard & Daten Route::middleware('auth')->group(function () { Volt::route('/partner/setup', 'partner.setup-wizard') ->name('partner.setup.wizard'); }); // Cabinet Quick-Status – key-geschützte Mini-App für schnellen Statuswechsel Route::get('/info/status', QuickStatus::class)->name('cabinet.quick-status'); // Authentifizierungs-Routen werden in domains.php eingebunden // require __DIR__ . '/auth.php';