{{-- Shell autenticado: sidebar + topbar (desktop) / topbar + bottom-nav (mobile). Porte de views/layout.php do aurios-ops original — mesmo HTML/CSS, mesmos componentes (busca global, sino de notificações, status do worker, tema). Diferença deliberada: o original usa para links relativos funcionarem tanto na raiz quanto numa subpasta de publicação. O Laravel já resolve isso via APP_URL/url(), então aqui todo link é absoluto (url()/asset()) e não há . @var string $content @var string|null $title @var list|null $crumbs --}} @php $appName = config('app.name'); $pageTitle = $title ?? $appName; $flash = (string) session('status', ''); $user = auth()->user(); $userName = trim((string) ($user->name ?? 'Usuário')) ?: 'Usuário'; $notificationSnapshot = \App\Services\NotificationService::unreadPage(0, 10); $notifications = $notificationSnapshot['items']; $notificationUnreadCount = $notificationSnapshot['total']; $notificationSoundConfig = \App\Services\NotificationSoundService::clientConfig(); $mobileNavigation = \App\Services\MobileNavigationPreferenceService::get($user); $activeTicketCount = \App\Models\AurelioTicket::query() ->whereIn('status', ['aberto', 'em_atendimento', 'aguardando_cliente']) ->count(); $userParts = preg_split('/\s+/', $userName, -1, PREG_SPLIT_NO_EMPTY) ?: ['U']; $initials = mb_strtoupper( mb_substr($userParts[0], 0, 1) . (count($userParts) > 1 ? mb_substr(end($userParts), 0, 1) : ''), ); $flashErr = str_contains(mb_strtolower($flash), 'incorret') || str_contains(mb_strtolower($flash), 'erro') || str_contains(mb_strtolower($flash), 'não foi'); $path = '/' . trim(request()->path(), '/'); $path = $path === '//' ? '/' : $path; $narrow = (bool) preg_match('#/(novo|nova|editar|categorias)$#', $path); $navItems = [ ['/', 'space_dashboard', 'Início'], ['/sistemas', 'apps', 'Soluções'], ['/monitoramentos', 'monitoring', 'Monitoramento'], ['/chamados', 'support_agent', 'Chamados'], ['/tarefas', 'checklist', 'Tarefas'], ['/leads', 'person_search', 'Leads'], ['/afiliados', 'handshake', 'Afiliados'], ['/clientes', 'groups', 'Clientes'], ['/projetos', 'folder_open', 'Projetos'], ['/financeiro', 'account_balance_wallet', 'Financeiro'], ]; $mobileNavItems = [...$navItems, ['/operacao', 'monitoring', 'LOGs']]; $isActive = static function (string $href) use ($path): bool { if ($href === '/') { return $path === '/'; } if ($href === '/monitoramentos') { return $path === '/monitoramentos' || preg_match('#^/sistemas/\d+/monitoramento$#', $path) === 1; } if ($href === '/sistemas' && preg_match('#^/sistemas/\d+/monitoramento$#', $path) === 1) { return false; } return str_starts_with($path, $href); }; if (!isset($crumbs)) { $sectionMap = [ 'clientes' => ['label' => 'Clientes', 'icon' => 'groups'], 'leads' => ['label' => 'Leads', 'icon' => 'person_search'], 'afiliados' => ['label' => 'Afiliados', 'icon' => 'handshake'], 'projetos' => ['label' => 'Projetos', 'icon' => 'folder_open'], 'financeiro' => ['label' => 'Financeiro', 'icon' => 'account_balance_wallet'], 'reunioes' => ['label' => 'Reuniões', 'icon' => 'calendar_month'], 'sistemas' => ['label' => 'Soluções', 'icon' => 'apps'], 'saude' => ['label' => 'Saúde', 'icon' => 'monitor_heart'], 'monitoramentos' => ['label' => 'Monitoramentos', 'icon' => 'monitoring'], 'notificacoes' => ['label' => 'Notificações', 'icon' => 'notifications'], 'operacao' => ['label' => 'LOGS', 'icon' => 'monitoring'], 'agenda' => ['label' => 'Agenda operacional', 'icon' => 'view_kanban'], 'chamados' => ['label' => 'Chamados', 'icon' => 'support_agent'], 'tarefas' => ['label' => 'Tarefas', 'icon' => 'checklist'], 'buscar' => ['label' => 'Busca', 'icon' => 'search'], 'perfil' => ['label' => 'Meu perfil', 'icon' => 'person'], 'configuracoes' => ['label' => 'Configurações', 'icon' => 'settings'], ]; $segmentLabels = [ 'ops' => 'Gestão interna', 'novo' => 'Novo', 'nova' => 'Nova', 'editar' => 'Editar', 'categorias' => 'Categorias', 'calendario' => 'Calendário', ]; $segmentIcons = [ 'ops' => 'admin_panel_settings', 'novo' => 'add', 'nova' => 'add', 'editar' => 'edit', 'categorias' => 'category', 'calendario' => 'calendar_month', ]; $segs = array_values(array_filter(explode('/', $path))); $crumbs = [['label' => 'Início', 'url' => '/', 'icon' => 'space_dashboard']]; if ($segs === []) { $crumbs[0] = ['label' => $pageTitle, 'icon' => 'space_dashboard']; } else { $section = $sectionMap[$segs[0]] ?? ['label' => ucfirst($segs[0]), 'icon' => 'chevron_right']; $sectionLabel = $section['label']; if (count($segs) > 1 && $segs[0] !== 'perfil' && $segs[0] !== 'buscar') { $crumbs[] = ['label' => $sectionLabel, 'url' => '/' . $segs[0], 'icon' => $section['icon']]; } $currentLabel = $pageTitle; if (count($segs) > 1 && $pageTitle === $sectionLabel) { $currentLabel = $segmentLabels[end($segs)] ?? $pageTitle; } $crumbs[] = [ 'label' => $currentLabel, 'icon' => count($segs) > 1 ? $segmentIcons[end($segs)] ?? 'description' : $section['icon'], ]; } } @endphp is('configuracoes/espelho')) data-preloader-duration="1000" @if (request()->boolean('janela')) data-snapshot-graph-window="1" @endif @endif style="{{ \App\Services\Appearance::cssVariables() }}"> {{-- assets/js/app.js (copiado do original, sem alterações) monta várias URLs de Ajax como caminhos relativos ("tarefas/1", "clientes/2/contatos") — precisam resolver sempre a partir da raiz do app, não da página atual. --}} {{ $pageTitle }} · {{ $appName }} @if (request()->is('financeiro')) @endif {{ $head ?? '' }} @if (session('prompt_aurelio_pin') && !\App\Security\AurelioPin::configured($user)) shield_lock Proteja sua sessão Cadastre um PIN de 6 dígitos para bloquear e retomar a tela sem sair da conta. Ele também protege consultas sensíveis do Aurélio. @csrf Confirme sua senha @error('current_password') {{ $message }} @enderror PIN 6 dígitos @error('pin') {{ $message }} @enderror Confirmar PIN Agora nãopin Cadastrar PIN @endif chevron_leftRecolher menu menu @foreach ($crumbs as $i => $c) @if ($i > 0) chevron_right @endif @php($isCurrent = empty($c['url']) || $i === count($crumbs) - 1) @if (!$isCurrent) @else @endif {{ $c['icon'] ?? 'chevron_right' }} {{ $c['label'] }} @if (!$isCurrent) @else @endif @endforeach @include('partials.notifications') @include('partials.meeting-navbar') monitor_heart @include('partials.worker-status') @if ($user !== null) @include('partials.ai-usage-gadget') @endif {{ $initials }} expand_more personMeu perfil settingsConfigurações dark_modeTema @csrflogoutSair lockBloquear tela @include('partials.global-search') search more_vert Operação Conta personMeu perfil settingsConfigurações dark_modeTema lockBloquear tela addNova reunião @csrf logoutSair person dark_mode @csrf logout @include('partials.global-search') @yield('content') @foreach ($mobileNavItems as [$href, $icon, $label]) 0) aria-label="Chamados, {{ $activeTicketCount }} ativos" @endif> {{ $icon }}{{ $label }} @if ($href === '/chamados' && $activeTicketCount > 0) {{ $activeTicketCount }} @endif @endforeach @if ($user !== null && !request()->routeIs('float-notes.page')) @include('partials.float-notes') @endif @if (request()->is('saude')) @endif @if (request()->is('sistemas/*/monitoramento')) @endif @if (((config('broadcasting.default') === 'reverb' && config('broadcasting.connections.reverb.key') && config('broadcasting.connections.reverb.options.host')) || (config('broadcasting.default') === 'pusher' && config('broadcasting.connections.pusher.key') && config('broadcasting.connections.pusher.options.cluster'))) && (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot')))) @vite('resources/js/notifications-realtime.js') @endif @if (request()->is('financeiro')) @endif @if ($user !== null) @endif @if ($user !== null) @endif @if ($user !== null) @endif
Cadastre um PIN de 6 dígitos para bloquear e retomar a tela sem sair da conta. Ele também protege consultas sensíveis do Aurélio.