Spaces:
Running
Running
Update events.js
Browse files
events.js
CHANGED
|
@@ -2,26 +2,22 @@
|
|
| 2 |
|
| 3 |
import { appState, saveState } from './state.js';
|
| 4 |
import { handleUpdateStock, handleRestock } from './services.js';
|
| 5 |
-
import { refreshUI, showToast, renderReport } from './ui.js';
|
| 6 |
import { generatePurchaseOrder } from './purchaseOrderService.js';
|
| 7 |
|
| 8 |
-
/**
|
| 9 |
-
* Attaches listeners to elements that are frequently re-rendered.
|
| 10 |
-
*/
|
| 11 |
export function attachAllListeners() {
|
| 12 |
attachProductInputListeners();
|
| 13 |
-
attachCurrentStockEditListeners();
|
| 14 |
attachRestockListeners();
|
| 15 |
attachPurchaseOrderListener();
|
| 16 |
}
|
| 17 |
|
| 18 |
-
/**
|
| 19 |
-
* Attaches listeners to static elements, like modals, only once on startup.
|
| 20 |
-
*/
|
| 21 |
export function attachOneTimeListeners() {
|
| 22 |
attachModalListeners();
|
| 23 |
}
|
| 24 |
|
|
|
|
|
|
|
| 25 |
function attachProductInputListeners() {
|
| 26 |
document.querySelectorAll('.update-btn').forEach(btn => {
|
| 27 |
if (btn.dataset.listenerAttached) return;
|
|
@@ -48,7 +44,7 @@ function attachCurrentStockEditListeners() {
|
|
| 48 |
const input = document.createElement('input');
|
| 49 |
input.type = 'number';
|
| 50 |
input.value = material.currentStock;
|
| 51 |
-
input.className = 'input-field w-24 text-2xl font-bold';
|
| 52 |
|
| 53 |
valueDiv.replaceWith(input);
|
| 54 |
input.focus();
|
|
@@ -62,7 +58,7 @@ function attachCurrentStockEditListeners() {
|
|
| 62 |
refreshUI();
|
| 63 |
} else {
|
| 64 |
showToast('Stock must be a valid positive number.', 'error');
|
| 65 |
-
refreshUI();
|
| 66 |
}
|
| 67 |
};
|
| 68 |
|
|
@@ -98,26 +94,25 @@ function attachRestockListeners() {
|
|
| 98 |
}
|
| 99 |
|
| 100 |
function attachPurchaseOrderListener() {
|
| 101 |
-
const poButton = document.getElementById('
|
| 102 |
if (poButton && !poButton.dataset.listenerAttached) {
|
| 103 |
poButton.dataset.listenerAttached = 'true';
|
| 104 |
poButton.addEventListener('click', () => {
|
| 105 |
-
const materialsToOrder = appState.materials.filter(m => m.currentStock <= m.reorderPoint);
|
| 106 |
if (materialsToOrder.length > 0) {
|
| 107 |
-
|
| 108 |
-
showToast(`Generated consolidated PO for ${materialsToOrder.length} items.`, 'success');
|
| 109 |
} else {
|
| 110 |
-
showToast('No items
|
| 111 |
}
|
| 112 |
});
|
| 113 |
}
|
| 114 |
}
|
| 115 |
|
| 116 |
function attachModalListeners() {
|
|
|
|
| 117 |
const resetModal = document.getElementById('reset-modal');
|
| 118 |
const reportsModal = document.getElementById('reports-modal');
|
| 119 |
|
| 120 |
-
// Reset Modal
|
| 121 |
document.getElementById('show-reset-modal-btn').addEventListener('click', () => resetModal.classList.remove('hidden'));
|
| 122 |
resetModal.addEventListener('click', (e) => {
|
| 123 |
const target = e.target.closest('button');
|
|
@@ -130,7 +125,6 @@ function attachModalListeners() {
|
|
| 130 |
}
|
| 131 |
});
|
| 132 |
|
| 133 |
-
// Reports Modal
|
| 134 |
document.getElementById('show-reports-modal-btn').addEventListener('click', () => reportsModal.classList.remove('hidden'));
|
| 135 |
reportsModal.addEventListener('click', (e) => {
|
| 136 |
const target = e.target.closest('button');
|
|
@@ -140,4 +134,39 @@ function attachModalListeners() {
|
|
| 140 |
if (target && target.id === 'report-prod-summary') renderReport('production');
|
| 141 |
if (target && target.id === 'report-mat-usage') renderReport('material');
|
| 142 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
}
|
|
|
|
| 2 |
|
| 3 |
import { appState, saveState } from './state.js';
|
| 4 |
import { handleUpdateStock, handleRestock } from './services.js';
|
| 5 |
+
import { refreshUI, showToast, renderReport, renderCustomPOModal } from './ui.js';
|
| 6 |
import { generatePurchaseOrder } from './purchaseOrderService.js';
|
| 7 |
|
|
|
|
|
|
|
|
|
|
| 8 |
export function attachAllListeners() {
|
| 9 |
attachProductInputListeners();
|
| 10 |
+
attachCurrentStockEditListeners();
|
| 11 |
attachRestockListeners();
|
| 12 |
attachPurchaseOrderListener();
|
| 13 |
}
|
| 14 |
|
|
|
|
|
|
|
|
|
|
| 15 |
export function attachOneTimeListeners() {
|
| 16 |
attachModalListeners();
|
| 17 |
}
|
| 18 |
|
| 19 |
+
// ... (keep attachProductInputListeners, attachCurrentStockEditListeners, attachRestockListeners) ...
|
| 20 |
+
|
| 21 |
function attachProductInputListeners() {
|
| 22 |
document.querySelectorAll('.update-btn').forEach(btn => {
|
| 23 |
if (btn.dataset.listenerAttached) return;
|
|
|
|
| 44 |
const input = document.createElement('input');
|
| 45 |
input.type = 'number';
|
| 46 |
input.value = material.currentStock;
|
| 47 |
+
input.className = 'input-field w-24 text-2xl font-bold';
|
| 48 |
|
| 49 |
valueDiv.replaceWith(input);
|
| 50 |
input.focus();
|
|
|
|
| 58 |
refreshUI();
|
| 59 |
} else {
|
| 60 |
showToast('Stock must be a valid positive number.', 'error');
|
| 61 |
+
refreshUI();
|
| 62 |
}
|
| 63 |
};
|
| 64 |
|
|
|
|
| 94 |
}
|
| 95 |
|
| 96 |
function attachPurchaseOrderListener() {
|
| 97 |
+
const poButton = document.getElementById('open-po-modal-btn');
|
| 98 |
if (poButton && !poButton.dataset.listenerAttached) {
|
| 99 |
poButton.dataset.listenerAttached = 'true';
|
| 100 |
poButton.addEventListener('click', () => {
|
| 101 |
+
const materialsToOrder = appState.materials.filter(m => m.currentStock <= m.reorderPoint * 1.5);
|
| 102 |
if (materialsToOrder.length > 0) {
|
| 103 |
+
renderCustomPOModal(materialsToOrder);
|
|
|
|
| 104 |
} else {
|
| 105 |
+
showToast('No items need reordering.', 'info');
|
| 106 |
}
|
| 107 |
});
|
| 108 |
}
|
| 109 |
}
|
| 110 |
|
| 111 |
function attachModalListeners() {
|
| 112 |
+
// Standard Modals (Reset, Reports)
|
| 113 |
const resetModal = document.getElementById('reset-modal');
|
| 114 |
const reportsModal = document.getElementById('reports-modal');
|
| 115 |
|
|
|
|
| 116 |
document.getElementById('show-reset-modal-btn').addEventListener('click', () => resetModal.classList.remove('hidden'));
|
| 117 |
resetModal.addEventListener('click', (e) => {
|
| 118 |
const target = e.target.closest('button');
|
|
|
|
| 125 |
}
|
| 126 |
});
|
| 127 |
|
|
|
|
| 128 |
document.getElementById('show-reports-modal-btn').addEventListener('click', () => reportsModal.classList.remove('hidden'));
|
| 129 |
reportsModal.addEventListener('click', (e) => {
|
| 130 |
const target = e.target.closest('button');
|
|
|
|
| 134 |
if (target && target.id === 'report-prod-summary') renderReport('production');
|
| 135 |
if (target && target.id === 'report-mat-usage') renderReport('material');
|
| 136 |
});
|
| 137 |
+
|
| 138 |
+
// Custom PO Modal
|
| 139 |
+
const customPOModal = document.getElementById('custom-po-modal');
|
| 140 |
+
customPOModal.addEventListener('click', e => {
|
| 141 |
+
const target = e.target;
|
| 142 |
+
// Close modal actions
|
| 143 |
+
if (target.id === 'custom-po-modal' || target.id === 'cancel-po-btn' || target.id === 'cancel-po-btn-footer' || target.closest('#cancel-po-btn')) {
|
| 144 |
+
customPOModal.classList.add('hidden');
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
// Generate PDF action
|
| 148 |
+
if (target.id === 'confirm-po-generation-btn') {
|
| 149 |
+
const supplierName = document.getElementById('supplier-name').value.trim();
|
| 150 |
+
const selectedItems = [];
|
| 151 |
+
|
| 152 |
+
document.querySelectorAll('.po-item-select:checked').forEach(checkbox => {
|
| 153 |
+
const row = checkbox.closest('.po-item-row');
|
| 154 |
+
const materialName = row.dataset.materialName;
|
| 155 |
+
const material = appState.materials.find(m => m.name === materialName);
|
| 156 |
+
const quantity = parseInt(row.querySelector('.po-item-qty').value, 10);
|
| 157 |
+
|
| 158 |
+
if (material && !isNaN(quantity) && quantity > 0) {
|
| 159 |
+
selectedItems.push({ material, quantity });
|
| 160 |
+
}
|
| 161 |
+
});
|
| 162 |
+
|
| 163 |
+
if (selectedItems.length > 0) {
|
| 164 |
+
generatePurchaseOrder(selectedItems, supplierName);
|
| 165 |
+
showToast(`Generated PO for ${selectedItems.length} items.`, 'success');
|
| 166 |
+
customPOModal.classList.add('hidden');
|
| 167 |
+
} else {
|
| 168 |
+
showToast('No items selected or quantities are invalid.', 'error');
|
| 169 |
+
}
|
| 170 |
+
}
|
| 171 |
+
});
|
| 172 |
}
|