MIF_E31231226/storage/framework/views/da4c8b215347ddbbfe979485d71...

354 lines
14 KiB
PHP

<?php $__env->startSection('content'); ?>
<div class="max-w-7xl mx-auto">
<?php if(session('success')): ?>
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-6 rounded">
<?php echo e(session('success')); ?>
</div>
<?php endif; ?>
<?php if(session('error')): ?>
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-6 rounded whitespace-pre-line">
<?php echo e(session('error')); ?>
</div>
<?php endif; ?>
<?php if($noDataPesan ?? null): ?>
<div class="bg-blue-50 border-l-4 border-blue-400 text-blue-700 p-4 mb-6 rounded flex items-center gap-2">
<span>📅</span> <span><?php echo e($noDataPesan); ?></span>
</div>
<?php endif; ?>
<?php if($periodeAktif && !$hasAnalisis): ?>
<div class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 mb-6 rounded">
Data ulasan sudah tersedia, tetapi belum dilakukan analisis sentimen.
</div>
<?php endif; ?>
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-3">
<span class="text-sm text-gray-600 font-medium">
Periode aktif: <?php echo e($periodeAktif->nama ?? 'Belum ada data'); ?>
</span>
<a href="<?php echo e(route('riwayat.index')); ?>" class="text-sm text-blue-600 hover:underline">
Lihat riwayat
</a>
</div>
<div class="flex items-center gap-3">
<?php if($periodeAktif): ?>
<span class="text-xs text-gray-400">
Terakhir update: <?php echo e($lastUpdate ? \Carbon\Carbon::parse($lastUpdate)->format('d M Y H:i') : '-'); ?>
</span>
<?php endif; ?>
<form method="GET"
action="<?php echo e(route('dashboard')); ?>"
class="flex flex-col md:flex-row gap-3 md:items-center">
<input type="month"
name="periode_bulan"
value="<?php echo e(request('periode_bulan', now()->format('Y-m'))); ?>"
max="<?php echo e(now()->format('Y-m')); ?>"
onchange="this.form.submit()"
class="border rounded-lg px-3 py-2 text-sm bg-white shadow-sm min-w-[150px]">
</form>
</div>
</div>
<div x-data="{ tab: new URLSearchParams(window.location.search).get('tab') || 'dashboard' }"
x-init="$nextTick(() => { if (tab === 'dashboard') renderAllCharts() })"
class="mb-6">
<!-- TAB -->
<div class="bg-blue-700 rounded-xl p-1 flex space-x-2 shadow mb-6">
<button @click="tab='dashboard'; $nextTick(() => renderAllCharts())"
: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>
<!-- ================= DASHBOARD ================= -->
<div x-show="tab === 'dashboard'">
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-xl shadow p-5">
<p class="text-gray-500 text-sm">Total Ulasan</p>
<h3 class="text-2xl font-bold mt-2 text-gray-900"><?php echo e($stats['total']); ?></h3>
</div>
<div class="bg-white rounded-xl shadow p-5">
<p class="text-gray-500 text-sm">Sentimen Positif</p>
<h3 class="text-2xl font-bold mt-2 text-green-600"><?php echo e($stats['positif_persen']); ?>%</h3>
</div>
<div class="bg-white rounded-xl shadow p-5">
<p class="text-gray-500 text-sm">Sentimen Negatif</p>
<h3 class="text-2xl font-bold mt-2 text-red-600"><?php echo e($stats['negatif_persen']); ?>%</h3>
</div>
<div class="bg-white rounded-xl shadow p-5">
<p class="text-gray-500 text-sm">Sentimen Netral</p>
<h3 class="text-2xl font-bold mt-2 text-yellow-500"><?php echo e($stats['netral_persen']); ?>%</h3>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<div class="bg-white rounded-xl shadow p-6">
<h3 class="font-semibold mb-4 text-gray-700">Distribusi Sentimen</h3>
<div style="height:300px;">
<canvas id="pieChart"></canvas>
</div>
</div>
<div class="bg-white rounded-xl shadow p-6">
<h3 class="font-semibold mb-4 text-gray-700">Sentimen per Destinasi</h3>
<div class="h-[300px]">
<canvas id="destinationChart"></canvas>
</div>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-xl shadow p-6 h-[320px]">
<h3 class="font-semibold mb-6 text-gray-700">Total Data per Destinasi</h3>
<div class="space-y-4 text-sm text-gray-600">
<?php $__currentLoopData = $totalPerWisata; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div class="flex justify-between border-b pb-3">
<span><?php echo e($item->wisata); ?></span>
<span class="font-semibold text-gray-800"><?php echo e($item->total); ?> ulasan</span>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
</div>
</div>
<div class="bg-white rounded-xl shadow p-6 h-[320px]">
<h3 class="font-semibold mb-6 text-gray-700">Word Cloud</h3>
<div id="wordCloud" class="w-full h-[240px] overflow-hidden flex flex-wrap content-center justify-center gap-3 text-center">
<p class="text-sm text-gray-400">Belum ada kata dominan.</p>
</div>
</div>
</div>
</div>
<!-- ================= ANALISIS ================= -->
<div x-show="tab === 'analisis'" id="analisis-content">
<?php echo $__env->make('analisis.index', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?>
</div>
<!-- ================= REKOMENDASI ================= -->
<div x-show="tab === 'rekomendasi'" id="rekomendasi-content">
<?php echo $__env->make('rekomendasi.index', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const pieData = <?php echo json_encode($chartSentimen, 15, 512) ?>;
const destinationData = <?php echo json_encode($chartDestinasi, 15, 512) ?>;
const text = <?php echo json_encode($allText, 15, 512) ?>;
function renderAllCharts() {
// PIE CHART
const pieCanvas = document.getElementById('pieChart');
if (pieCanvas) {
if (window.pieChartInstance) {
window.pieChartInstance.destroy();
window.pieChartInstance = null;
}
// Reset canvas dengan clone agar benar-benar bersih
const newPie = pieCanvas.cloneNode(false);
pieCanvas.parentNode.replaceChild(newPie, pieCanvas);
window.pieChartInstance = new Chart(newPie, { // <-- newPie, bukan pieCanvas
type: 'pie',
data: {
labels: pieData.map(i => i.sentimen),
datasets: [{
data: pieData.map(i => Number(i.total)),
backgroundColor: ['#3B82F6', '#EF4444', '#F59E0B']
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
animation: false
}
});
}
// BAR CHART
const destinationCanvas = document.getElementById('destinationChart');
if (destinationCanvas) {
if (window.destinationChartInstance) {
window.destinationChartInstance.destroy();
window.destinationChartInstance = null;
}
window.destinationChartInstance = new Chart(destinationCanvas, {
type: 'bar',
data: {
labels: destinationData.map(item => item.wisata),
datasets: [
{
label: 'Positif',
data: destinationData.map(item => Number(item.positif || 0)),
backgroundColor: 'rgba(96, 165, 250, 0.88)',
borderColor: '#3B82F6',
borderWidth: 1,
borderRadius: 3,
},
{
label: 'Negatif',
data: destinationData.map(item => Number(item.negatif || 0)),
backgroundColor: 'rgba(248, 113, 113, 0.9)',
borderColor: '#EF4444',
borderWidth: 1,
borderRadius: 3,
},
{
label: 'Netral',
data: destinationData.map(item => Number(item.netral || 0)),
backgroundColor: 'rgba(251, 191, 36, 0.72)',
borderColor: '#F59E0B',
borderWidth: 1,
borderRadius: 3,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
animation: false,
plugins: {
legend: {
position: 'top',
align: 'center',
labels: { boxWidth: 38, boxHeight: 10, color: '#4B5563', font: { size: 12 } },
},
tooltip: {
callbacks: {
label: context => `${context.dataset.label}: ${context.parsed.y} ulasan`,
},
},
},
scales: {
x: {
grid: { color: 'rgba(156, 163, 175, 0.22)' },
ticks: { color: '#4B5563', maxRotation: 14, minRotation: 14, font: { size: 12 } },
},
y: {
beginAtZero: true,
ticks: { color: '#4B5563', precision: 0 },
grid: { color: 'rgba(156, 163, 175, 0.28)' },
},
},
categoryPercentage: 0.72,
barPercentage: 0.82,
},
});
}
// WORD CLOUD
const wordCloud = document.getElementById('wordCloud');
const stopwords = new Set([
'yang','dan','dari','untuk','dengan','ini','itu','tidak','ada','juga',
'sangat','lebih','sudah','bisa','tapi','karena','pada','atau','saya',
'kami','mereka','nya','jadi','kalau','dalam','akan','saat','tempat'
]);
if (wordCloud && text.trim().length > 0) {
const wordCount = {};
text.toLowerCase().split(/\s+/).forEach(word => {
const cleanWord = word.replace(/[^a-z]/g, '');
if (cleanWord.length > 3 && !stopwords.has(cleanWord)) {
wordCount[cleanWord] = (wordCount[cleanWord] || 0) + 1;
}
});
const words = Object.entries(wordCount)
.sort((a, b) => b[1] - a[1])
.slice(0, 28);
if (words.length > 0) {
const max = words[0][1] || 1;
const colors = ['text-blue-700', 'text-green-600', 'text-red-500', 'text-yellow-600', 'text-indigo-600'];
wordCloud.innerHTML = words.map(([word, count], index) => {
const size = 13 + Math.round((count / max) * 20);
const weight = count === max ? 800 : 600;
return `<span class="${colors[index % colors.length]} inline-block" style="font-size:${size}px;font-weight:${weight}" title="${count}x">${word}</span>`;
}).join('');
}
}
}
</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 params = new URLSearchParams(new FormData(e.target)).toString();
fetch('/dashboard?' + params)
.then(res => res.text())
.then(html => {
const doc = new DOMParser().parseFromString(html, 'text/html');
container.innerHTML = doc.getElementById('analisis-content').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 doc = new DOMParser().parseFromString(html, 'text/html');
container.innerHTML = doc.getElementById('analisis-content').innerHTML;
});
}
});
});
</script>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.sentara', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH C:\laragon\www\SistemAnalisisSentimen\resources\views/dashboard.blade.php ENDPATH**/ ?>