Rating Setengah Bintang & Analitik
Sistem penilaian destinasi dengan presisi desimal 0.5 hingga 5.0 beserta agregasi statistik distribusi bintang di sisi server.
Membaca sekitar 2 menit
Sistem penilaian destinasi dengan presisi desimal 0.5 hingga 5.0 beserta agregasi statistik distribusi bintang di sisi server.
Membagi elemen visual bintang menjadi dua area klik (kiri untuk .5, kanan untuk bulat) dan menghitung persentase tiap rentang nilai di model Destination.
Menggunakan tipe kolom decimal(2,1) dan agregasi langsung di level query menjaga performa dashboard tetap cepat meski jumlah ulasan bertambah.
Masalahnya dulu
Dalam menilai tempat wisata, angka bulat 1 sampai 5 sering kali terasa kurang mewakili: banyak pengunjung yang merasa suatu tempat lebih bagus dari bintang 4 tetapi belum sempurna untuk bintang 5 (alias 4.5). Di sisi lain, menampilkan rata-rata rating saja tanpa grafik sebaran nilai membuat calon pengunjung maupun admin sulit melihat apakah sebuah destinasi konsisten bagus atau justru memicu opini ekstrem.
Hitbox bintang terbelah di UI dan agregasi di level database
Skema tabel reviews dirancang menggunakan tipe decimal('rating', 2, 1) dengan validasi antara 0.5 hingga 5.0. Pada antarmuka form ulasan, setiap ikon bintang dibungkus kontainer relatif yang memiliki dua area klik transparan: sisi kiri (lebar 50%) untuk nilai i - 0.5 dan sisi kanan untuk nilai bulat i, sementara visual terisinya diatur menggunakan CSS clip-path: inset(0 50% 0 0). Di sisi backend, model Destination dan DashboardController menghitung rata-rata serta distribusi rating langsung lewat query agregat.
Detail kecil seperti mengizinkan nilai setengah bintang dan menampilkan grafik distribusi membuat ulasan terasa jauh lebih jujur dan informatif.
Implementasi di ngodingan ini
Perhitungan distribusi rating pada model Destination dan query peringkat destinasi terbaik di Admin\DashboardController:
// Di App\Models\Destination.php:
public function ratingDistribution(): array {
$dist = [];
for ($i = 5; $i >= 1; $i--) {
$dist[$i] = $this->reviews()
->whereBetween('rating', [$i - 0.4, $i + 0.5])
->count();
}
return $dist;
}
// Di App\Http\Controllers\Admin\DashboardController.php:
$topRated = Destination::approved()
->withCount('reviews as review_count')
->withAvg('reviews as avg_rating', 'rating')
->having('review_count', '>', 0)
->orderByDesc('avg_rating')
->take(5)
->get();Jebakan dan detail yang harus dijaga
- Karena rating menyimpan angka pecahan seperti 4.5 atau 3.5, pengelompokan distribusi per tingkat bintang (5 sampai 1) tidak bisa memakai where('rating', $i) biasa, melainkan perlu rentang whereBetween('rating', [$i - 0.4, $i + 0.5]) atau pembulatan agar nilai setengah bintang tetap terhitung di dalam bar progresnya.
- Saat menyusun daftar Top 5 Destinasi di dashboard admin, penggunaan withCount dan withAvg diikuti klausa having('review_count', '>', 0) memastikan semua perhitungan dilakukan dalam satu query SQL tanpa masalah N+1 dan mengecualikan destinasi yang belum memiliki ulasan.