Bulk Action di Tabel Filament dengan Aman
Salah satu fitur paling menyenangkan di Filament adalah bulk action: centang beberapa baris di tabel, lalu jalankan satu aksi untuk semuanya sekaligus. Enak buat developer, enak buat user. Tapi begitu tabel yang dikelola berisi data pasien, hasil pemeriksaan, atau catatan tindakan medis, kenyamanan itu berubah jadi risiko. Klik yang salah, filter yang lupa direset, atau select all yang dipencet tanpa sadar, bisa mengubah atau menghapus ratusan baris data dalam sekali jalan. Di sistem klinik atau rumah sakit, ini bukan cuma soal bug, tapi soal kepercayaan dan kepatuhan.
Dari pengalaman berkutat dengan sistem seperti ini, ada dua hal yang menurut saya wajib ada di setiap bulk action yang menyentuh data sensitif: konfirmasi yang sungguh-sungguh menahan pengguna sejenak, dan audit trail yang bisa dilacak setelahnya. Dua-duanya sebenarnya sudah difasilitasi Filament, tinggal bagaimana kita memakainya dengan disiplin.
Konfirmasi yang Tidak Sekadar Formalitas
Filament menyediakan requiresConfirmation() di setiap BulkAction, tapi modal konfirmasi default yang cuma bertuliskan "Yakin?" itu gampang diklik tanpa dibaca. Untuk aksi berisiko tinggi seperti hapus massal atau ubah status rekam medis, saya biasa menambahkan deskripsi yang eksplisit menyebutkan jumlah baris yang akan terdampak, bukan cuma nama aksinya.
Tables\Actions\BulkAction::make('archive')
->label('Arsipkan Rekam')
->requiresConfirmation()
->modalHeading('Arsipkan rekam terpilih?')
->modalDescription(fn ($records) => "Anda akan mengarsipkan {$records->count()} rekam. Tindakan ini dapat dibatalkan lewat halaman arsip.")
->modalSubmitActionLabel('Ya, arsipkan')
->action(function ($records) {
// proses di sini
});
Untuk aksi yang sifatnya destruktif dan sulit dibatalkan, saya lebih suka menambah lapisan lagi: minta pengguna mengetik ulang jumlah baris atau kata kunci tertentu sebelum tombol submit aktif. Filament mendukung ini lewat form() di dalam bulk action, jadi konfirmasi bukan sekadar klik ya/tidak, tapi ada friksi kecil yang memaksa pengguna berpikir dua kali.
Audit Trail: Jangan Biarkan Sistem Amnesia
Konfirmasi mencegah kesalahan di depan, audit trail menyelamatkan kita setelah kesalahan terjadi, atau saat ada pertanyaan "siapa yang mengubah data ini dan kapan". Untuk kebutuhan seperti ini, paket activity log semacam spatie/laravel-activitylog cukup umum dipakai bersama Filament, tapi intinya bisa dibangun sendiri: catat aktor, waktu, aksi, dan ID setiap baris yang terdampak, bukan cuma ringkasan "user X menjalankan bulk action".
->action(function ($records) {
foreach ($records as $record) {
activity('bulk-archive')
->performedOn($record)
->causedBy(auth()->user())
->log('Rekam diarsipkan via bulk action');
$record->update(['status' => 'archived']);
}
});
Poin pentingnya: log per baris, bukan satu log untuk seluruh batch. Kalau suatu saat ada audit dan pertanyaannya spesifik ke satu rekam pasien, kita perlu bisa menjawab persis kapan dan oleh siapa rekam itu tersentuh, bukan cuma tahu "ada bulk action yang berjalan hari itu".
Batasi Siapa yang Boleh dan Data Apa yang Kena
Bulk action idealnya tunduk pada aturan otorisasi yang sama dengan aksi satuan. Saya selalu menempelkan pengecekan lewat Policy atau kondisi visible()/authorize() di level bulk action, bukan cuma mengandalkan menu yang disembunyikan di UI. Kalau perlu, batasi juga jumlah baris yang boleh dipilih sekaligus untuk aksi berisiko, misalnya dengan validasi di dalam action() yang menolak proses kalau $records->count() melebihi batas wajar. Ini mencegah skenario "select all" pada tabel dengan ribuan baris berubah jadi insiden besar dalam sedetik.
Ambil Pelajarannya
Bulk action bukan fitur yang harus dihindari di sistem data sensitif, tapi fitur yang harus dirancang dengan asumsi bahwa suatu saat akan ada yang salah klik. Konfirmasi yang informatif memperlambat kesalahan sebelum terjadi, audit trail per baris memastikan kesalahan itu tetap bisa dilacak dan diperbaiki setelahnya. Dua-duanya murah untuk diimplementasikan di Filament, dan jauh lebih murah dibanding harga sebuah insiden data yang tidak bisa dijelaskan siapa penyebabnya.