From 64f521adcccbe63eaf4634f2b049ccaa3106e3f8 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sat, 11 Apr 2026 14:43:54 +0700 Subject: [PATCH] feat: add company-specific dashboard stats and cooperation status chart with role-based filtering --- app/Filament/Pages/Dashboard.php | 2 + .../Widgets/Charts/CooperationStatusChart.php | 9 ++++ app/Filament/Widgets/Stats/OverviewStats.php | 54 +++++++++++++++++++ database/seeders/ShieldSeeder.php | 6 ++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/app/Filament/Pages/Dashboard.php b/app/Filament/Pages/Dashboard.php index c38c038..c4790e8 100644 --- a/app/Filament/Pages/Dashboard.php +++ b/app/Filament/Pages/Dashboard.php @@ -2,6 +2,7 @@ namespace App\Filament\Pages; +use App\Filament\Widgets\Charts\CooperationStatusChart; use App\Filament\Widgets\Stats\OverviewStats; use BezhanSalleh\FilamentShield\Traits\HasPageShield; use Filament\Pages\Dashboard as BaseDashboard; @@ -23,6 +24,7 @@ public function getWidgets(): array { return [ OverviewStats::class, + CooperationStatusChart::class, ]; } } diff --git a/app/Filament/Widgets/Charts/CooperationStatusChart.php b/app/Filament/Widgets/Charts/CooperationStatusChart.php index 3e7c7e8..56f2ec1 100644 --- a/app/Filament/Widgets/Charts/CooperationStatusChart.php +++ b/app/Filament/Widgets/Charts/CooperationStatusChart.php @@ -3,6 +3,7 @@ namespace App\Filament\Widgets\Charts; use App\Enums\CooperationStatus; +use App\Enums\RoleEnum; use App\Models\Cooperation; use BezhanSalleh\FilamentShield\Traits\HasWidgetShield; use Filament\Widgets\ChartWidget; @@ -25,9 +26,17 @@ protected function getData(): array $startDate = $this->filters['startDate'] ?? null; $endDate = $this->filters['endDate'] ?? null; + $user = auth()->user(); + $data = Cooperation::query() ->when($startDate, fn ($q) => $q->whereDate('created_at', '>=', $startDate)) ->when($endDate, fn ($q) => $q->whereDate('created_at', '<=', $endDate)) + ->when($user && $user->hasRole(RoleEnum::PERUSAHAAN->value), function ($query) use ($user) { + $partnerMediaId = $user->company?->partnerMedia?->id; + $query->whereHas('partnerMedia', function ($q) use ($partnerMediaId) { + $q->where('partner_media.id', $partnerMediaId); + }); + }) ->selectRaw('status, count(*) as total') ->groupBy('status') ->get(); diff --git a/app/Filament/Widgets/Stats/OverviewStats.php b/app/Filament/Widgets/Stats/OverviewStats.php index 80d55e9..cc801a1 100644 --- a/app/Filament/Widgets/Stats/OverviewStats.php +++ b/app/Filament/Widgets/Stats/OverviewStats.php @@ -4,6 +4,7 @@ use App\Enums\IsActive; use App\Enums\IssueSentiment; +use App\Enums\RoleEnum; use App\Models\Classification; use App\Models\CooperationPayment; use App\Models\DataChangeRequest; @@ -31,6 +32,12 @@ class OverviewStats extends BaseWidget protected function getStats(): array { + $user = auth()->user(); + + if ($user && $user->hasRole(RoleEnum::PERUSAHAAN->value)) { + return $this->getCompanyStats($user); + } + $totalJournalists = Journalist::count(); $totalMedia = PartnerMedia::count(); $average = $totalMedia > 0 ? round($totalJournalists / $totalMedia, 1) : 0; @@ -114,4 +121,51 @@ private function getRandomColor(): string { return $this->availableColors[array_rand($this->availableColors)]; } + + private function getCompanyStats($user): array + { + $company = $user->company; + + if (! $company) { + return [ + Stat::make('Status Perusahaan', 'Belum Terdaftar') + ->description('Silakan lengkapi profil perusahaan') + ->color('danger'), + ]; + } + + $journalistCount = $company->journalists()->count(); + $cooperationCount = 0; + + if ($company->partnerMedia) { + $cooperationCount = $company->partnerMedia->cooperations()->count(); + } + + $verificationStatus = $company->verificationRequest?->status?->getLabel() ?? 'Belum Mengajukan'; + $verificationColor = $company->verificationRequest?->status?->getColor() ?? 'gray'; + + $dataChangeRequestsCount = $company->dataChangeRequests()->pending()->count() + $user->dataChangeRequests()->pending()->count(); + + return [ + Stat::make('Status Verifikasi', $verificationStatus) + ->description('Status verifikasi perusahaan') + ->descriptionIcon('heroicon-o-shield-check') + ->color($verificationColor), + + Stat::make('Total Jurnalis', $journalistCount) + ->description('Jurnalis terdaftar') + ->descriptionIcon('heroicon-o-users') + ->color($this->getRandomColor()), + + Stat::make('Total Kerjasama', $cooperationCount) + ->description('Kerjasama diajukan/diikuti') + ->descriptionIcon('heroicon-o-hand-raised') + ->color($this->getRandomColor()), + + Stat::make('Antrean Perubahan Data', $dataChangeRequestsCount) + ->description('Perubahan data menunggu persetujuan') + ->descriptionIcon('heroicon-o-document-text') + ->color($this->getRandomColor()), + ]; + } } diff --git a/database/seeders/ShieldSeeder.php b/database/seeders/ShieldSeeder.php index 0386382..dd684cd 100644 --- a/database/seeders/ShieldSeeder.php +++ b/database/seeders/ShieldSeeder.php @@ -692,11 +692,11 @@ public function run(): void "name": "Perusahaan", "guard_name": "web", "permissions": [ - "View:Analytic", - "ViewAny:Cooperation", "View:Cooperation", + "View:CooperationStatusChart", + "View:Company", "View:Dashboard", @@ -712,6 +712,8 @@ public function run(): void "View:Media", + "View:OverviewStats", + "View:Verification" ] }