Spaces:
Running
Running
File size: 8,669 Bytes
5a5996a 8b41798 2313378 572e913 8b41798 5a5996a 2313378 5a5996a 76c2b27 933a12f 8b41798 5a5996a 5676853 f080a44 5676853 933a12f 5676853 f080a44 22f1d46 5676853 3f496fe 8b41798 2313378 3f496fe 8b41798 3f496fe 5676853 572e913 933a12f 572e913 5676853 572e913 933a12f 8b41798 572e913 933a12f 5676853 5a5996a 8b41798 5a5996a 5a50dfa 8b41798 5a5996a 8b41798 933a12f 8b41798 933a12f 5a50dfa 8b41798 933a12f 8b41798 2313378 8b41798 2313378 5a5996a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
// events.js - Manages all event listeners
import { appState } from './state.js';
import { handleUpdateStock, handleRestock, handleSetStock } from './services.js';
import { refreshUI, showToast, renderReport, renderCustomPOModal } from './ui.js';
import { generatePurchaseOrder } from './purchaseOrderService.js';
import { supabase } from './supabaseClient.js';
export function attachAllListeners() {
attachProductInputListeners();
attachCurrentStockEditListeners();
attachRestockListeners();
attachPurchaseOrderListener();
}
export function attachOneTimeListeners() {
attachAuthListeners();
attachModalListeners();
}
function attachProductInputListeners() {
document.querySelectorAll('.update-btn').forEach(btn => {
if (btn.dataset.listenerAttached) return;
btn.dataset.listenerAttached = 'true';
btn.addEventListener('click', (e) => {
const card = e.target.closest('.dashboard-card');
const productName = e.target.dataset.productName;
const quantity = parseInt(card.querySelector('input').value, 10);
handleUpdateStock(productName, quantity);
});
});
}
function attachCurrentStockEditListeners() {
document.querySelectorAll('.edit-current-stock').forEach(icon => {
if (icon.dataset.listenerAttached) return;
icon.dataset.listenerAttached = 'true';
icon.addEventListener('click', (e) => {
const card = e.target.closest('.dashboard-card');
const valueDiv = card.querySelector('.current-stock-value');
const materialName = card.dataset.materialName;
const input = document.createElement('input');
input.type = 'number';
input.value = valueDiv.textContent;
input.className = 'input-field w-24 text-2xl font-bold';
valueDiv.replaceWith(input);
input.focus();
input.select();
const saveChange = () => {
const newValue = parseInt(input.value, 10);
handleSetStock(materialName, newValue);
};
input.addEventListener('blur', saveChange);
input.addEventListener('keydown', (event) => { if (event.key === 'Enter') input.blur(); });
});
});
}
function attachRestockListeners() {
document.querySelectorAll('.restock-icon').forEach(btn => {
if (btn.dataset.listenerAttached) return;
btn.dataset.listenerAttached = 'true';
btn.addEventListener('click', (e) => {
const parentEl = e.target.closest('[data-material-name]');
const materialName = parentEl.dataset.materialName;
const formContainer = parentEl.querySelector('.restock-form');
if (formContainer.classList.contains('hidden')) {
document.querySelectorAll('.restock-form').forEach(f => { f.classList.add('hidden'); f.innerHTML = ''; });
formContainer.classList.remove('hidden');
formContainer.innerHTML = `<div class="flex items-center gap-2"><input type="number" placeholder="Qty" class="input-field w-20"><button class="btn btn-primary text-xs confirm-restock-btn">Add</button></div>`;
const input = formContainer.querySelector('input');
input.focus();
formContainer.querySelector('.confirm-restock-btn').addEventListener('click', () => { handleRestock(materialName, parseInt(input.value, 10)); });
input.addEventListener('keydown', (event) => { if (event.key === 'Enter') handleRestock(materialName, parseInt(input.value, 10)); if (event.key === 'Escape') formContainer.classList.add('hidden'); });
} else {
formContainer.classList.add('hidden');
formContainer.innerHTML = '';
}
});
});
}
function attachPurchaseOrderListener() {
// This listener is now attached dynamically in renderReorderList in ui.js
// We can use event delegation on the header to make it more robust.
const reorderHeader = document.getElementById('reorder-header');
if (reorderHeader && !reorderHeader.dataset.listenerAttached) {
reorderHeader.dataset.listenerAttached = 'true';
reorderHeader.addEventListener('click', (e) => {
if (e.target.id === 'open-po-modal-btn') {
const materialsToOrder = appState.materials.filter(m => m.currentStock <= m.reorderPoint * 1.5);
if (materialsToOrder.length > 0) {
renderCustomPOModal(materialsToOrder);
} else {
showToast('No items need reordering.', 'info');
}
}
});
}
}
function attachAuthListeners() {
const loginForm = document.getElementById('login-form');
const logoutBtn = document.getElementById('logout-btn');
if (loginForm) {
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) {
showToast(`Login failed: ${error.message}`, 'error');
}
// onAuthStateChange in main.js will handle success
});
}
if (logoutBtn) {
logoutBtn.addEventListener('click', async () => {
await supabase.auth.signOut();
// onAuthStateChange in main.js will handle UI changes
});
}
}
function attachModalListeners() {
const resetModal = document.getElementById('reset-modal');
const reportsModal = document.getElementById('reports-modal');
const customPOModal = document.getElementById('custom-po-modal');
document.getElementById('show-reset-modal-btn')?.addEventListener('click', () => resetModal.classList.remove('hidden'));
resetModal.addEventListener('click', async (e) => {
const target = e.target.closest('button');
if ((target && target.id === 'cancel-reset-btn') || e.target === resetModal) {
resetModal.classList.add('hidden');
}
if (target && target.id === 'confirm-reset-btn') {
showToast('Resetting data... please wait.', 'info');
await supabase.from('production_log').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await supabase.from('materials').delete().neq('id', '00000000-0000-0000-0000-000000000000');
window.location.reload();
}
});
document.getElementById('show-reports-modal-btn')?.addEventListener('click', () => reportsModal.classList.remove('hidden'));
reportsModal.addEventListener('click', (e) => {
const target = e.target.closest('button');
if ((target && target.id === 'close-reports-modal-btn') || e.target === reportsModal) {
reportsModal.classList.add('hidden');
}
if (target && target.id === 'report-prod-summary') renderReport('production');
if (target && target.id === 'report-mat-usage') renderReport('material');
});
customPOModal.addEventListener('click', e => {
const target = e.target;
if (target.id === 'custom-po-modal' || target.closest('#cancel-po-btn') || target.id === 'cancel-po-btn-footer') {
customPOModal.classList.add('hidden');
}
if (target.id === 'confirm-po-generation-btn') {
const supplierName = document.getElementById('supplier-name').value.trim();
const selectedItems = [];
document.querySelectorAll('.po-item-select:checked').forEach(checkbox => {
const row = checkbox.closest('.po-item-row');
const materialName = row.dataset.materialName;
const material = appState.materials.find(m => m.name === materialName);
const quantity = parseInt(row.querySelector('.po-item-qty').value, 10);
if (material && !isNaN(quantity) && quantity > 0) {
selectedItems.push({ material, quantity });
}
});
if (selectedItems.length > 0) {
generatePurchaseOrder(selectedItems, supplierName);
showToast(`Generated PO for ${selectedItems.length} items.`, 'success');
customPOModal.classList.add('hidden');
} else {
showToast('No items selected or quantities are invalid.', 'error');
}
}
});
} |