sentimeter / js /history.js
rhmnsae's picture
up
3cc3895
/* ═══════════════════════════════════════════════════
SentiMeter β€” history.js
Riwayat Analisis Core Logic
═══════════════════════════════════════════════════ */
'use strict';
SM.injectLayout('nav-history');
document.addEventListener('DOMContentLoaded', () => {
renderHistory();
});
function renderHistory() {
const container = document.getElementById('historyContainer');
const history = SM.getHistory();
const badge = document.getElementById('histCount');
if (badge) badge.textContent = history.length || 0;
if (!history || history.length === 0) {
container.innerHTML = `
<div class="history-empty reveal-up" style="--d:100ms">
<h3>Belum Ada Riwayat Analisis</h3>
<p>Log aktivitas analisis Anda akan muncul di sini. Silakan mulai dengan mengunggah dan memproses file CSV pertama Anda.</p>
<a href="upload" class="btn btn-primary btn-lg empty-cta">Mulai Analisis Sekarang</a>
</div>
`;
return;
}
let html = '';
history.forEach((h, index) => {
const d = h.data;
const meta = d.meta;
const dateStr = new Date(h.savedAt).toLocaleDateString('id-ID', {
day: 'numeric', month: 'long', year: 'numeric',
hour: '2-digit', minute: '2-digit'
});
const totalPos = d.rows.filter(r => r.sentiment === 'Positif').length;
const totalNeg = d.rows.filter(r => r.sentiment === 'Negatif').length;
const totalNeu = d.rows.filter(r => r.sentiment === 'Netral').length;
const total = meta.totalRows || 1;
const pPos = ((totalPos / total) * 100).toFixed(1);
const pNeg = ((totalNeg / total) * 100).toFixed(1);
const pNeu = ((totalNeu / total) * 100).toFixed(1);
html += `
<div class="hist-card" style="--d:${index * 80}ms">
<div class="hist-card-top">
<div class="hist-info">
<div class="hist-filename">${meta.filename || 'data.csv'}</div>
<div class="hist-meta">
<span class="hist-date">Dianalisis pada ${dateStr}</span>
</div>
</div>
<div class="hist-actions">
<button class="btn btn-primary btn-sm" onclick="viewHistory('${h.id}')">Lihat Dashboard</button>
<button class="btn btn-outline btn-sm" style="color:var(--neg);border-color:var(--neg-d)" onclick="removeHistory('${h.id}')">Hapus</button>
</div>
</div>
<div class="hist-visual">
<div class="hist-bar-outer">
<div class="hist-bar-segment pos" style="width: ${pPos}%"></div>
<div class="hist-bar-segment neu" style="width: ${pNeu}%"></div>
<div class="hist-bar-segment neg" style="width: ${pNeg}%"></div>
</div>
</div>
<div class="hist-stats">
<div class="hist-stat-box">
<span class="hist-stat-label">Total Data</span>
<span class="hist-stat-val">${SM.fmt(meta.totalRows)} <span class="hist-stat-unit">Baris</span></span>
</div>
<div class="hist-stat-box">
<span class="hist-stat-label">Positif</span>
<span class="hist-stat-val pos">${pPos}%</span>
</div>
<div class="hist-stat-box">
<span class="hist-stat-label">Netral</span>
<span class="hist-stat-val neu">${pNeu}%</span>
</div>
<div class="hist-stat-box">
<span class="hist-stat-label">Negatif</span>
<span class="hist-stat-val neg">${pNeg}%</span>
</div>
</div>
</div>
`;
});
container.innerHTML = html;
}
window.viewHistory = function(id) {
if (SM.loadHistoryItem(id)) {
SM.showToast('Data riwayat berhasil dimuat.');
setTimeout(() => {
window.location.href = 'dashboard';
}, 500);
} else {
SM.showToast('Gagal memuat riwayat data.', 'error');
}
};
window.removeHistory = function(id) {
const history = SM.getHistory();
const item = history.find(h => h.id === id);
const filename = item ? item.data.meta.filename : 'data';
SM.showModal({
title: 'Hapus Riwayat?',
message: `Apakah Anda yakin ingin menghapus riwayat analisis untuk file <b>${SM.esc(filename)}</b>? Tindakan ini tidak dapat dibatalkan.`,
type: 'error',
confirmText: 'Hapus Riwayat',
cancelText: 'Batal',
showCancel: true,
isDanger: true,
onConfirm: () => {
SM.deleteHistoryItem(id);
renderHistory();
SM.injectLayout('nav-history'); // Refresh sidebar state
SM.showToast('Riwayat berhasil dihapus', 'success');
},
onCancel: () => {
// Do nothing, just close
}
});
};