Penilaian Setengah Bintang & Ulasan Pengunjung
Wisatawan bisa memberi ulasan dan bintang secara detail (seperti 4.5 bintang) sehingga gambaran kepuasan pengunjung tempat wisata jadi lebih akurat.
Wisatawan bisa memberi ulasan dan bintang secara detail (seperti 4.5 bintang) sehingga gambaran kepuasan pengunjung tempat wisata jadi lebih akurat.
Tantangan & Kebutuhan Pengguna
Sistem rating bilangan bulat (1 sampai 5) sering kali terlalu kaku bagi pengunjung yang ingin memberikan nilai tengah seperti 3.5 atau 4.5. Selain itu, menampilkan angka rata-rata tunggal tanpa sebaran distribusi per tingkat bintang serta analitik peringkat di halaman Admin menyulitkan pengelola dalam memantau kualitas destinasi terpopuler.
Presisi penilaian di sisi antarmuka harus didukung oleh tipe data desimal yang tepat di level skema serta query agregasi SQL yang efisien di sisi server.
Solusi & Cara Kerja
Kolom `rating` pada tabel `reviews` dirancang dengan tipe `decimal('rating', 2, 1)` dan divalidasi pada rentang `min:0.5|max:5`. Di sisi frontend, masing-masing dari 5 elemen bintang dibagi menjadi dua area klik transparan (`w-1/2` kiri untuk nilai `i - 0.5` dan `w-1/2` kanan untuk nilai bulat `i`), dengan render warna bintang sebagian menggunakan `clip-path`. Di sisi backend, model `Destination` menyediakan metode `ratingDistribution()` menggunakan rentang `whereBetween`, sedangkan `Admin\DashboardController` memanfaatkan agregasi SQL `withCount` dan `withAvg` untuk menyusun peringkat destinasi terbaik.
Berikut adalah implementasi metode distribusi rating di `app/Models/Destination.php` dan query agregat peringkat destinasi di `app/Http/Controllers/Admin/DashboardController.php`:
Detail & Hal yang Diperhatikan
- Pengelompokan nilai pecahan ke dalam bar histogram 1–5 bintang: Karena database menyimpan nilai seperti `4.5`, pengelompokan distribusi menggunakan rentang `whereBetween('rating', [$i - 0.4, $i + 0.5])` serta pembulatan `round($r->rating)` agar setiap ulasan setengah bintang terhitung secara konsisten di grafik progres.
- Eliminasi N+1 Query pada Dashboard Admin: Peringkat 5 destinasi dengan rating tertinggi dihitung langsung di engine SQL menggunakan `withCount('reviews as review_count')`, `withAvg('reviews as avg_rating', 'rating')`, dan filter `having('review_count', '>', 0)` dalam satu eksekusi query.
- Proteksi integritas ulasan publik: `Public\ReviewController::store` memfilter target destinasi dengan `Destination::approved()->where('slug', $slug)->firstOrFail()`, memastikan ulasan tidak dapat dikirimkan ke destinasi yang masih berstatus `pending` atau `rejected`.