@php
$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,
'documents_total' => 0,
'documents_draft' => 0,
'documents_under_review' => 0,
'documents_approved' => 0,
'documents_active' => 0,
'documents_obsolete' => 0,
'documents_pending_my_approval' => 0,
'documents_review_due' => 0,
];
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
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) {}
// ─── Document Control ───────────────────────────
try {
if (class_exists(\App\Models\Document::class)) {
$c['documents_total'] = \App\Models\Document::query()->count();
$c['documents_draft'] = \App\Models\Document::query()
->where('document_status', 'Draft')->count();
$c['documents_under_review'] = \App\Models\Document::query()
->where('document_status', 'Under Review')->count();
$c['documents_approved'] = \App\Models\Document::query()
->where('document_status', 'Approved')->count();
$c['documents_active'] = \App\Models\Document::query()
->where('document_status', 'Approved')
->where(function ($q) {
$q->whereNull('expiry_date')
->orWhereDate('expiry_date', '>=', now()->toDateString());
})->count();
$c['documents_obsolete'] = \App\Models\Document::query()
->whereIn('document_status', ['Obsolete', 'Archived'])->count();
if (auth()->check()) {
$c['documents_pending_my_approval'] = \App\Models\Document::query()
->where('document_status', 'Under Review')
->where(function ($q) {
$q->where('approver_id', auth()->id())
->orWhere('created_by', auth()->id());
})->count();
}
$c['documents_review_due'] = \App\Models\Document::query()
->whereNotNull('review_date')
->whereDate('review_date', '<=', now()->addDays(30)->toDateString())
->whereDate('review_date', '>=', now()->toDateString())
->whereNotIn('document_status', ['Obsolete', 'Archived'])->count();
}
} catch (\Throwable $e) {}
return $c;
})();
$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;
};
// Helper to check a route exists before rendering its link
$hasRoute = fn(string $name) => \Illuminate\Support\Facades\Route::has($name);
// ─── Document Control permissions ─────────────────────
$canViewDocuments = $can('documents.view');
$canCreateDocument = $can('documents.create');
$canEditDocument = $can('documents.edit');
$canApproveDocument = $can('documents.approve');
$canViewDocControl = $can('doc_control.view');
$canViewDocumentTypes = $can('document_types.view');
// ─── Lab SOP ──────────────────────────────────────────
$canViewLabSop = $can('lab_sop.view');
$canCreateLabSop = $can('lab_sop.create');
// ─── Other modules ────────────────────────────────────
$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 --}}
@hasSection('page-header')
@yield('page-header')
@else
@yield('title', 'Dashboard')
@yield('header-actions')
@endif
@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
@yield('content')