Laravel Filament 3 Global Dashboard Filters 学習メモ

Laravel Filament 3 Global Dashboard Filters 学習メモ

Global Dashbord Filters

Filament のダッシュボードに日付などのフィルタをセットしchartのフィルタにも反映してみる。

参考ドキュメントは、

https://filamentphp.com/docs/3.x/panels/dashboard#customizing-the-dashboard-page

/App/Filament/Pages/Dashbord.php の新規作成

<?php

namespace App\Filament\Pages;

use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Section;
use Filament\Forms\Form;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;

class Dashboard extends \Filament\Pages\Dashboard
{
    use HasFiltersForm;

    public function filtersForm(Form $form): Form
    {
        return $form->schema([
            Section::make('')->schema([
                TextInput::make('name'),
                DatePicker::make('startDate'),
                DatePicker::make('endDate'),
                Toggle::make('active'),
            ])->columns(4)
        ]);
    }
}

/App/Providers/Filament/AdminPanelProvider.php の編集

<?php

namespace App\Providers\Filament;

use App\Filament\Widgets\TestWidget;
use App\Filament\Resources\CommentResource\Widgets\LatestCommentsWidget;
use App\Filament\Resources\PostResource\Widgets\PostsPerMonthChart;
use App\Filament\Resources\UserResource\Widgets\UserStatsWidget;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Pages;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Filament\Widgets;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->login()
            ->colors([
                'primary' => Color::Amber,
            ])
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
            ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
            ->pages([
                \App\Filament\Pages\Dashboard::class,
            ])
            ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
            ->widgets([
                // UserStatsWidget::class,
                // PostsPerMonthChart::class,
                // LatestCommentsWidget::class
                TestWidget::class,
            ])
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([
                Authenticate::class,
            ]);
    }
}

/App/Filament/Widgets/TestChartWidget.php の編集

<?php

namespace App\Filament\Widgets;

use App\Models\User;
use Filament\Widgets\ChartWidget;
use Flowframe\Trend\Trend;
use Flowframe\Trend\TrendValue;
use Illuminate\Support\Carbon;

class TestChartWidget extends ChartWidget
{
    use \Filament\Widgets\Concerns\InteractsWithPageFilters;

    protected static ?string $heading = 'Test Chart';

    protected int | string | array $columnSpan = 1;

    protected function getData(): array
    {
        $start = $this->filters['startDate'];
        $end = $this->filters['endDate'];

        $data = Trend::model(User::class)
            ->between(
                start: $start ? Carbon::parse($start) : now()->subMonths(6),
                end: $end ? Carbon::parse($end) : now(),
            )
            ->perMonth()
            ->count();

        // dd($data);
        
        return [
            'datasets' => [
                [
                    'label' => 'Blog posts created',
                    // 'data' => [0, 10, 5, 2, 21, 32, 45, 74, 65, 45, 77, 89],
                    'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
                ],
            ],
            // 'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
            'labels' => $data->map(fn (TrendValue $value) => $value->date),
        ];
    }

    protected function getType(): string
    {
        return 'line';
    }
}

/App/Filament/Widgets/TestWidget.php の編集

<?php

namespace App\Filament\Widgets;

use App\Models\User;
use Filament\Support\Enums\IconPosition;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Carbon;

class TestWidget extends BaseWidget
{
    use \Filament\Widgets\Concerns\InteractsWithPageFilters;

    protected function getStats(): array
    {
        $start = $this->filters['startDate'];
        $end = $this->filters['endDate'];

        return [
            Stat::make('New Users', 
                User::
                when($start,
                    fn ($query) => $query->whereDate('created_at','>',$start)
                )
                ->when($end,
                    fn ($query) => $query->whereDate('created_at','<',$end)
                )
                ->count()
                )
                ->description('New users that have joined')
                ->descriptionIcon('heroicon-m-user-group',IconPosition::Before)
                ->chart([1,3,5,10,20,40])
                ->color('success'),
        ];
    }
}