update fitur
This commit is contained in:
parent
d5f3f33a83
commit
1f653dda6c
|
|
@ -10,7 +10,9 @@ class DashboardController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$wisata = $request->wisata;
|
||||
|
||||
$evaluasi = DB::table('evaluasi_model')
|
||||
->latest()
|
||||
->first();
|
||||
// =============================
|
||||
// TOTAL ULASAN (DARI TABEL ULASAN)
|
||||
// =============================
|
||||
|
|
@ -115,14 +117,28 @@ public function index(Request $request)
|
|||
->latest('created_at')
|
||||
->value('created_at');
|
||||
|
||||
return view('dashboard', compact(
|
||||
'stats',
|
||||
'chartSentimen',
|
||||
'chartDestinasi',
|
||||
'totalPerWisata',
|
||||
'allText',
|
||||
'lastUpdate',
|
||||
'hasAnalisis'
|
||||
));
|
||||
$destinasiList = DB::table('ulasan')
|
||||
->select('wisata')
|
||||
->distinct()
|
||||
->pluck('wisata');
|
||||
|
||||
$hasil = DB::table('hasil_analisis')
|
||||
->when($wisata && $wisata != 'Semua Destinasi', function ($q) use ($wisata) {
|
||||
$q->where('wisata', $wisata);
|
||||
})
|
||||
->paginate(10);
|
||||
|
||||
return view('dashboard', compact(
|
||||
'stats',
|
||||
'chartSentimen',
|
||||
'chartDestinasi',
|
||||
'totalPerWisata',
|
||||
'allText',
|
||||
'lastUpdate',
|
||||
'hasAnalisis',
|
||||
'destinasiList', // WAJIB
|
||||
'hasil',
|
||||
'evaluasi' // WAJIB
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\HasilAnalisis;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RekomendasiController extends Controller
|
||||
{
|
||||
|
|
@ -49,11 +50,23 @@ public function index(Request $request)
|
|||
// saran otomatis sederhana
|
||||
$saran = "Perlu peningkatan layanan terkait: " . $isuUtama;
|
||||
|
||||
return view('rekomendasi.index', compact(
|
||||
'destinasiList',
|
||||
'isuUtama',
|
||||
'kataDominan',
|
||||
'saran'
|
||||
));
|
||||
$destinasiList = DB::table('hasil_analisis')
|
||||
->select('wisata')
|
||||
->distinct()
|
||||
->pluck('wisata');
|
||||
|
||||
|
||||
return view('dashboard', compact(
|
||||
'stats',
|
||||
'chartSentimen',
|
||||
'chartDestinasi',
|
||||
'totalPerWisata',
|
||||
'allText',
|
||||
'lastUpdate',
|
||||
'hasAnalisis',
|
||||
'wisataList',
|
||||
'hasil',
|
||||
'destinasiList' // ✅ TAMBAH INI
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -19,6 +20,7 @@ public function register(): void
|
|||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Paginator::useTailwind();
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,146 +1,259 @@
|
|||
@extends('layouts.sentara')
|
||||
<div class="space-y-6">
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="max-w-6xl mx-auto space-y-8">
|
||||
|
||||
<!-- HEADER -->
|
||||
{{-- ================= HEADER ================= --}}
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-3xl font-bold text-gray-800">
|
||||
Hasil Analisis Sentimen
|
||||
</h2>
|
||||
|
||||
<!-- Dropdown Filter -->
|
||||
<form method="GET" action="{{ route('analisis.index') }}">
|
||||
<select name="wisata"
|
||||
onchange="this.form.submit()"
|
||||
class="bg-white border border-gray-300 text-sm rounded-lg px-4 py-2 shadow-sm
|
||||
focus:ring-2 focus:ring-blue-400 focus:outline-none">
|
||||
|
||||
<option value="">Semua Destinasi</option>
|
||||
|
||||
@foreach($wisataList as $dest)
|
||||
<option value="{{ $dest }}"
|
||||
{{ request('wisata') == $dest ? 'selected' : '' }}>
|
||||
{{ $dest }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</form>
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold">Hasil Analisis Sentimen</h2>
|
||||
<p class="text-gray-500 text-sm">
|
||||
Berikut adalah hasil evaluasi model dan detail analisis sentimen terhadap ulasan wisata.
|
||||
</p>
|
||||
</div>
|
||||
<!-- <div class="text-sm text-gray-500">
|
||||
{{ now()->format('d F Y - H:i') }}
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
{{-- ================= METRICS ================= --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
|
||||
<!-- TABLE CARD -->
|
||||
<div class="bg-white rounded-xl shadow p-6">
|
||||
<div class="bg-white p-5 rounded-xl shadow">
|
||||
<p class="text-gray-500 text-sm">Precision</p>
|
||||
<h3 class="text-2xl font-bold text-blue-600">
|
||||
{{ $evaluasi->precision ?? 0 }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<h3 class="text-lg font-semibold text-gray-700 mb-4">
|
||||
Data Hasil Analisis
|
||||
</h3>
|
||||
<div class="bg-white p-5 rounded-xl shadow">
|
||||
<p class="text-gray-500 text-sm">Recall</p>
|
||||
<h3 class="text-2xl font-bold text-green-600">
|
||||
{{ $evaluasi->recall ?? 0 }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm text-left">
|
||||
<thead>
|
||||
<tr class="bg-gray-100 text-gray-600">
|
||||
<th class="px-4 py-3">wisata</th>
|
||||
<th class="px-4 py-3">Ulasan Terolah</th>
|
||||
<th class="px-4 py-3">Sentimen</th>
|
||||
<th class="px-4 py-3">Probabilitas</th>
|
||||
<div class="bg-white p-5 rounded-xl shadow">
|
||||
<p class="text-gray-500 text-sm">F1 Score</p>
|
||||
<h3 class="text-2xl font-bold text-purple-600">
|
||||
{{ $evaluasi->f1_score ?? 0 }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-5 rounded-xl shadow">
|
||||
<p class="text-gray-500 text-sm">Akurasi</p>
|
||||
<h3 class="text-2xl font-bold text-indigo-600">
|
||||
{{ $evaluasi->accuracy ?? 0 }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- ================= MATRIX + PERFORMA ================= --}}
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
|
||||
{{-- CONFUSION MATRIX --}}
|
||||
<div class="bg-white p-6 rounded-xl shadow">
|
||||
<h3 class="font-semibold mb-4">Confusion Matrix</h3>
|
||||
|
||||
<table class="w-full text-center border rounded-lg overflow-hidden">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Positif</th>
|
||||
<th>Negatif</th>
|
||||
<th>Netral</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($hasil as $row)
|
||||
<tr class="border-b">
|
||||
|
||||
<!-- Destinasi -->
|
||||
<td class="px-4 py-3 font-medium">
|
||||
{{ $row->wisata }}
|
||||
</td>
|
||||
|
||||
<!-- Ulasan -->
|
||||
<td class="px-4 py-3 text-gray-700">
|
||||
{{ $row->ulasan_terolah }}
|
||||
</td>
|
||||
|
||||
<!-- Badge Sentimen -->
|
||||
<td class="px-4 py-3">
|
||||
@if($row->sentimen == 'positif')
|
||||
<span class="px-3 py-1 rounded-full bg-green-100 text-green-700 text-xs font-semibold">
|
||||
Positif
|
||||
</span>
|
||||
@elseif($row->sentimen == 'negatif')
|
||||
<span class="px-3 py-1 rounded-full bg-red-100 text-red-700 text-xs font-semibold">
|
||||
Negatif
|
||||
</span>
|
||||
@else
|
||||
<span class="px-3 py-1 rounded-full bg-yellow-100 text-yellow-700 text-xs font-semibold">
|
||||
Netral
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<!-- Probabilitas -->
|
||||
<td class="px-4 py-3 font-semibold text-gray-700">
|
||||
{{ number_format($row->probabilitas, 2) }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-6 text-gray-400">
|
||||
Belum ada hasil analisis sentimen.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<tr>
|
||||
<th class="bg-gray-50">Positif</th>
|
||||
<td class="bg-green-100">{{ $evaluasi->tp ?? 0 }}</td>
|
||||
<td class="bg-red-100">{{ $evaluasi->fn ?? 0 }}</td>
|
||||
<td class="bg-yellow-100">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="bg-gray-50">Negatif</th>
|
||||
<td class="bg-red-100">{{ $evaluasi->fp ?? 0 }}</td>
|
||||
<td class="bg-green-100">{{ $evaluasi->tn ?? 0 }}</td>
|
||||
<td class="bg-yellow-100">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="bg-gray-50">Netral</th>
|
||||
<td class="bg-yellow-100">0</td>
|
||||
<td class="bg-yellow-100">0</td>
|
||||
<td class="bg-green-100">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- PAGINATION -->
|
||||
<div class="text-sm text-gray-500 mt-4 text-center">
|
||||
Showing {{ $hasil->firstItem() }} to {{ $hasil->lastItem() }}
|
||||
of {{ $hasil->total() }} results
|
||||
</div>
|
||||
{{-- PERFORMA --}}
|
||||
<div class="bg-white p-6 rounded-xl shadow">
|
||||
<h3 class="font-semibold mb-4">Performa per Kelas</h3>
|
||||
|
||||
<div class="flex justify-center mt-3 items-center gap-2 text-sm">
|
||||
<table class="w-full text-sm border">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
<th>Kelas</th>
|
||||
<th>Precision</th>
|
||||
<th>Recall</th>
|
||||
<th>F1</th>
|
||||
<th>Support</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-green-600 font-semibold">Positif</td>
|
||||
<td>{{ $evaluasi->precision ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->recall ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->f1_score ?? 0 }}</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-red-600 font-semibold">Negatif</td>
|
||||
<td>{{ $evaluasi->precision ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->recall ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->f1_score ?? 0 }}</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-yellow-600 font-semibold">Netral</td>
|
||||
<td>{{ $evaluasi->precision ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->recall ?? 0 }}</td>
|
||||
<td>{{ $evaluasi->f1_score ?? 0 }}</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- ================= FILTER ================= --}}
|
||||
<form id="filter-form" class="flex items-center gap-3">
|
||||
|
||||
<input type="hidden" name="tab" value="analisis">
|
||||
|
||||
<select name="wisata" class="border rounded px-3 py-2">
|
||||
<option value="">Semua Destinasi</option>
|
||||
|
||||
@foreach($destinasiList as $d)
|
||||
<option value="{{ $d }}" {{ request('wisata') == $d ? 'selected' : '' }}>
|
||||
{{ $d }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded">
|
||||
Filter
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
{{-- ================= TABLE ================= --}}
|
||||
<div class="bg-white rounded-xl shadow p-4">
|
||||
|
||||
<h3 class="font-semibold mb-4">Detail Hasil Analisis Sentimen</h3>
|
||||
|
||||
<table class="w-full text-sm">
|
||||
<thead class="border-b text-left">
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Wisata</th>
|
||||
<th>Ulasan</th>
|
||||
<th>Sentimen</th>
|
||||
<th>Probabilitas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($hasil as $index => $item)
|
||||
<tr class="border-b">
|
||||
<td>{{ $loop->iteration }}</td>
|
||||
<td>{{ $item->wisata }}</td>
|
||||
<td>{{ Str::limit($item->ulasan_terolah, 80) }}</td>
|
||||
|
||||
<td>
|
||||
<span class="
|
||||
px-2 py-1 rounded text-xs
|
||||
{{ $item->sentimen == 'Positif' ? 'bg-green-100 text-green-600' : '' }}
|
||||
{{ $item->sentimen == 'Negatif' ? 'bg-red-100 text-red-600' : '' }}
|
||||
{{ $item->sentimen == 'Netral' ? 'bg-yellow-100 text-yellow-600' : '' }}
|
||||
">
|
||||
{{ $item->sentimen }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>{{ $item->probabilitas ?? '-' }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4 text-gray-500">
|
||||
Tidak ada data
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{-- PAGINATION --}}
|
||||
<div class="mt-6 flex items-center justify-between text-sm text-gray-500">
|
||||
|
||||
{{-- INFO --}}
|
||||
<div>
|
||||
Menampilkan {{ $hasil->firstItem() }} - {{ $hasil->lastItem() }}
|
||||
dari {{ $hasil->total() }} data
|
||||
</div>
|
||||
|
||||
{{-- PAGINATION --}}
|
||||
{{-- PAGINATION --}}
|
||||
<div class="flex items-center gap-1">
|
||||
|
||||
{{-- PREV --}}
|
||||
@if ($hasil->onFirstPage())
|
||||
<span class="text-gray-400">‹</span>
|
||||
<span class="px-3 py-1 rounded border text-gray-300">‹</span>
|
||||
@else
|
||||
<a href="{{ $hasil->previousPageUrl() }}">‹</a>
|
||||
<a href="{{ $hasil->appends(request()->query())->previousPageUrl() }}"
|
||||
class="px-3 py-1 rounded border hover:bg-gray-100">‹</a>
|
||||
@endif
|
||||
|
||||
@php
|
||||
$start = max($hasil->currentPage() - 2, 1);
|
||||
$end = min($hasil->currentPage() + 2, $hasil->lastPage());
|
||||
@endphp
|
||||
{{-- PAGE NUMBERS --}}
|
||||
@foreach ($hasil->getUrlRange(1, $hasil->lastPage()) as $page => $url)
|
||||
|
||||
{{-- NUMBER --}}
|
||||
@for ($i = $start; $i <= $end; $i++)
|
||||
@if ($i == $hasil->currentPage())
|
||||
<span class="px-3 py-1 bg-blue-600 text-white rounded-full">
|
||||
{{ $i }}
|
||||
@php
|
||||
$query = request()->query();
|
||||
$query['page'] = $page;
|
||||
$customUrl = url()->current() . '?' . http_build_query($query);
|
||||
@endphp
|
||||
|
||||
@if ($page == $hasil->currentPage())
|
||||
<span class="px-3 py-1 rounded bg-blue-600 text-white">
|
||||
{{ $page }}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $hasil->url($i) }}" class="px-2 hover:underline">
|
||||
{{ $i }}
|
||||
|
||||
@elseif ($page <= 3 || $page > $hasil->lastPage()-3 || abs($page - $hasil->currentPage()) <= 1)
|
||||
|
||||
<a href="{{ $customUrl }}"
|
||||
class="px-3 py-1 rounded border hover:bg-gray-100">
|
||||
{{ $page }}
|
||||
</a>
|
||||
|
||||
@elseif ($page == 4 || $page == $hasil->lastPage()-3)
|
||||
<span class="px-2">...</span>
|
||||
@endif
|
||||
@endfor
|
||||
|
||||
@endforeach
|
||||
|
||||
{{-- NEXT --}}
|
||||
@if ($hasil->hasMorePages())
|
||||
<a href="{{ $hasil->nextPageUrl() }}">›</a>
|
||||
<a href="{{ $hasil->appends(request()->query())->nextPageUrl() }}"
|
||||
class="px-3 py-1 rounded border hover:bg-gray-100">›</a>
|
||||
@else
|
||||
<span class="text-gray-400">›</span>
|
||||
<span class="px-3 py-1 rounded border text-gray-300">›</span>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
</div>
|
||||
|
|
@ -11,6 +11,38 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
<div x-data="{ tab: 'dashboard' }" class="mb-6">
|
||||
|
||||
<!-- TAB -->
|
||||
<div class="bg-blue-700 rounded-xl p-1 flex space-x-2 shadow mb-6">
|
||||
|
||||
<button @click="tab='dashboard'"
|
||||
:class="tab==='dashboard'
|
||||
? 'bg-white text-blue-700 shadow'
|
||||
: 'text-white hover:bg-blue-600'"
|
||||
class="flex-1 py-3 rounded-lg text-sm font-medium transition">
|
||||
Dashboard Sentara
|
||||
</button>
|
||||
|
||||
<button @click="tab='analisis'"
|
||||
:class="tab==='analisis'
|
||||
? 'bg-white text-blue-700 shadow'
|
||||
: 'text-white hover:bg-blue-600'"
|
||||
class="flex-1 py-3 rounded-lg text-sm font-medium transition">
|
||||
Hasil Analisis Sentimen
|
||||
</button>
|
||||
|
||||
<button @click="tab='rekomendasi'"
|
||||
:class="tab==='rekomendasi'
|
||||
? 'bg-white text-blue-700 shadow'
|
||||
: 'text-white hover:bg-blue-600'"
|
||||
class="flex-1 py-3 rounded-lg text-sm font-medium transition">
|
||||
Rekomendasi Layanan
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div x-show="tab === 'dashboard'">
|
||||
{{-- Statistik Cards --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
||||
|
||||
|
|
@ -94,10 +126,22 @@
|
|||
<div id="wordCloud" class="w-full h-[240px] overflow-hidden"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ================= ANALISIS ================= -->
|
||||
<div x-show="tab === 'analisis'" id="analisis-content">
|
||||
@include('analisis.index')
|
||||
</div>
|
||||
|
||||
<!-- ================= REKOMENDASI ================= -->
|
||||
<div x-show="tab === 'rekomendasi'" id="rekomendasi-content">
|
||||
@include('rekomendasi.index')
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{{-- ========================= --}}
|
||||
{{-- SCRIPT SECTION --}}
|
||||
{{-- ========================= --}}
|
||||
|
|
@ -173,4 +217,58 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
const tab = new URLSearchParams(window.location.search).get('tab');
|
||||
|
||||
if (tab === 'analisis') {
|
||||
showTab('analisis');
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
const container = document.getElementById('analisis-content');
|
||||
|
||||
// ================= FILTER AJAX =================
|
||||
document.addEventListener('submit', function(e){
|
||||
if(e.target.id === 'filter-form'){
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const params = new URLSearchParams(formData).toString();
|
||||
|
||||
fetch('/dashboard?' + params)
|
||||
.then(res => res.text())
|
||||
.then(html => {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
const newContent = doc.getElementById('analisis-content');
|
||||
container.innerHTML = newContent.innerHTML;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ================= PAGINATION AJAX =================
|
||||
document.addEventListener('click', function(e){
|
||||
const link = e.target.closest('a');
|
||||
|
||||
if(link && link.href.includes('page=')){
|
||||
e.preventDefault();
|
||||
|
||||
fetch(link.href)
|
||||
.then(res => res.text())
|
||||
.then(html => {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
const newContent = doc.getElementById('analisis-content');
|
||||
container.innerHTML = newContent.innerHTML;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -26,23 +26,23 @@
|
|||
<!-- Menu -->
|
||||
<nav class="flex-1 px-4 space-y-2 text-sm font-medium">
|
||||
<a href="{{ route('dashboard') }}" class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||
Dashboard
|
||||
Dashboard Sentimen
|
||||
</a>
|
||||
|
||||
<a href="{{ route('ulasan.index') }}" class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||
Data Ulasan
|
||||
</a>
|
||||
|
||||
<a href="{{ route('analisis.index') }}"
|
||||
<!-- <a href="{{ route('analisis.index') }}"
|
||||
class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||
Hasil Analisis Sentimen
|
||||
</a>
|
||||
</a> -->
|
||||
|
||||
|
||||
<a href="{{ route('rekomendasi.index') }}"
|
||||
<!-- <a href="{{ route('rekomendasi.index') }}"
|
||||
class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||
Rekomendasi Layanan
|
||||
</a>
|
||||
</a> -->
|
||||
|
||||
</nav>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,89 +1,228 @@
|
|||
@extends('layouts.sentara')
|
||||
<div class="space-y-6">
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="max-w-6xl mx-auto space-y-8">
|
||||
|
||||
<!-- HEADER -->
|
||||
{{-- HEADER --}}
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-3xl font-bold text-gray-800">
|
||||
Rekomendasi Layanan
|
||||
</h2>
|
||||
|
||||
<!-- Dropdown -->
|
||||
<form method="GET">
|
||||
<select name="destinasi"
|
||||
onchange="this.form.submit()"
|
||||
class="bg-white border border-gray-300 text-sm rounded-lg px-4 py-2 shadow-sm
|
||||
focus:ring-2 focus:ring-blue-400 focus:outline-none">
|
||||
|
||||
<option value="">Semua Destinasi</option>
|
||||
|
||||
@foreach($destinasiList as $d)
|
||||
<option value="{{ $d }}">
|
||||
{{ $d }}
|
||||
</option>
|
||||
@endforeach
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Rekomendasi Layanan</h2>
|
||||
<p class="text-sm text-gray-500">
|
||||
Rekomendasi dibuat berdasarkan hasil analisis sentimen ulasan wisata.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<select class="border rounded-lg px-3 py-2 text-sm">
|
||||
<option>Semua Destinasi</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- CARD GRID -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
|
||||
<!-- Isu Utama -->
|
||||
<div class="bg-white rounded-xl shadow p-6">
|
||||
<h3 class="text-gray-700 font-semibold mb-4">
|
||||
Isu Utama
|
||||
</h3>
|
||||
|
||||
<div class="text-sm text-gray-600 space-y-2">
|
||||
<span class="inline-block bg-red-100 text-red-700 px-3 py-1 rounded-full text-xs font-medium">
|
||||
Kebersihan
|
||||
</span>
|
||||
<span class="inline-block bg-red-100 text-red-700 px-3 py-1 rounded-full text-xs font-medium">
|
||||
Parkir
|
||||
</span>
|
||||
<!-- <select class="border rounded-lg px-3 py-2 text-sm">
|
||||
<option>2020 - 2025</option>
|
||||
</select> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kata Kunci Dominan -->
|
||||
<div class="bg-white rounded-xl shadow p-6">
|
||||
<h3 class="text-gray-700 font-semibold mb-4">
|
||||
Kata Kunci Dominan
|
||||
</h3>
|
||||
{{-- SUMMARY --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-5">
|
||||
|
||||
<div class="bg-white rounded-xl shadow p-5 flex items-center gap-4">
|
||||
<div class="bg-red-100 text-red-500 p-3 rounded-full text-xl">😟</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-500">Total Ulasan Negatif</p>
|
||||
<h3 class="text-xl font-bold">312</h3>
|
||||
<p class="text-xs text-red-500">25,06% dari total</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow p-5 flex items-center gap-4">
|
||||
<div class="bg-green-100 text-green-600 p-3 rounded-full text-xl">😊</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-500">Tingkat Kepuasan</p>
|
||||
<h3 class="text-xl font-bold">68%</h3>
|
||||
<span class="text-xs bg-yellow-100 text-yellow-700 px-2 py-1 rounded">
|
||||
Sedang
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow p-5 flex items-center gap-4">
|
||||
<div class="bg-purple-100 text-purple-600 p-3 rounded-full text-xl">❗</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-500">Isu Dominan</p>
|
||||
<h3 class="text-xl font-bold">Kebersihan</h3>
|
||||
<p class="text-xs text-gray-500">45% dari total isu</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="bg-white rounded-xl shadow p-5 flex items-center gap-4">
|
||||
<div class="bg-blue-100 text-blue-600 p-3 rounded-full text-xl">📅</div>
|
||||
<div>
|
||||
<p class="text-sm text-gray-500">Periode Data</p>
|
||||
<h3 class="text-xl font-bold">2020 - 2025</h3>
|
||||
<p class="text-xs text-gray-500">6 tahun data</p>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<ul class="text-sm text-gray-600 space-y-2">
|
||||
<li class="flex justify-between">
|
||||
<span>kotor</span>
|
||||
<span class="font-semibold">15x</span>
|
||||
</li>
|
||||
<li class="flex justify-between">
|
||||
<span>parkir</span>
|
||||
<span class="font-semibold">10x</span>
|
||||
</li>
|
||||
<li class="flex justify-between">
|
||||
<span>mahal</span>
|
||||
<span class="font-semibold">7x</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Saran -->
|
||||
<div class="bg-white rounded-xl shadow p-6">
|
||||
<h3 class="text-gray-700 font-semibold mb-4">
|
||||
Saran Perbaikan
|
||||
</h3>
|
||||
{{-- GRID ANALISIS --}}
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
|
||||
{{-- ISU UTAMA --}}
|
||||
<div class="bg-white rounded-xl shadow p-5">
|
||||
<h3 class="font-semibold mb-4 text-gray-700">Isu Utama (Top 5)</h3>
|
||||
|
||||
@php
|
||||
$isu = [
|
||||
['nama'=>'Kebersihan','persen'=>45,'warna'=>'red'],
|
||||
['nama'=>'Parkir','persen'=>30,'warna'=>'orange'],
|
||||
['nama'=>'Harga / Tiket','persen'=>15,'warna'=>'yellow'],
|
||||
['nama'=>'Fasilitas','persen'=>6,'warna'=>'green'],
|
||||
['nama'=>'Keramaian','persen'=>4,'warna'=>'blue'],
|
||||
];
|
||||
@endphp
|
||||
|
||||
@foreach($isu as $i => $item)
|
||||
<div class="mb-4">
|
||||
<div class="flex justify-between text-sm mb-1">
|
||||
<span>{{ $i+1 }}. {{ $item['nama'] }}</span>
|
||||
<span>{{ $item['persen'] }}%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 h-2 rounded">
|
||||
<div class="h-2 rounded
|
||||
@if($item['warna'] == 'red') bg-red-500
|
||||
@elseif($item['warna'] == 'orange') bg-orange-500
|
||||
@elseif($item['warna'] == 'yellow') bg-yellow-500
|
||||
@elseif($item['warna'] == 'green') bg-green-500
|
||||
@else bg-blue-500
|
||||
@endif"
|
||||
style="width: {{ $item['persen'] }}%">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
{{-- KEYWORD --}}
|
||||
<div class="bg-white rounded-xl shadow p-5">
|
||||
<h3 class="font-semibold mb-4 text-gray-700">Kata Kunci Dominan</h3>
|
||||
|
||||
@php
|
||||
$keywords = [
|
||||
['kotor',15],
|
||||
['parkir',10],
|
||||
['mahal',7],
|
||||
['sampah',6],
|
||||
['toilet',5],
|
||||
];
|
||||
@endphp
|
||||
|
||||
@foreach($keywords as $k)
|
||||
<div class="mb-3">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span>{{ $k[0] }}</span>
|
||||
<span>{{ $k[1] }}x</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 h-2 rounded mt-1">
|
||||
<div class="bg-blue-500 h-2 rounded"
|
||||
style="width: {{ $k[1]*5 }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
{{-- SARAN --}}
|
||||
<div class="bg-white rounded-xl shadow p-5">
|
||||
<h3 class="font-semibold mb-4 text-gray-700">Saran Perbaikan</h3>
|
||||
|
||||
<div class="space-y-4 text-sm">
|
||||
|
||||
<div class="flex gap-3">
|
||||
<div class="text-green-500 text-xl">🧹</div>
|
||||
<div>
|
||||
<p class="font-semibold">Perbaikan Kebersihan</p>
|
||||
<p class="text-gray-600">
|
||||
Tambah tempat sampah & jadwal pembersihan rutin.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<div class="text-orange-500 text-xl">🚗</div>
|
||||
<div>
|
||||
<p class="font-semibold">Penataan Parkir</p>
|
||||
<p class="text-gray-600">
|
||||
Sistem parkir lebih rapi dan transparan.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<div class="text-yellow-500 text-xl">🏷️</div>
|
||||
<div>
|
||||
<p class="font-semibold">Evaluasi Harga</p>
|
||||
<p class="text-gray-600">
|
||||
Penyesuaian harga tiket agar lebih terjangkau.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600 leading-relaxed">
|
||||
Perlu peningkatan kebersihan area wisata serta evaluasi sistem
|
||||
pengelolaan parkir untuk meningkatkan kenyamanan pengunjung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{-- PRIORITAS --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
|
||||
</div>
|
||||
{{-- CARD 1 --}}
|
||||
<div class="border border-red-300 rounded-xl p-5 bg-white">
|
||||
<h4 class="font-semibold text-red-600 mb-2">Prioritas 1</h4>
|
||||
<h3 class="text-lg font-bold mb-3">Kebersihan</h3>
|
||||
|
||||
@endsection
|
||||
<ul class="text-sm space-y-2">
|
||||
<li>✔ Tambah tempat sampah</li>
|
||||
<li>✔ Jadwal pembersihan rutin</li>
|
||||
<li>✔ Petugas kebersihan tambahan</li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-4 text-xs bg-red-100 text-red-600 p-2 rounded">
|
||||
Dampak: Kepuasan meningkat signifikan
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- CARD 2 --}}
|
||||
<div class="border border-orange-300 rounded-xl p-5 bg-white">
|
||||
<h4 class="font-semibold text-orange-600 mb-2">Prioritas 2</h4>
|
||||
<h3 class="text-lg font-bold mb-3">Parkir</h3>
|
||||
|
||||
<ul class="text-sm space-y-2">
|
||||
<li>✔ Penataan area parkir</li>
|
||||
<li>✔ Tarif transparan</li>
|
||||
<li>✔ Petugas lebih ramah</li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-4 text-xs bg-orange-100 text-orange-600 p-2 rounded">
|
||||
Dampak: Mengurangi keluhan
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- CARD 3 --}}
|
||||
<div class="border border-yellow-300 rounded-xl p-5 bg-white">
|
||||
<h4 class="font-semibold text-yellow-600 mb-2">Prioritas 3</h4>
|
||||
<h3 class="text-lg font-bold mb-3">Harga</h3>
|
||||
|
||||
<ul class="text-sm space-y-2">
|
||||
<li>✔ Evaluasi harga tiket</li>
|
||||
<li>✔ Promo wisata</li>
|
||||
<li>✔ Diskon tertentu</li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-4 text-xs bg-yellow-100 text-yellow-600 p-2 rounded">
|
||||
Dampak: Daya tarik meningkat
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
Loading…
Reference in New Issue