`;
}).join('') || '
No recent activity.
'; } function renderUpdateForm() { updateItemSelect.innerHTML = state.items.map(i => ``).join(''); } function renderConfiguration() { itemCategorySelect.innerHTML = state.categories.map(c => ``).join(''); itemsList.innerHTML = state.items.map(item => { const category = state.categories.find(c => c.id === item.categoryId); return `
${item.name}
${category?.name || 'N/A'}
Stock: ${item.currentStock}
`
}).join('') || 'No items configured.
'; categoriesList.innerHTML = state.categories.map(c => `${c.name}
`).join('');
}
// SECTION: Event Handlers
function handleTabClick(tabName) { state.activeTab = tabName; render(); }
function handleNavClick(dir) { const i = TABS.indexOf(state.activeTab); const newI = i + dir; if (newI >= 0 && newI < TABS.length) { state.activeTab = TABS[newI]; render(); } }
function handleAddCategory(e) { e.preventDefault(); const name = categoryNameInput.value.trim(); if(name){ state.categories.push({id: Date.now(), name}); categoryNameInput.value = ''; saveState(); render(); } }
function handleDelete(type, id) { if(confirm(`Delete this ${type}? This action cannot be undone.`)){ state[type+'s'] = state[type+'s'].filter(item => item.id !== id); saveState(); render(); } }
function handleAddItem(e) {
e.preventDefault();
const item = { id: Date.now(), name: itemNameInput.value.trim(), categoryId: parseInt(itemCategorySelect.value), lowStockThreshold: parseInt(itemLowStockInput.value), currentStock: 0 };
state.items.push(item);
state.activityLog.push({ id: Date.now(), itemId: item.id, action: 'created', quantity: 0, date: new Date() });
addItemForm.reset();
saveState();
render();
}
function handleUpdateInventory(e) {
e.preventDefault();
const itemId = parseInt(updateItemSelect.value);
const action = updateActionSelect.value;
const quantity = parseInt(updateQuantityInput.value);
const item = state.items.find(i => i.id === itemId);
if (action === 'check_out' && quantity > item.currentStock) {
alert('Error: Cannot check out more items than are in stock.');
return;
}
item.currentStock = action === 'check_in' ? item.currentStock + quantity : item.currentStock - quantity;
state.activityLog.push({ id: Date.now(), itemId, action, quantity, date: new Date() });
updateForm.reset();
saveState();
alert('Inventory updated successfully!');
state.activeTab = 'dashboard';
render();
}
function generatePDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
doc.setFontSize(22); doc.text('Office Supply Inventory Report', 105, 20, { align: 'center' });
doc.setFontSize(10); doc.setTextColor(150); doc.text(`Generated on: ${new Date().toLocaleDateString()}`, 105, 27, { align: 'center' });
const tableBody = state.items.map(item => {
const category = state.categories.find(c => c.id === item.categoryId)?.name || 'N/A';
let status = 'In Stock';
if (item.currentStock === 0) status = 'Out of Stock';
else if (item.currentStock <= item.lowStockThreshold) status = 'Low Stock';
return [item.name, category, item.currentStock, item.lowStockThreshold, status];
});
doc.autoTable({
head: [['Item Name', 'Category', 'Current Stock', 'Low Stock Level', 'Status']], body: tableBody, startY: 40, theme: 'grid',
headStyles: { fillColor: [37, 99, 235] },
didDrawPage: data => { doc.setFontSize(8); doc.setTextColor(150); doc.text('Page ' + data.pageNumber, data.settings.margin.left, doc.internal.pageSize.height - 10); }
});
doc.save(`Inventory_Report_${new Date().toISOString().slice(0,10)}.pdf`);
}
// SECTION: Event Listeners
Object.keys(tabButtons).forEach(id => tabButtons[id]?.addEventListener('click', () => handleTabClick(id)));
prevTabBtn?.addEventListener('click', () => handleNavClick(-1));
nextTabBtn?.addEventListener('click', () => handleNavClick(1));
downloadPdfBtn?.addEventListener('click', generatePDF);
updateForm?.addEventListener('submit', handleUpdateInventory);
addItemForm?.addEventListener('submit', handleAddItem);
addCategoryForm?.addEventListener('submit', handleAddCategory);
itemsList?.addEventListener('click', e => { if(e.target.classList.contains('delete-item-btn')) handleDelete('item', parseInt(e.target.dataset.id)); });
categoriesList?.addEventListener('click', e => { if(e.target.classList.contains('delete-category-btn')) handleDelete('category', parseInt(e.target.dataset.id)); });
// SECTION: Initial Load
loadState();
render();
});
