@vite(['resources/css/app.css', 'resources/js/app.js'])
@livewireStyles
@php
$maintenanceWindows = collect();
if (auth()->check()) {
$portalCustomer = \App\Models\Customer::query()->where('user_id', auth()->id())->first()
?? \App\Models\Customer::query()->where('email', auth()->user()->email)->first();
if ($portalCustomer) {
$maintenanceWindows = \App\Models\MaintenanceWindow::bannerFor($portalCustomer);
}
}
@endphp
@foreach ($maintenanceWindows as $mw)
@php $isActive = now()->greaterThanOrEqualTo($mw->starts_at) && now()->lessThanOrEqualTo($mw->ends_at); @endphp
{{ $mw->title }}
{{ $isActive
? __('maintenance.banner_active', ['end' => $mw->ends_at->isoFormat('LT')])
: __('maintenance.banner_upcoming', ['start' => $mw->starts_at->isoFormat('LLL'), 'end' => $mw->ends_at->isoFormat('LT')]) }}
@endforeach
@if (session('impersonator_id'))
{{-- Admin impersonation banner — visible on every portal page until the admin returns. --}}
{{ __('impersonate.banner', ['name' => auth()->user()->name]) }}
@endif
{{-- Sidebar: fixed drawer on small screens, fixed full-height column on large (R7). --}}
{{-- Mobile backdrop --}}
{{-- Global toast — any element can trigger it with $dispatch('notify', { message }) --}}
show = false, 3200)"
x-show="show"
x-cloak
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-12"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-12"
role="status"
aria-live="polite"
class="fixed bottom-6 left-1/2 z-[80] -translate-x-1/2 rounded-pill bg-ink px-5 py-3 text-sm font-medium text-on-accent shadow-md"
>
@livewire('wire-elements-modal')
@livewireScripts