@stack('styles')
{{-- ═══════════════════════════════════════════════════════════ SIDEBAR ═══════════════════════════════════════════════════════════ --}} @php // ─── Compute all sidebar counters ONCE ──────────────── $sidebarCounts = (function () { $c = [ 'notifications' => 0, 'sops' => 0, 'deviations_total' => 0, 'deviations_open' => 0, 'deviations_emergency' => 0, 'deviations_my_action' => 0, 'deviations_capa' => 0, 'deviations_closure' => 0, 'deviations_closed' => 0, 'capa_open' => 0, 'capa_overdue' => 0, 'capa_dashboard' => 0, 'training_pending' => 0, 'training_overdue' => 0, 'training_expiring' => 0, 'training_alerts' => 0, 'approvals_pending' => 0, 'change_control_open' => 0, 'change_control_overdue' => 0, 'complaints_open' => 0, 'complaints_reportable' => 0, 'complaints_overdue' => 0, 'audits_open' => 0, 'audits_in_progress' => 0, 'audits_overdue' => 0, 'audits_open_findings' => 0, 'suppliers_total' => 0, 'suppliers_qualified' => 0, 'suppliers_pending' => 0, 'suppliers_requalification_due' => 0, 'suppliers_overdue' => 0, 'suppliers_gmp_expiring' => 0, 'risk_templates_active' => 0, 'risk_assessments_open' => 0, 'risk_assessments_high' => 0, 'risk_assessments_critical' => 0, ]; // ─── Change Control ───────────────────────────── try { if (class_exists(\App\Models\ChangeControlMaster::class)) { $c['change_control_open'] = \App\Models\ChangeControlMaster::query()->open()->count(); $c['change_control_overdue'] = \App\Models\ChangeControlMaster::query()->overdue()->count(); } } catch (\Throwable $e) {} // ─── Notifications ────────────────────────────── try { if (class_exists(\App\Models\Notification::class) && auth()->check()) { $c['notifications'] = \App\Models\Notification::where('user_id', auth()->id()) ->where('is_read', false)->count(); } } catch (\Throwable $e) {} // ─── Lab SOPs ─────────────────────────────────── try { if (class_exists(\App\Models\LabSopDocument::class)) { $c['sops'] = \App\Models\LabSopDocument::where('doc_type', 'Prefilled_doc') ->whereNull('deleted_at')->count(); } } catch (\Throwable $e) {} // ─── Deviations ───────────────────────────────── try { if (class_exists(\App\Models\DeviationMaster::class)) { $c['deviations_total'] = \App\Models\DeviationMaster::query()->count(); $c['deviations_open'] = \App\Models\DeviationMaster::query()->open()->count(); $c['deviations_emergency'] = \App\Models\DeviationMaster::query()->emergency() ->whereNotIn('status', ['CLOSED', 'REJECTED'])->count(); $c['deviations_capa'] = \App\Models\DeviationMaster::query() ->where('status', 'AWAITING_CAPA')->count(); $c['deviations_closure'] = \App\Models\DeviationMaster::query() ->where('status', 'AWAITING_CLOSURE')->count(); $c['deviations_closed'] = \App\Models\DeviationMaster::query() ->where('status', 'CLOSED') ->whereMonth('updated_at', now()->month) ->whereYear('updated_at', now()->year)->count(); if (class_exists(\App\Models\DeviationAction::class) && auth()->check()) { $c['deviations_my_action'] = \App\Models\DeviationAction::where('assigned_to', auth()->id()) ->whereNotIn('status', ['COMPLETED', 'VERIFIED']) ->whereHas('deviation', fn ($q) => $q->whereNotIn('status', ['CLOSED', 'REJECTED'])) ->count(); } } } catch (\Throwable $e) {} // ─── CAPA ─────────────────────────────────────── try { if (class_exists(\App\Models\CapaRequest::class)) { $c['capa_open'] = \App\Models\CapaRequest::query()->open()->count(); $c['capa_overdue'] = \App\Models\CapaRequest::query()->overdue()->count(); $c['capa_dashboard'] = \App\Models\CapaRequest::query() ->whereIn('status', ['UNDER_REVIEW', 'EFFECTIVENESS_CHECK'])->count(); } } catch (\Throwable $e) {} // ─── Complaints ───────────────────────────────── try { if (class_exists(\App\Models\Complaint::class)) { $c['complaints_open'] = \App\Models\Complaint::query() ->whereNotIn('current_status', ['CLOSED', 'REJECTED']) ->count(); $c['complaints_reportable'] = \App\Models\Complaint::query() ->where('is_reportable', true) ->whereNull('report_submitted_date') ->whereNotIn('current_status', ['CLOSED', 'REJECTED']) ->count(); $c['complaints_overdue'] = \App\Models\Complaint::query() ->where('is_reportable', true) ->whereNull('report_submitted_date') ->whereDate('report_due_date', '<', now()->toDateString()) ->whereNotIn('current_status', ['CLOSED', 'REJECTED']) ->count(); } } catch (\Throwable $e) {} // ─── Audits ───────────────────────────────────── try { if (class_exists(\App\Models\Audit::class)) { $c['audits_open'] = \App\Models\Audit::query() ->whereNotIn('current_status', ['CLOSED', 'CANCELLED'])->count(); $c['audits_in_progress'] = \App\Models\Audit::query() ->where('current_status', 'IN_PROGRESS')->count(); $c['audits_overdue'] = \App\Models\Audit::query() ->whereDate('planned_end_date', '<', now()->toDateString()) ->whereNotIn('current_status', ['CLOSED', 'CANCELLED'])->count(); if (class_exists(\App\Models\AuditFinding::class)) { $c['audits_open_findings'] = \App\Models\AuditFinding::query() ->whereNotIn('status', ['CLOSED', 'ACCEPTED'])->count(); } } } catch (\Throwable $e) {} // ─── Suppliers ────────────────────────────────── try { if (class_exists(\App\Models\Supplier::class)) { $c['suppliers_total'] = \App\Models\Supplier::query()->count(); $c['suppliers_qualified'] = \App\Models\Supplier::query() ->where('current_status', 'QUALIFIED')->count(); $c['suppliers_pending'] = \App\Models\Supplier::query() ->where('current_status', 'PENDING_QUALIFICATION')->count(); $c['suppliers_requalification_due'] = \App\Models\Supplier::query() ->whereDate('next_requalification_date', '<=', now()->addDays(60)->toDateString()) ->whereNotIn('current_status', ['DISQUALIFIED']) ->count(); $c['suppliers_overdue'] = \App\Models\Supplier::query() ->whereDate('next_requalification_date', '<', now()->toDateString()) ->whereNotIn('current_status', ['DISQUALIFIED']) ->count(); $c['suppliers_gmp_expiring'] = \App\Models\Supplier::query() ->whereNotNull('gmp_certificate_expiry') ->whereDate('gmp_certificate_expiry', '<=', now()->addDays(60)->toDateString()) ->whereDate('gmp_certificate_expiry', '>=', now()->toDateString()) ->count(); } } catch (\Throwable $e) {} // ─── Risk Management ──────────────────────────── try { if (class_exists(\App\Models\RiskAssessmentTemplate::class)) { $c['risk_templates_active'] = \App\Models\RiskAssessmentTemplate::query() ->where('status', 'ACTIVE')->count(); } if (class_exists(\App\Models\RiskAssessment::class)) { $c['risk_assessments_open'] = \App\Models\RiskAssessment::query() ->whereIn('status', ['DRAFT', 'IN_PROGRESS', 'COMPLETED'])->count(); $c['risk_assessments_high'] = \App\Models\RiskAssessment::query() ->where('outcome', 'HIGH') ->whereNotIn('status', ['SUPERSEDED']) ->count(); $c['risk_assessments_critical'] = \App\Models\RiskAssessment::query() ->where('outcome', 'CRITICAL') ->whereNotIn('status', ['SUPERSEDED']) ->count(); } } catch (\Throwable $e) {} // ─── Training ─────────────────────────────────── try { if (class_exists(\App\Models\QmsTraining::class) && auth()->check()) { $c['training_pending'] = \App\Models\QmsTraining::whereIn('status', ['Scheduled', 'In Progress']) ->where('employee_id', auth()->id())->count(); $c['training_overdue'] = \App\Models\QmsTraining::overdue() ->where('employee_id', auth()->id())->count(); } if (class_exists(\App\Models\EmployeeCompetency::class)) { $c['training_expiring'] = \App\Models\EmployeeCompetency::expiringSoon(30)->count(); } if (class_exists(\App\Models\TrainingNotification::class) && auth()->check()) { $c['training_alerts'] = \App\Models\TrainingNotification::where('user_id', auth()->id()) ->where('is_read', false)->count(); } } catch (\Throwable $e) {} // ─── Approvals ────────────────────────────────── try { if (class_exists(\App\Models\UniversalApprovalInstance::class) && auth()->check()) { $roleName = auth()->user()->role?->name; $c['approvals_pending'] = \App\Models\UniversalApprovalInstance::query() ->whereIn('status', ['PENDING', 'IN_PROGRESS']) ->where(function ($q) use ($roleName) { $q->where('initiated_by', auth()->id()) ->orWhereHas('workflow.steps', function ($s) use ($roleName) { $s->where('approver_user_id', auth()->id()); if ($roleName) $s->orWhere('required_role', $roleName); }); }) ->count(); } } catch (\Throwable $e) {} return $c; })(); // ─── Permission flags (compute once) ────────────────── $u = auth()->user(); $isSuperAdmin = $u && method_exists($u, 'isSuperAdmin') ? $u->isSuperAdmin() : false; $isAdmin = $u && method_exists($u, 'isAdmin') ? $u->isAdmin() : false; $can = function (string $permission) use ($u, $isSuperAdmin) { if ($isSuperAdmin) return true; if (! $u) return false; if (method_exists($u, 'can') && $u->can($permission)) return true; if (str_contains($permission, '.')) { [$resource, $action] = explode('.', $permission, 2); if (method_exists($u, 'can') && $u->can($resource, $action)) return true; } return false; }; $canViewDocuments = $can('documents.view'); $canViewLabSop = $can('lab_sop.view'); $canCreateLabSop = $can('lab_sop.create'); $canViewDeviations = $can('deviations.view'); $canCreateDeviation = $can('deviations.create'); $canViewCompliance = $can('deviations.compliance.view'); $canViewCapa = $can('capa.view'); $canViewWorkflows = $can('workflows.view'); $canViewApprovals = $can('approvals.view'); $canViewComplaints = $can('complaints.view'); $canCreateComplaint = $can('complaints.create'); $canViewAudits = $can('audits.view'); $canCreateAudit = $can('audits.create'); $canViewSuppliers = $can('suppliers.view'); $canCreateSupplier = $can('suppliers.create'); $canApproveQualification = $can('suppliers.approve_qualification'); $canViewRiskTemplates = $can('risk_templates.view'); $canCreateRiskTemplate = $can('risk_templates.create'); $canViewRiskAssessments = $can('risk_assessments.view'); $canCreateRiskAssessment = $can('risk_assessments.create'); $canViewKpi = $can('kpi.view'); @endphp {{-- End of Sidebar --}} {{-- ═══════════════════════════════════════════════════════════ CONTENT WRAPPER ═══════════════════════════════════════════════════════════ --}}
{{-- Topbar --}} {{-- End Topbar --}} {{-- Begin Page Content --}}
{{-- Page heading --}} @hasSection('page-header') @yield('page-header') @else

@yield('title', 'Dashboard')

@yield('header-actions')
@endif {{-- ═══════════════════════════════════════════════════ FLASH MESSAGES ═══════════════════════════════════════════════════ --}} @if(session('success'))
{{ session('success') }}
@endif @if(session('warning'))
{{ session('warning') }}
@endif @if(session('error'))
{{ session('error') }} @if(session('missing') && count(session('missing')))
Missing prerequisites:
    @foreach(session('missing') as $m)
  • {{ $m }}
  • @endforeach
@endif
@endif @if(session('info'))
{{ session('info') }}
@endif @if($errors->any())
    @foreach($errors->all() as $e)
  • {{ $e }}
  • @endforeach
@endif {{-- ═══════════════════════════════════════════════════ PAGE CONTENT ═══════════════════════════════════════════════════ --}} @yield('content')
{{-- /.container-fluid --}}
{{-- End of Main Content --}}
{{-- End of Content Wrapper --}}
{{-- End of Page Wrapper --}} {{-- Scroll to Top --}} {{-- Logout Modal --}} {{-- JavaScript --}} @stack('scripts')