(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: 'Budget', 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: ['Direct Raw','Indirect','Logistics','IT','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: ['PR Created','PO Issued','Deliveries','Total'], datasets: [{ label: 'Procurement', data: [423, 186, 52, 661], backgroundColor: ['#10b981', '#10b981', '#10b981', '#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 } } }, x: { grid: { display: false }, ticks: { color: grayText, font: { size: 9 } } } } } }); });