{{-- IMPULSA shell (Vibrant template only). The purple-gradient sidebar with the "biting tab" active nav + the 70px header (search · quick actions · theme toggle · language · greeting + turquoise balance + avatar). Light+dark since MEJORA 2 — the header carries a theme toggle (dark = #1d1f1f). Multi-tenant safe: the sidebar gradient derives from --brand, so a reseller re-themes it, while the turquoise --rf-accent (logo / balance) stays IMPULSA's signature. Consumes $user / $balance from the wrapper (components.layouts.client). --}} @php // Flat nav in IMPULSA order. `routes` drives the active/"biting" state. $imp_nav = [ ['label' => __('Statistics'), 'icon' => 'bar-chart-3', 'route' => 'app.dashboard', 'routes' => ['app.dashboard']], ['label' => __('New Order'), 'icon' => 'shopping-cart', 'route' => 'app.orders.create', 'routes' => ['app.orders.create']], ['label' => __('Order Logs'), 'icon' => 'clock', 'route' => 'app.orders', 'routes' => ['app.orders']], ['label' => __('Drip-feed'), 'icon' => 'droplets', 'route' => 'app.dripfeed', 'routes' => ['app.dripfeed']], ['label' => __('Subscriptions'), 'icon' => 'repeat', 'route' => 'app.subscriptions', 'routes' => ['app.subscriptions']], ['label' => __('Services'), 'icon' => 'list', 'route' => 'app.services', 'routes' => ['app.services']], ['label' => __('Add Funds'), 'icon' => 'wallet', 'route' => 'app.funds', 'routes' => ['app.funds']], ['label' => __('Transactions'), 'icon' => 'receipt', 'route' => 'app.transactions', 'routes' => ['app.transactions']], ['label' => __('AI Support'), 'icon' => 'message-circle', 'route' => 'app.tickets', 'routes' => ['app.tickets', 'app.tickets.show'], // Count tickets that have staff replies the client hasn't read yet. // customer_read_at IS NULL → never opened; staff message after read_at → new reply since last visit. 'badge' => \App\Models\Ticket::where('user_id', $user->id) ->whereNotIn('status', ['closed']) ->whereHas('messages', fn ($m) => $m->where('is_staff', true)) ->where(fn ($q) => $q ->whereNull('customer_read_at') ->orWhereHas('messages', fn ($m) => $m ->where('is_staff', true) ->whereColumn('ticket_messages.created_at', '>', 'tickets.customer_read_at') ) ) ->count() ?: null, 'badge_live' => true], ['label' => __('News'), 'icon' => 'megaphone', 'route' => 'app.news', 'routes' => ['app.news'], 'badge' => $newsUnread], ['label' => __('FAQ'), 'icon' => 'help-circle', 'route' => 'faq', 'routes' => ['faq']], ]; // The API row only exists while the API does. Both controls that close it // (the module and Settings > Defaults > Enable public API) make the route // 404, so leaving the link in the sidebar advertises a dead end. if (api_enabled()) { $imp_nav[] = ['label' => __('API'), 'icon' => 'code', 'route' => 'app.api', 'routes' => ['app.api']]; } $imp_nav[] = ['label' => __('Terms & Conditions'), 'icon' => 'file-text', 'route' => 'app.terms', 'routes' => ['app.terms']]; $imp_active = fn ($item) => collect($item['routes'])->contains(fn ($r) => request()->routeIs($r)); $imp_first = strtoupper(mb_substr($user->display_name ?? $user->name ?? 'U', 0, 1)); // Vibrant sidebar has a dark brand background — prefer logo_light; fall back to logo_dark inverted. $_vb = current_panel()?->branding ?? []; $imp_logo = isset($_vb['logo_light']) ? asset($_vb['logo_light']) : panel_logo_url(); // logo_dark or legacy 'logo' $imp_logo_alt = \App\Support\Brand::name(); // Header — a single meaningful action. "AI Messages"/"Support"/"Own Panel"/"Top up" // duplicated the sidebar (AI Support, Add Funds) and the balance badge, so they are // gone; the utility icons (website / theme / fullscreen) live directly in the header. $imp_actions = [ ['label' => __('AI Support'), 'icon' => 'message-circle', 'route' => 'app.tickets'], ]; @endphp
{{-- Mobile backdrop --}}
{{-- ============================ SIDEBAR ============================ --}} {{-- ============================ CONTENT ============================ --}}
{{-- Service ID quick-search: type an ID or name → dropdown → click → /app/new-order?service=id. Hidden on phones and allowed to shrink above that: the class pins it at 32vw and refuses to give width back, which pushed the balance and the avatar clean off the right edge of a 390px screen. New Order and Services are one tap away in the sidebar there. --}}
@foreach ($imp_actions as $a) {{ $a['label'] }} @endforeach
{{-- Public website (opens the panel's public landing in a new tab). Hidden on phones — the footer already links it, and the row has to fit the balance and the avatar first. --}} {{-- Dark / light theme toggle --}} {{-- Fullscreen toggle — desktop only; a phone browser is already one. --}} {{-- Language switcher --}}
@foreach (active_locales() as $code => $label) {{ $label }} @endforeach
{{-- Wallet balance --}} {{-- User menu --}}
{{ $user->display_name ?? $user->name }}
{{ $user->email }}
{{ __('Profile') }} @if (api_enabled()) {{ __('API key') }} @endif
@csrf
{{ $slot }} {{-- The SAME footer the other two client shells render. Vibrant is the factory default, and it was the one shell that omitted this — so the support email, phone and working hours an operator fills in under Settings had nowhere to appear for most installs. Sharing the partial rather than forking it keeps the three shells from drifting into three different answers. --}} @include('partials.client-footer')