Widget Dashboard Filament yang Informatif

Setiap kali saya buka panel admin Filament di project baru, hal pertama yang biasanya dibuat orang adalah widget statistik di dashboard. Jumlah user, jumlah transaksi, jumlah item — angka besar, warna cerah, ikon menarik. Masalahnya, setelah dipakai beberapa minggu, widget seperti ini sering berakhir diabaikan. Staf lewat begitu saja karena angka itu tidak menjawab pertanyaan yang sebenarnya mereka punya: "ini normal atau tidak", "perlu saya tindak lanjuti atau tidak", "lebih baik atau lebih buruk dari biasanya". Di sistem yang saya kerjakan sehari-hari, mulai dari aplikasi internal sampai sistem yang dipakai fasilitas kesehatan, saya belajar bahwa widget dashboard yang bagus bukan soal menampilkan data sebanyak mungkin, tapi soal menjawab pertanyaan operasional dengan cepat.

Mulai dari pertanyaan staf, bukan dari kolom database

Kesalahan paling umum saat membuat widget adalah berangkat dari struktur data: "tabel ini punya kolom status, jadi tampilkan hitungan per status." Pendekatan ini menghasilkan widget yang benar secara teknis tapi tidak relevan secara operasional. Cara yang lebih baik adalah duduk dulu dan tanya ke pengguna widget-nya: "kalau kamu buka dashboard ini pagi hari, kamu mau tahu apa duluan?" Jawabannya biasanya bukan angka absolut, tapi sesuatu yang butuh perhatian — antrean yang menumpuk, item yang mendekati tenggat, atau tren yang menyimpang dari biasanya.

Di Filament, ini biasanya berarti widget StatsOverviewWidget tidak cukup hanya diisi Stat::make() dengan angka polos. Saya lebih suka menambahkan konteks perbandingan, misalnya:

Stat::make('Antrean Hari Ini', $total)
    ->description($selisih >= 0 ? "+{$selisih} dari kemarin" : "{$selisih} dari kemarin")
    ->descriptionIcon($selisih >= 0 ? 'heroicon-m-arrow-trending-up' : 'heroicon-m-arrow-trending-down')
    ->color($selisih > $ambangBatas ? 'danger' : 'success')

Perhatikan bagian warna: bukan sekadar hijau untuk angka tinggi dan merah untuk angka rendah, tapi warna yang mencerminkan apakah situasi ini butuh tindakan. Angka tinggi bisa saja bagus (penjualan) atau buruk (antrean menumpuk), tergantung konteks bisnisnya. Widget yang informatif selalu mempertimbangkan arah nilai itu, bukan cuma besarnya.

Beri ambang batas, bukan cuma tren

Tren naik-turun itu penting, tapi sering tidak cukup. Staf biasanya tidak punya waktu menghafal berapa angka "normal" untuk tiap metrik, jadi widget sebaiknya menyimpan logika itu sendiri lewat ambang batas eksplisit. Misalnya, sebagai ilustrasi saja, kalau rata-rata waktu tunggu di suatu proses biasanya di bawah 15 menit, widget bisa langsung memberi warna peringatan begitu melewati angka itu, tanpa staf perlu menghitung sendiri.

Filament memudahkan ini karena Stat menerima warna, ikon, dan deskripsi secara dinamis, sehingga logika ambang batas bisa ditaruh di method widget, bukan di template Blade. Saya biasanya taruh angka ambang batas sebagai konstanta atau, lebih baik lagi, sebagai setting yang bisa diubah admin lewat Filament sendiri — jadi ketika kondisi operasional berubah, tidak perlu deploy ulang kode hanya untuk menggeser angka "normal".

Satu hal yang sering terlewat: query widget stat dijalankan setiap kali dashboard dibuka, kadang oleh banyak user sekaligus. Untuk metrik yang query-nya berat, sebaiknya di-cache dengan durasi pendek, misalnya:

protected function getStats(): array
{
    $data = Cache::remember('dashboard-stats-antrean', now()->addMinutes(2), function () {
        return [
            'total' => Antrean::whereDate('created_at', today())->count(),
            'kemarin' => Antrean::whereDate('created_at', today()->subDay())->count(),
        ];
    });

    // ...
}

Cache pendek seperti ini membuat dashboard tetap terasa "real-time" bagi staf, tapi tidak membebani database setiap detik saat banyak orang membuka halaman yang sama.

Widget grafik: pilih yang bisa dibaca dalam lima detik

Selain StatsOverviewWidget, Filament juga punya widget chart (line, bar, pie) lewat paket resminya. Godaan umum adalah memasukkan sebanyak mungkin dimensi ke satu grafik — per kategori, per cabang, per status, sekaligus. Hasilnya justru sulit dibaca cepat. Untuk widget dashboard, saya pegang aturan sederhana: kalau staf tidak bisa menangkap poin utamanya dalam lima detik pandangan pertama, grafik itu lebih cocok dipindah ke halaman laporan detail, bukan dashboard utama.

Dashboard sebaiknya menjawab "apa yang perlu saya perhatikan sekarang", sedangkan laporan detail menjawab "kenapa ini terjadi". Memisahkan dua kebutuhan ini juga membantu performa: widget dashboard tetap ringan, laporan berat cukup diakses saat dibutuhkan.

Untuk polling otomatis, Filament menyediakan properti $pollingInterval di widget. Ini berguna untuk metrik yang memang perlu update near real-time, tapi jangan dipasang di semua widget sekaligus — polling terlalu agresif bisa membuat browser staf terus-menerus mengirim request.

Takeaway

Widget dashboard yang informatif itu hasil dari tiga kebiasaan: mulai dari pertanyaan nyata staf bukan dari struktur tabel, sertakan konteks (perbandingan dan ambang batas) supaya warna dan ikon benar-benar berarti, dan batasi jumlah informasi per widget supaya bisa dicerna cepat. Filament memberi semua alat teknisnya — Stat, warna dinamis, chart, polling, caching sederhana lewat Cache::remember — tapi keputusan mana yang penting untuk ditampilkan tetap ada di tangan kita sebagai developer yang duduk bersama pengguna dan mendengarkan apa yang sebenarnya mereka butuhkan dari layar pertama yang mereka lihat setiap hari.