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.
This commit is contained in:
parent
98535a3c03
commit
2a7b1cf875
48
app/Filament/Widgets/MediaClassificationChart.php
Normal file
48
app/Filament/Widgets/MediaClassificationChart.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\MediaClassification;
|
||||
use App\Models\PartnerMedia;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class MediaClassificationChart extends ChartWidget
|
||||
{
|
||||
protected ?string $heading = 'Klasifikasi Media';
|
||||
|
||||
protected static ?int $sort = 3;
|
||||
|
||||
protected int|string|array $columnSpan = 1;
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$data = PartnerMedia::query()
|
||||
->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';
|
||||
}
|
||||
}
|
||||
47
app/Filament/Widgets/MediaRegistrationChart.php
Normal file
47
app/Filament/Widgets/MediaRegistrationChart.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\PartnerMedia;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class MediaRegistrationChart extends ChartWidget
|
||||
{
|
||||
protected ?string $heading = 'Tren Pendaftaran Media';
|
||||
|
||||
protected static ?int $sort = 4;
|
||||
|
||||
protected int|string|array $columnSpan = 'full';
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$data = PartnerMedia::query()
|
||||
->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';
|
||||
}
|
||||
}
|
||||
53
app/Filament/Widgets/MediaTypeChart.php
Normal file
53
app/Filament/Widgets/MediaTypeChart.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\MediaType;
|
||||
use App\Models\PartnerMedia;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class MediaTypeChart extends ChartWidget
|
||||
{
|
||||
protected ?string $heading = 'Distribusi Jenis Media';
|
||||
|
||||
protected static ?int $sort = 2;
|
||||
|
||||
protected int|string|array $columnSpan = 1;
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$data = PartnerMedia::query()
|
||||
->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';
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,8 @@ class OverviewStats extends BaseWidget
|
||||
{
|
||||
protected static ?int $sort = 1;
|
||||
|
||||
protected int|string|array $columnSpan = 'full';
|
||||
|
||||
protected function getStats(): array
|
||||
{
|
||||
return [
|
||||
|
||||
40
app/Filament/Widgets/TopMediaJournalistChart.php
Normal file
40
app/Filament/Widgets/TopMediaJournalistChart.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\PartnerMedia;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class TopMediaJournalistChart extends ChartWidget
|
||||
{
|
||||
protected ?string $heading = 'Top Media Berdasarkan Jumlah Jurnalis';
|
||||
|
||||
protected static ?int $sort = 5;
|
||||
|
||||
protected int|string|array $columnSpan = 'full';
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$data = PartnerMedia::query()
|
||||
->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';
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user