From 2a7b1cf87508a751bea2db4e9dbb24b21cdc1b69 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 29 Jan 2026 10:17:54 +0700 Subject: [PATCH] feat: Introduce new Filament chart widgets for media classification, registration trends, type distribution, and top media by journalist count, and update the OverviewStats widget's column span. --- .../Widgets/MediaClassificationChart.php | 48 +++++++++++++++++ .../Widgets/MediaRegistrationChart.php | 47 ++++++++++++++++ app/Filament/Widgets/MediaTypeChart.php | 53 +++++++++++++++++++ app/Filament/Widgets/OverviewStats.php | 2 + .../Widgets/TopMediaJournalistChart.php | 40 ++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 app/Filament/Widgets/MediaClassificationChart.php create mode 100644 app/Filament/Widgets/MediaRegistrationChart.php create mode 100644 app/Filament/Widgets/MediaTypeChart.php create mode 100644 app/Filament/Widgets/TopMediaJournalistChart.php diff --git a/app/Filament/Widgets/MediaClassificationChart.php b/app/Filament/Widgets/MediaClassificationChart.php new file mode 100644 index 0000000..960cd03 --- /dev/null +++ b/app/Filament/Widgets/MediaClassificationChart.php @@ -0,0 +1,48 @@ +selectRaw('classification, count(*) as total') + ->groupBy('classification') + ->get(); + + $labels = []; + $counts = []; + + foreach (MediaClassification::cases() as $case) { + $labels[] = $case->getLabel(); + $counts[] = $data->where('classification', $case)->first()?->total ?? 0; + } + + return [ + 'datasets' => [ + [ + 'label' => 'Jumlah Media', + 'data' => $counts, + 'backgroundColor' => '#4F46E5', + ], + ], + 'labels' => $labels, + ]; + } + + protected function getType(): string + { + return 'bar'; + } +} diff --git a/app/Filament/Widgets/MediaRegistrationChart.php b/app/Filament/Widgets/MediaRegistrationChart.php new file mode 100644 index 0000000..9193d09 --- /dev/null +++ b/app/Filament/Widgets/MediaRegistrationChart.php @@ -0,0 +1,47 @@ +select( + DB::raw('COUNT(*) as count'), + DB::raw("DATE_FORMAT(created_at, '%Y-%m') as month") + ) + ->where('created_at', '>=', now()->subMonths(6)) + ->groupBy('month') + ->orderBy('month') + ->get(); + + return [ + 'datasets' => [ + [ + 'label' => 'Media Baru', + 'data' => $data->pluck('count')->toArray(), + 'fill' => 'start', + 'borderColor' => '#10B981', + 'backgroundColor' => 'rgba(16, 185, 129, 0.1)', + ], + ], + 'labels' => $data->pluck('month')->map(fn ($m) => \Carbon\Carbon::createFromFormat('Y-m', $m)->translatedFormat('M Y'))->toArray(), + ]; + } + + protected function getType(): string + { + return 'line'; + } +} diff --git a/app/Filament/Widgets/MediaTypeChart.php b/app/Filament/Widgets/MediaTypeChart.php new file mode 100644 index 0000000..26d65f6 --- /dev/null +++ b/app/Filament/Widgets/MediaTypeChart.php @@ -0,0 +1,53 @@ +selectRaw('type, count(*) as total') + ->groupBy('type') + ->get(); + + $labels = []; + $counts = []; + + foreach (MediaType::cases() as $case) { + $labels[] = $case->getLabel(); + $counts[] = $data->where('type', $case)->first()?->total ?? 0; + } + + return [ + 'datasets' => [ + [ + 'label' => 'Jumlah Media', + 'data' => $counts, + 'backgroundColor' => [ + '#36A2EB', + '#FF6384', + '#FFCE56', + '#4BC0C0', + ], + ], + ], + 'labels' => $labels, + ]; + } + + protected function getType(): string + { + return 'pie'; + } +} diff --git a/app/Filament/Widgets/OverviewStats.php b/app/Filament/Widgets/OverviewStats.php index c359ecf..174ff08 100644 --- a/app/Filament/Widgets/OverviewStats.php +++ b/app/Filament/Widgets/OverviewStats.php @@ -16,6 +16,8 @@ class OverviewStats extends BaseWidget { protected static ?int $sort = 1; + protected int|string|array $columnSpan = 'full'; + protected function getStats(): array { return [ diff --git a/app/Filament/Widgets/TopMediaJournalistChart.php b/app/Filament/Widgets/TopMediaJournalistChart.php new file mode 100644 index 0000000..c95bbed --- /dev/null +++ b/app/Filament/Widgets/TopMediaJournalistChart.php @@ -0,0 +1,40 @@ +withCount('journalists') + ->orderByDesc('journalists_count') + ->limit(10) + ->get(); + + return [ + 'datasets' => [ + [ + 'label' => 'Jumlah Jurnalis', + 'data' => $data->pluck('journalists_count')->toArray(), + 'backgroundColor' => '#F59E0B', + ], + ], + 'labels' => $data->pluck('name')->toArray(), + ]; + } + + protected function getType(): string + { + return 'bar'; + } +}