update fitur
This commit is contained in:
parent
d5f3f33a83
commit
1f653dda6c
|
|
@ -10,7 +10,9 @@ class DashboardController extends Controller
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$wisata = $request->wisata;
|
$wisata = $request->wisata;
|
||||||
|
$evaluasi = DB::table('evaluasi_model')
|
||||||
|
->latest()
|
||||||
|
->first();
|
||||||
// =============================
|
// =============================
|
||||||
// TOTAL ULASAN (DARI TABEL ULASAN)
|
// TOTAL ULASAN (DARI TABEL ULASAN)
|
||||||
// =============================
|
// =============================
|
||||||
|
|
@ -115,6 +117,17 @@ public function index(Request $request)
|
||||||
->latest('created_at')
|
->latest('created_at')
|
||||||
->value('created_at');
|
->value('created_at');
|
||||||
|
|
||||||
|
$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(
|
return view('dashboard', compact(
|
||||||
'stats',
|
'stats',
|
||||||
'chartSentimen',
|
'chartSentimen',
|
||||||
|
|
@ -122,7 +135,10 @@ public function index(Request $request)
|
||||||
'totalPerWisata',
|
'totalPerWisata',
|
||||||
'allText',
|
'allText',
|
||||||
'lastUpdate',
|
'lastUpdate',
|
||||||
'hasAnalisis'
|
'hasAnalisis',
|
||||||
|
'destinasiList', // WAJIB
|
||||||
|
'hasil',
|
||||||
|
'evaluasi' // WAJIB
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\HasilAnalisis;
|
use App\Models\HasilAnalisis;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class RekomendasiController extends Controller
|
class RekomendasiController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -49,11 +50,23 @@ public function index(Request $request)
|
||||||
// saran otomatis sederhana
|
// saran otomatis sederhana
|
||||||
$saran = "Perlu peningkatan layanan terkait: " . $isuUtama;
|
$saran = "Perlu peningkatan layanan terkait: " . $isuUtama;
|
||||||
|
|
||||||
return view('rekomendasi.index', compact(
|
$destinasiList = DB::table('hasil_analisis')
|
||||||
'destinasiList',
|
->select('wisata')
|
||||||
'isuUtama',
|
->distinct()
|
||||||
'kataDominan',
|
->pluck('wisata');
|
||||||
'saran'
|
|
||||||
|
|
||||||
|
return view('dashboard', compact(
|
||||||
|
'stats',
|
||||||
|
'chartSentimen',
|
||||||
|
'chartDestinasi',
|
||||||
|
'totalPerWisata',
|
||||||
|
'allText',
|
||||||
|
'lastUpdate',
|
||||||
|
'hasAnalisis',
|
||||||
|
'wisataList',
|
||||||
|
'hasil',
|
||||||
|
'destinasiList' // ✅ TAMBAH INI
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Pagination\Paginator;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +20,7 @@ public function register(): void
|
||||||
*/
|
*/
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
|
Paginator::useTailwind();
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,140 +1,253 @@
|
||||||
@extends('layouts.sentara')
|
<div class="space-y-6">
|
||||||
|
|
||||||
@section('content')
|
{{-- ================= HEADER ================= --}}
|
||||||
|
|
||||||
<div class="max-w-6xl mx-auto space-y-8">
|
|
||||||
|
|
||||||
<!-- HEADER -->
|
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<h2 class="text-3xl font-bold text-gray-800">
|
<div>
|
||||||
Hasil Analisis Sentimen
|
<h2 class="text-2xl font-bold">Hasil Analisis Sentimen</h2>
|
||||||
</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>
|
||||||
|
|
||||||
<!-- Dropdown Filter -->
|
{{-- ================= METRICS ================= --}}
|
||||||
<form method="GET" action="{{ route('analisis.index') }}">
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
<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">
|
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<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="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>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{{-- PERFORMA --}}
|
||||||
|
<div class="bg-white p-6 rounded-xl shadow">
|
||||||
|
<h3 class="font-semibold mb-4">Performa per Kelas</h3>
|
||||||
|
|
||||||
|
<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>
|
<option value="">Semua Destinasi</option>
|
||||||
|
|
||||||
@foreach($wisataList as $dest)
|
@foreach($destinasiList as $d)
|
||||||
<option value="{{ $dest }}"
|
<option value="{{ $d }}" {{ request('wisata') == $d ? 'selected' : '' }}>
|
||||||
{{ request('wisata') == $dest ? 'selected' : '' }}>
|
{{ $d }}
|
||||||
{{ $dest }}
|
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded">
|
||||||
|
Filter
|
||||||
|
</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
{{-- ================= TABLE ================= --}}
|
||||||
|
<div class="bg-white rounded-xl shadow p-4">
|
||||||
|
|
||||||
<!-- TABLE CARD -->
|
<h3 class="font-semibold mb-4">Detail Hasil Analisis Sentimen</h3>
|
||||||
<div class="bg-white rounded-xl shadow p-6">
|
|
||||||
|
|
||||||
<h3 class="text-lg font-semibold text-gray-700 mb-4">
|
<table class="w-full text-sm">
|
||||||
Data Hasil Analisis
|
<thead class="border-b text-left">
|
||||||
</h3>
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
<div class="overflow-x-auto">
|
<th>Wisata</th>
|
||||||
<table class="w-full text-sm text-left">
|
<th>Ulasan</th>
|
||||||
<thead>
|
<th>Sentimen</th>
|
||||||
<tr class="bg-gray-100 text-gray-600">
|
<th>Probabilitas</th>
|
||||||
<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>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse($hasil as $row)
|
@forelse($hasil as $index => $item)
|
||||||
<tr class="border-b">
|
<tr class="border-b">
|
||||||
|
<td>{{ $loop->iteration }}</td>
|
||||||
|
<td>{{ $item->wisata }}</td>
|
||||||
|
<td>{{ Str::limit($item->ulasan_terolah, 80) }}</td>
|
||||||
|
|
||||||
<!-- Destinasi -->
|
<td>
|
||||||
<td class="px-4 py-3 font-medium">
|
<span class="
|
||||||
{{ $row->wisata }}
|
px-2 py-1 rounded text-xs
|
||||||
</td>
|
{{ $item->sentimen == 'Positif' ? 'bg-green-100 text-green-600' : '' }}
|
||||||
|
{{ $item->sentimen == 'Negatif' ? 'bg-red-100 text-red-600' : '' }}
|
||||||
<!-- Ulasan -->
|
{{ $item->sentimen == 'Netral' ? 'bg-yellow-100 text-yellow-600' : '' }}
|
||||||
<td class="px-4 py-3 text-gray-700">
|
">
|
||||||
{{ $row->ulasan_terolah }}
|
{{ $item->sentimen }}
|
||||||
</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>
|
</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>
|
</td>
|
||||||
|
|
||||||
|
<td>{{ $item->probabilitas ?? '-' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4" class="text-center py-6 text-gray-400">
|
<td colspan="5" class="text-center py-4 text-gray-500">
|
||||||
Belum ada hasil analisis sentimen.
|
Tidak ada data
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
</table>
|
</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>
|
</div>
|
||||||
|
|
||||||
<!-- PAGINATION -->
|
{{-- PAGINATION --}}
|
||||||
<div class="text-sm text-gray-500 mt-4 text-center">
|
{{-- PAGINATION --}}
|
||||||
Showing {{ $hasil->firstItem() }} to {{ $hasil->lastItem() }}
|
<div class="flex items-center gap-1">
|
||||||
of {{ $hasil->total() }} results
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-center mt-3 items-center gap-2 text-sm">
|
|
||||||
|
|
||||||
{{-- PREV --}}
|
{{-- PREV --}}
|
||||||
@if ($hasil->onFirstPage())
|
@if ($hasil->onFirstPage())
|
||||||
<span class="text-gray-400">‹</span>
|
<span class="px-3 py-1 rounded border text-gray-300">‹</span>
|
||||||
@else
|
@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
|
@endif
|
||||||
|
|
||||||
|
{{-- PAGE NUMBERS --}}
|
||||||
|
@foreach ($hasil->getUrlRange(1, $hasil->lastPage()) as $page => $url)
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$start = max($hasil->currentPage() - 2, 1);
|
$query = request()->query();
|
||||||
$end = min($hasil->currentPage() + 2, $hasil->lastPage());
|
$query['page'] = $page;
|
||||||
|
$customUrl = url()->current() . '?' . http_build_query($query);
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
{{-- NUMBER --}}
|
@if ($page == $hasil->currentPage())
|
||||||
@for ($i = $start; $i <= $end; $i++)
|
<span class="px-3 py-1 rounded bg-blue-600 text-white">
|
||||||
@if ($i == $hasil->currentPage())
|
{{ $page }}
|
||||||
<span class="px-3 py-1 bg-blue-600 text-white rounded-full">
|
|
||||||
{{ $i }}
|
|
||||||
</span>
|
</span>
|
||||||
@else
|
|
||||||
<a href="{{ $hasil->url($i) }}" class="px-2 hover:underline">
|
@elseif ($page <= 3 || $page > $hasil->lastPage()-3 || abs($page - $hasil->currentPage()) <= 1)
|
||||||
{{ $i }}
|
|
||||||
|
<a href="{{ $customUrl }}"
|
||||||
|
class="px-3 py-1 rounded border hover:bg-gray-100">
|
||||||
|
{{ $page }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@elseif ($page == 4 || $page == $hasil->lastPage()-3)
|
||||||
|
<span class="px-2">...</span>
|
||||||
@endif
|
@endif
|
||||||
@endfor
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
{{-- NEXT --}}
|
{{-- NEXT --}}
|
||||||
@if ($hasil->hasMorePages())
|
@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
|
@else
|
||||||
<span class="text-gray-400">›</span>
|
<span class="px-3 py-1 rounded border text-gray-300">›</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -143,4 +256,4 @@ class="bg-white border border-gray-300 text-sm rounded-lg px-4 py-2 shadow-sm
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@endsection
|
</div>
|
||||||
|
|
@ -11,6 +11,38 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@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 --}}
|
{{-- Statistik Cards --}}
|
||||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
||||||
|
|
||||||
|
|
@ -95,9 +127,21 @@
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{{-- ========================= --}}
|
{{-- ========================= --}}
|
||||||
{{-- SCRIPT SECTION --}}
|
{{-- SCRIPT SECTION --}}
|
||||||
{{-- ========================= --}}
|
{{-- ========================= --}}
|
||||||
|
|
@ -173,4 +217,58 @@
|
||||||
});
|
});
|
||||||
</script>
|
</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
|
@endsection
|
||||||
|
|
@ -26,23 +26,23 @@
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
<nav class="flex-1 px-4 space-y-2 text-sm font-medium">
|
<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">
|
<a href="{{ route('dashboard') }}" class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||||
Dashboard
|
Dashboard Sentimen
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('ulasan.index') }}" class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
<a href="{{ route('ulasan.index') }}" class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||||
Data Ulasan
|
Data Ulasan
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('analisis.index') }}"
|
<!-- <a href="{{ route('analisis.index') }}"
|
||||||
class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||||
Hasil Analisis Sentimen
|
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">
|
class="block px-4 py-2 rounded-lg hover:bg-blue-800">
|
||||||
Rekomendasi Layanan
|
Rekomendasi Layanan
|
||||||
</a>
|
</a> -->
|
||||||
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,89 +1,228 @@
|
||||||
@extends('layouts.sentara')
|
<div class="space-y-6">
|
||||||
|
|
||||||
@section('content')
|
{{-- HEADER --}}
|
||||||
|
|
||||||
<div class="max-w-6xl mx-auto space-y-8">
|
|
||||||
|
|
||||||
<!-- HEADER -->
|
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<h2 class="text-3xl font-bold text-gray-800">
|
<div>
|
||||||
Rekomendasi Layanan
|
<h2 class="text-2xl font-bold text-gray-800">Rekomendasi Layanan</h2>
|
||||||
</h2>
|
<p class="text-sm text-gray-500">
|
||||||
|
Rekomendasi dibuat berdasarkan hasil analisis sentimen ulasan wisata.
|
||||||
<!-- 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
|
|
||||||
|
|
||||||
</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>
|
|
||||||
</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>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<p class="text-sm text-gray-600 leading-relaxed">
|
|
||||||
Perlu peningkatan kebersihan area wisata serta evaluasi sistem
|
|
||||||
pengelolaan parkir untuk meningkatkan kenyamanan pengunjung.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<select class="border rounded-lg px-3 py-2 text-sm">
|
||||||
|
<option>Semua Destinasi</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- <select class="border rounded-lg px-3 py-2 text-sm">
|
||||||
|
<option>2020 - 2025</option>
|
||||||
|
</select> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- 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> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- 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>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@endsection
|
{{-- PRIORITAS --}}
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
|
||||||
|
{{-- 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>
|
||||||
|
|
||||||
|
<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