@php $seoData = isset($seo) && is_array($seo) ? $seo : []; $pageTitle = $seoData['title'] ?? trim($__env->yieldContent('title', 'Coaster World')); $pageDescription = $seoData['description'] ?? __('ui.brand_tagline'); $pageCanonical = $seoData['canonical'] ?? url()->current(); $pageImage = $seoData['image'] ?? url('/coaster-world-logo.png'); $pageType = $seoData['type'] ?? 'website'; $indexableRoute = request()->routeIs( 'home', 'explore', 'parks.show', 'coasters.show', 'attractions.show', 'experts.index', 'community.photos.index', 'community.photos.entity', 'community.photos.show', 'site.about', 'site.contact', 'site.legal', 'site.privacy', 'site.terms', 'site.cookies' ); $pageRobots = $seoData['robots'] ?? ($indexableRoute ? 'index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1' : (request()->routeIs('search') ? 'noindex,follow' : 'noindex,nofollow')); @endphp @php $cwCanonicalAppUrl = rtrim((string) config('app.url'), '/'); $cwCanonicalParts = parse_url($cwCanonicalAppUrl); $cwCanonicalHttps = app()->environment('production') && is_array($cwCanonicalParts) && strtolower((string) ($cwCanonicalParts['scheme'] ?? '')) === 'https' && !empty($cwCanonicalParts['host']); $cwCanonicalOrigin = $cwCanonicalHttps ? 'https://'.strtolower((string) $cwCanonicalParts['host']) .(isset($cwCanonicalParts['port']) ? ':'.(int) $cwCanonicalParts['port'] : '') : ''; @endphp @if($cwCanonicalHttps) @endif {{ $pageTitle }} @if(!empty($seoData['json_ld'])) @endif @vite(['resources/css/app.css', 'resources/js/app.js']) @stack('head') @auth @php $headerNotificationStats = \App\Support\SafeCache::rememberArray( 'cw:header-notifications:v1931:'.auth()->id(), now()->addSeconds(8), function (): array { $stats = auth()->user()->coasterWorldNotifications() ->whereNull('read_at') ->where(function ($query): void { $query->whereNull('expires_at')->orWhere('expires_at', '>', now()); }) ->selectRaw('COUNT(*) as unread_count, COALESCE(MAX(id), 0) as latest_id') ->toBase() ->first(); return [ 'unread_count' => (int) ($stats->unread_count ?? 0), 'latest_id' => (int) ($stats->latest_id ?? 0), ]; } ); $headerUnreadNotifications = (int) ($headerNotificationStats['unread_count'] ?? 0); $headerLatestNotificationId = (int) ($headerNotificationStats['latest_id'] ?? 0); $headerRecentNotifications = auth()->user()->coasterWorldNotifications() ->where(function ($query): void { $query->whereNull('expires_at')->orWhere('expires_at', '>', now()); }) ->latest() ->limit(5) ->get(); @endphp @endauth
@php $headerInitials = 'CW'; if (auth()->check()) { $headerNameParts = preg_split('/\s+/u', trim((string) auth()->user()->name)) ?: []; $headerInitials = collect($headerNameParts) ->filter() ->take(2) ->map(fn ($part) => mb_strtoupper(mb_substr((string) $part, 0, 1))) ->implode(''); $headerInitials = $headerInitials !== '' ? $headerInitials : 'CW'; } $headerSearchLabels = [ 'park' => __('ui.type_park'), 'coaster' => __('ui.type_coaster'), 'attraction' => __('ui.type_attraction'), 'user' => __('ui.type_user'), 'group' => __('ui.type_group'), 'manufacturer' => __('ui.type_manufacturer'), 'country' => __('ui.type_country'), ]; $headerAccessAllowed = function (string $access): bool { return match ($access) { 'auth' => auth()->check(), 'admin' => auth()->check() && (bool) auth()->user()->is_admin, default => true, }; }; $headerCategories = collect(app(\App\Services\Navigation\HeaderNavigationService::class)->categories()) ->filter(fn (array $category) => $headerAccessAllowed((string) ($category['access'] ?? 'all'))) ->values(); $headerDesktopCategories = $headerCategories->filter(fn (array $category) => (bool) ($category['desktop_visible'] ?? true))->values(); $headerMobileCategories = $headerCategories->filter(fn (array $category) => (bool) ($category['mobile_visible'] ?? true))->values(); $headerLocales = [ 'fr' => ['flag' => '/images/flags/fr.svg', 'label' => 'Français'], 'en' => ['flag' => '/images/flags/en.svg', 'label' => 'English'], 'de' => ['flag' => '/images/flags/de.svg', 'label' => 'Deutsch'], 'es' => ['flag' => '/images/flags/es.svg', 'label' => 'Español'], 'it' => ['flag' => '/images/flags/it.svg', 'label' => 'Italiano'], ]; $headerLabel = function (array $entry): string { $key = (string) ($entry['label'] ?? ''); $translated = $key !== '' ? __($key) : ''; if ($translated === $key && !empty($entry['fallback_label'])) { return (string) $entry['fallback_label']; } return $translated; }; $headerItemAvailable = function (array $item, string $surface = 'desktop') use ($headerAccessAllowed): bool { if (!$headerAccessAllowed((string) ($item['access'] ?? 'all'))) { return false; } if ($surface === 'desktop' && !((bool) ($item['desktop_visible'] ?? true))) { return false; } if ($surface === 'mobile' && !((bool) ($item['mobile_visible'] ?? true))) { return false; } if (!empty($item['user_param'])) { if (!auth()->check()) { return false; } $attribute = (string) $item['user_param']; return trim((string) auth()->user()->{$attribute}) !== ''; } return true; }; $headerItemUrl = function (array $item): string { if (!empty($item['url'])) { return (string) $item['url']; } $params = (array) ($item['params'] ?? []); if (!empty($item['user_param']) && auth()->check()) { $attribute = (string) $item['user_param']; $params[] = auth()->user()->{$attribute}; } $url = route((string) $item['route'], $params); if (!empty($item['query']) && is_array($item['query'])) { $url .= '?'.http_build_query($item['query']); } if (!empty($item['fragment'])) { $url .= '#'.ltrim((string) $item['fragment'], '#'); } return $url; }; $headerRouteActive = function (array $patterns): bool { return $patterns !== [] && request()->routeIs(...$patterns); }; $headerItemActive = function (array $item) use ($headerRouteActive): bool { $patterns = array_values((array) ($item['active'] ?? [])); if (!$headerRouteActive($patterns)) { return false; } foreach ((array) ($item['active_query'] ?? []) as $key => $expected) { $default = $key === 'kind' ? 'all' : null; if ((string) request()->query($key, $default) !== (string) $expected) { return false; } } return true; }; @endphp
@yield('content')
@guest @include('partials.auth-modal') @endguest @stack('scripts')