user(); if ($user->hasRole('Admin')) { return redirect()->route('admin.dashboard'); } if ($user->hasRole('Admin Kewangan')) { return redirect()->route('kewangan.dashboard'); } if ($user->hasRole('PPM')) { return redirect()->route('ppm.dashboard'); } if ($user->hasRole('KTM')) { return redirect()->route('ktm.dashboard'); } if ($user->hasRole('Pemohon')) { return redirect()->route('pemohon.dashboard'); } return view('dashboards.index', $this->payload( 'Dashboard', 'Akaun ini belum mempunyai peranan sistem.', 'Hubungi Admin untuk penetapan peranan.', [ ['label' => 'Peranan aktif', 'value' => '0', 'icon' => 'bi-shield-lock', 'tone' => 'secondary'], ['label' => 'Akses modul', 'value' => 'Belum aktif', 'icon' => 'bi-door-closed', 'tone' => 'secondary'], ], )); } public function admin(PennempatanService $pennempatanService): View { $pusatsWithVacancy = $pennempatanService->pusatsWithVacancySummary(); return view('dashboards.admin', [ 'cards' => [ ['label' => 'Pusat Mengundi', 'value' => (string) PusatMengundi::query()->count(), 'icon' => 'bi-building', 'tone' => 'primary'], ['label' => 'Saluran', 'value' => (string) SaluranMengundi::query()->count(), 'icon' => 'bi-diagram-3', 'tone' => 'info'], ['label' => 'Pemohon', 'value' => (string) Application::query()->count(), 'icon' => 'bi-people', 'tone' => 'success'], ['label' => 'Staf Aktif', 'value' => (string) StaffAssignment::query()->where('status', 'active')->count(), 'icon' => 'bi-person-check', 'tone' => 'success'], ], 'pusatsWithVacancy' => $pusatsWithVacancy, ]); } public function kewangan(): View { $missingBankStatement = BankVerification::query() ->whereHas('application', fn ($query) => $query->whereIn('status', ['approved', 'assigned'])) ->whereHas('application', fn ($query) => $query->whereDoesntHave('documents', fn ($documentQuery) => $documentQuery->where('document_type', 'bank_statement'))) ->count(); return view('dashboards.index', $this->payload( 'Dashboard Admin Kewangan', 'Semakan bank dan dokumen kewangan', 'Paparan asas untuk status verifikasi bank tanpa akses perubahan penempatan.', [ ['label' => 'Pending bank', 'value' => (string) BankVerification::query()->where('status', 'pending')->whereHas('application', fn ($query) => $query->whereIn('status', ['approved', 'assigned']))->count(), 'icon' => 'bi-bank', 'tone' => 'warning'], ['label' => 'Dokumen hilang', 'value' => (string) $missingBankStatement, 'icon' => 'bi-file-earmark-x', 'tone' => 'danger'], ['label' => 'Ditolak', 'value' => (string) BankVerification::query()->where('status', 'rejected')->count(), 'icon' => 'bi-x-circle', 'tone' => 'danger'], ['label' => 'Perlu pembetulan', 'value' => (string) BankVerification::query()->where('status', 'requires_correction')->count(), 'icon' => 'bi-pencil-square', 'tone' => 'info'], ], [ ['label' => 'Senarai staf diluluskan', 'route' => 'kewangan.bank.index'], ['label' => 'Semakan akaun bank', 'route' => 'kewangan.bank.index'], ['label' => 'Export finance list', 'route' => 'kewangan.bank.export'], ], )); } public function ppm(Request $request, PpmScopeService $scopeService): View { $pusatIds = $scopeService->assignedPusatIds($request->user()); return view('dashboards.index', $this->payload( 'Dashboard PPM', 'Pengurusan Pusat Mengundi sendiri', 'Paparan asas untuk semakan permohonan, tugasan saluran, wakil agensi, dan kehadiran.', [ ['label' => 'Pusat jagaan', 'value' => (string) $pusatIds->count(), 'icon' => 'bi-geo-alt', 'tone' => 'primary'], ['label' => 'Permohonan pending', 'value' => (string) Application::query()->whereIn('pusat_mengundi_id', $pusatIds)->whereIn('status', ['submitted', 'under_ppm_review'])->count(), 'icon' => 'bi-inbox', 'tone' => 'warning'], ['label' => 'Staf aktif', 'value' => (string) StaffAssignment::query()->whereIn('pusat_mengundi_id', $pusatIds)->where('status', 'active')->count(), 'icon' => 'bi-person-check', 'tone' => 'success'], ['label' => 'Kehadiran hadir', 'value' => (string) Attendance::query()->whereIn('pusat_mengundi_id', $pusatIds)->where('status', 'present')->count(), 'icon' => 'bi-check2-circle', 'tone' => 'info'], ], [ ['label' => 'Semak permohonan', 'route' => 'ppm.applications.index'], ['label' => 'Rekod kehadiran', 'route' => 'ppm.attendance.index'], 'Assign KTM/KP/KPDP', ], )); } public function ktm(Request $request, KtmScopeService $scopeService, KtmVacancyService $vacancyService): View { $assignments = $scopeService->assignmentsFor($request->user()); $assignmentIds = $assignments->pluck('id'); $kpVacancy = $assignments->sum(fn (StaffAssignment $assignment): int => $vacancyService->remainingForAssignment($assignment, 'KP')); return view('dashboards.index', $this->payload( 'Dashboard KTM', 'Pengurusan pasukan KP sendiri', 'Paparan asas untuk saluran ditugaskan, kekosongan KP, dan pendaftaran KP.', [ ['label' => 'Saluran ditugaskan', 'value' => (string) $assignments->count(), 'icon' => 'bi-signpost', 'tone' => 'primary'], ['label' => 'KP aktif', 'value' => (string) StaffAssignment::query()->whereIn('reports_to_assignment_id', $assignmentIds)->where('status', 'active')->count(), 'icon' => 'bi-people', 'tone' => 'success'], ['label' => 'Kekosongan KP', 'value' => (string) $kpVacancy, 'icon' => 'bi-person-plus', 'tone' => 'warning'], ], [ ['label' => 'Senarai KP', 'route' => 'ktm.applications.index'], ['label' => 'Daftar KP', 'route' => 'ktm.applications.create'], 'Semak permohonan KP', ], )); } public function pemohon(): View { return view('dashboards.index', $this->payload( 'Dashboard Pemohon', 'Status permohonan', 'Akaun Pemohon akan digunakan jika portal status kendiri diaktifkan dalam fasa akan datang.', [ ['label' => 'Permohonan', 'value' => '0', 'icon' => 'bi-file-text', 'tone' => 'secondary'], ['label' => 'Status', 'value' => 'Belum aktif', 'icon' => 'bi-info-circle', 'tone' => 'info'], ], )); } /** * @param array $cards * @param array $actions * @return array */ private function payload(string $title, string $eyebrow, string $description, array $cards, array $actions = []): array { return compact('title', 'eyebrow', 'description', 'cards', 'actions'); } }