Files

51 lines
3.8 KiB
JavaScript

(function() {
const nav = document.getElementById('sidebar-nav');
const wrap = document.getElementById('sidebar-nav-wrap');
const track = document.getElementById('sb-track');
const thumb = document.getElementById('sb-thumb');
if (!nav || !track || !thumb || !wrap) return;
let isDragging = false;
function show() { track.style.opacity = '1'; }
function hide() { if (!isDragging) track.style.opacity = '0'; }
function update() {
const sh = nav.scrollHeight, ch = nav.clientHeight;
if (sh <= ch) { track.style.display = 'none'; return; }
track.style.display = 'block'; track.style.opacity = '1';
const st = nav.scrollTop, th = Math.max((ch / sh) * ch, 24);
const maxTop = ch - th, ratio = sh > ch ? st / (sh - ch) : 0;
thumb.style.height = th + 'px'; thumb.style.top = (ratio * maxTop) + 'px';
}
const observer = new MutationObserver(function() {
update(); setTimeout(function() {
update();
if (nav.scrollHeight > nav.clientHeight) { track.style.display = 'block'; track.style.opacity = '1'; }
}, 350);
});
observer.observe(nav, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
nav.addEventListener('scroll', update); window.addEventListener('resize', update);
wrap.addEventListener('mouseenter', function() { show(); update(); });
wrap.addEventListener('mouseleave', hide);
thumb.addEventListener('mousedown', function(e) {
e.preventDefault(); isDragging = true; track.style.opacity = '1';
document.body.style.cursor = 'pointer'; document.body.style.userSelect = 'none';
function onMove(ev) {
if (!isDragging) return;
const rect = track.getBoundingClientRect();
nav.scrollTop = ((ev.clientY - rect.top) / rect.height) * (nav.scrollHeight - nav.clientHeight);
}
function onUp() {
isDragging = false; document.body.style.cursor = ''; document.body.style.userSelect = '';
document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp);
}
document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp);
});
update(); setTimeout(update, 300);
})();
document.addEventListener('DOMContentLoaded', function() {
const grayText = '#94a3b8';
const plRevenue = '#2563eb', plExpenses = '#f97316';
new Chart(document.getElementById('plChart'), { type: 'bar', data: { labels: ['Jan','Feb','Mar','Apr','May','Jun'], datasets: [{ label: 'Revenue', data: [1.8,2.1,1.9,2.2,2.4,2.0], backgroundColor: plRevenue, borderRadius: 4, barPercentage: 0.4 }, { label: 'Outgoing', data: [1.4,1.6,1.5,1.7,1.8,1.5], backgroundColor: plExpenses, borderRadius: 4, barPercentage: 0.4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { color: grayText, font: { size: 10 }, callback: v => '$' + v + 'M' } }, x: { grid: { display: false }, ticks: { color: grayText, font: { size: 9 } } } } } });
new Chart(document.getElementById('expenseChart'), { type: 'doughnut', data: { labels: ['Racking','Bulk','Overflow','Cold','Others'], datasets: [{ data: [42,22,15,12,9], backgroundColor: ['#2563eb', '#f97316', '#ec4899', '#8b5cf6', '#06b6d4'], borderWidth: 0 }] }, options: { responsive: true, maintainAspectRatio: false, cutout: '72%', plugins: { legend: { display: false } } } });
new Chart(document.getElementById('cashflowChart'), { type: 'bar', data: { labels: ['Goods Receive','Deliveries','Adjustments','Total'], datasets: [{ label: 'Activity', data: [450, 320, 180, 950], backgroundColor: ['#10b981', '#e11d48', '#e11d48', '#6366f1'], borderRadius: 4, barPercentage: 0.5 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { color: grayText, font: { size: 10 }, callback: v => v } }, x: { grid: { display: false }, ticks: { color: grayText, font: { size: 9 } } } } } });
});