diff --git a/src/components/CardGrid.astro b/src/components/CardGrid.astro index 07af2f7..c0e9fc4 100644 --- a/src/components/CardGrid.astro +++ b/src/components/CardGrid.astro @@ -461,6 +461,91 @@ import BackToTop from "./BackToTop.astro" }); const cardModal = document.getElementById('cardModal'); + + // ── Delegated submit handler for inventory form ────────────────────────── + cardModal.addEventListener('submit', async (e) => { + const form = e.target.closest('[data-inventory-form]'); + if (!form) return; + e.preventDefault(); + + if (!form.checkValidity()) { form.classList.add('was-validated'); return; } + + const cardId = form.closest('[data-card-id]')?.dataset.cardId; + if (!cardId) return; + + const submitBtn = form.querySelector('button[type="submit"]'); + if (submitBtn) { submitBtn.disabled = true; submitBtn.textContent = 'Saving…'; } + + const body = new FormData(form); + body.append('action', 'add'); + body.append('cardId', cardId); + + try { + const res = await fetch('/api/inventory', { method: 'POST', body }); + const html = await res.text(); + const invList = document.getElementById('inventoryEntryList'); + if (invList) invList.innerHTML = html || ''; + form.reset(); + form.classList.remove('was-validated'); + } catch { + // keep current inventory list state + } finally { + if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = 'Save to inventory'; } + } + }); + + // ── Delegated click handler for inventory entry buttons ───────────────── + cardModal.addEventListener('click', async (e) => { + const btn = e.target.closest('[data-inv-action]'); + if (!btn) return; + + const article = btn.closest('[data-inventory-id]'); + if (!article) return; + + const action = btn.dataset.invAction; + const inventoryId = article.dataset.inventoryId; + const cardId = article.dataset.cardId; + const qtyEl = article.querySelector('[data-inv-qty]'); + let qty = Number(qtyEl?.textContent) || 1; + + if (action === 'increment') { + qtyEl.textContent = ++qty; + return; + } + + if (action === 'decrement') { + if (qty > 1) qtyEl.textContent = --qty; + return; + } + + // update or remove — POST to API and reload inventory list + btn.disabled = true; + const body = new FormData(); + body.append('cardId', cardId); + + if (action === 'update') { + body.append('action', 'update'); + body.append('inventoryId', inventoryId); + body.append('quantity', String(qty)); + body.append('purchasePrice', article.dataset.purchasePrice); + body.append('note', article.dataset.note || ''); + } else if (action === 'remove') { + body.append('action', 'remove'); + body.append('inventoryId', inventoryId); + } + + try { + const res = await fetch('/api/inventory', { method: 'POST', body }); + const html = await res.text(); + const invList = document.getElementById('inventoryEntryList'); + if (invList) invList.innerHTML = html || ''; + } catch { + // keep current state + } finally { + btn.disabled = false; + } + }); + cardModal.addEventListener('shown.bs.modal', () => { updateNavButtons(cardModal); initChartAfterSwap(cardModal); diff --git a/src/pages/api/inventory.ts b/src/pages/api/inventory.ts index d918936..02ce7f8 100644 --- a/src/pages/api/inventory.ts +++ b/src/pages/api/inventory.ts @@ -24,7 +24,11 @@ const getInventory = async (userId:string, cardId:number) => { const invHtml = inventories.map(inv => { return ` -
+
@@ -52,14 +56,14 @@ const getInventory = async (userId:string, cardId:number) => {
Qty
- - - + + +
- - + +