Low Stock Alert System

Low Stock Alert System

Monitor inventory levels and get alerts for products that need reordering.

Products Requiring Action

Configure your products and alert threshold, then click "Check Stock Levels" on the configuration tab.

${lowStockItems.length}

Total Products Tracked

${products.length}

Most Urgent Item

${mostUrgent}

`; // Render Alert Cards if (lowStockItems.length === 0) { alertContainer.innerHTML = `
All products are above the stock threshold.
`; } else { alertContainer.innerHTML = lowStockItems.map(p => `

${p.name}

Current Stock: ${p.inventory} units

Reorder Needed
`).join(''); } }; // --- CORE LOGIC --- const handleCheck = () => { checkBtnSpinner.classList.remove('hidden'); checkBtnText.textContent = 'Checking...'; checkBtn.disabled = true; setTimeout(() => { const threshold = parseInt(document.getElementById('low-stock-threshold').value); const lowStockItems = products.filter(p => p.inventory <= threshold); renderDashboard(lowStockItems); switchTab('dashboard'); downloadPdfBtn.disabled = lowStockItems.length === 0; checkBtnSpinner.classList.add('hidden'); checkBtnText.textContent = 'Check Stock Levels'; checkBtn.disabled = false; }, 500); }; // --- UI & EVENT HANDLERS --- const switchTab = (tabId) => { currentTab = tabId; Object.values(tabPanes).forEach(pane => pane.classList.add('hidden')); tabPanes[tabId].classList.remove('hidden'); Object.values(tabButtons).forEach(btn => btn.classList.replace('tab-active', 'tab-inactive')); tabButtons[tabId].classList.replace('tab-inactive', 'tab-active'); updateNavButtons(); }; const navigateTabs = (direction) => { const currentIndex = tabs.indexOf(currentTab); const newIndex = direction === 'next' ? currentIndex + 1 : currentIndex - 1; if (newIndex >= 0 && newIndex < tabs.length) switchTab(tabs[newIndex]); }; const updateNavButtons = () => { const currentIndex = tabs.indexOf(currentTab); prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); }; const handlePdfDownload = () => { const pdfRenderContainer = document.getElementById('pdf-render-content'); const pdfContent = document.getElementById('pdf-content').innerHTML; const threshold = document.getElementById('low-stock-threshold').value; const header = `

Low Stock Report (Threshold: ${threshold})

`; pdfRenderContainer.innerHTML = header + pdfContent + '
'; html2canvas(pdfRenderContainer, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(), margin = 40; const contentWidth = pdfWidth - margin * 2; const pdfHeight = (canvas.height * contentWidth) / canvas.width; pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, pdfHeight); pdf.save('Low-Stock-Report.pdf'); }); }; // --- EVENT LISTENERS --- window.switchTab = switchTab; window.navigateTabs = navigateTabs; checkBtn.addEventListener('click', handleCheck); downloadPdfBtn.addEventListener('click', handlePdfDownload); addProductBtn.addEventListener('click', () => { products.push({ id: nextId++, name: 'New Product', inventory: 0 }); renderConfigTable(); }); configTableBody.addEventListener('input', e => { if (!e.target.classList.contains('cfg-input')) return; const id = parseInt(e.target.closest('tr').dataset.id); const prop = e.target.dataset.prop; const item = products.find(p => p.id === id); if (item) item[prop] = e.target.type === 'number' ? parseInt(e.target.value) : e.target.value; }); configTableBody.addEventListener('click', e => { if (!e.target.classList.contains('rm-btn')) return; const id = parseInt(e.target.closest('tr').dataset.id); products = products.filter(p => p.id !== id); renderConfigTable(); }); // --- INITIALIZATION --- renderConfigTable(); updateNavButtons(); switchTab('dashboard'); });
Scroll to Top