Коли на дашборді кілька віджетів, зручно мати один набір фільтрів (період, регіон, менеджер), що діє на всі одразу.
1. Власна сторінка дашборда з формою фільтрів:
namespace App\Filament\Pages;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
public function filtersForm(Schema $schema): Schema
{
return $schema
->components([
Section::make()
->schema([
DatePicker::make('startDate'),
DatePicker::make('endDate'),
Select::make('region')->options(Region::class),
])
->columns(3)
->columnSpanFull(),
]);
}
}
Стандартний дашборд треба замінити цим класом (прибрати Dashboard::class зі сторінок панелі чи вимкнути автовиявлення стандартного).
2. Віджети читають фільтри через трейт:
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
class SalesOverview extends StatsOverviewWidget
{
use InteractsWithPageFilters;
protected function getStats(): array
{
$query = Order::query()
->when($this->pageFilters['startDate'] ?? null, fn ($q, $date) => $q->whereDate('created_at', '>=', $date))
->when($this->pageFilters['endDate'] ?? null, fn ($q, $date) => $q->whereDate('created_at', '<=', $date))
->when($this->pageFilters['region'] ?? null, fn ($q, $region) => $q->where('region', $region));
return [
Stat::make('Замовлень', $query->count()),
Stat::make('Виручка', Number::currency((clone $query)->sum('total'), 'UAH', 'uk')),
];
}
}
Коли фільтри змінюються, віджети перезавантажуються з новими значеннями.
Варіанти:
- фільтри можна винести в модальне вікно за кнопкою (
HasFiltersAction) - дашборд лишається компактним; $this->pageFiltersможна зберігати в сесії, щоб вибраний період не скидався при поверненні.
Пастки:
$pageFilters- сирі дані з браузера. Перевіряйте й приводьте їх (дати, значення зі списку), а не підставляйте вwhereRaw;- повторне використання запиту -
count()іsum()на тому самому білдері працюють, але при модифікаціях кращеclone, щоб умови не накопичувалися; - кожна зміна фільтра перераховує всі віджети - для важких метрик потрібне кешування з ключем від фільтрів.