import { api } from "../lib/api.js"; const FIXED_EVENTS = [ { id: "asado", label: "Asado / Parrilla" }, { id: "horno", label: "Horno" }, { id: "sanguches", label: "Sanguches" }, ]; const PERSON_TYPES = [ { id: "adult", label: "Adulto" }, { id: "child", label: "NiƱo" }, ]; class QuantitiesCrud extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.products = []; this.ruleCounts = new Map(); this.selectedProduct = null; this.productRules = []; this.loading = false; this.searchQuery = ""; this.saving = false; this.shadowRoot.innerHTML = `
Productos
Cargando...
Cantidades por Persona
Selecciona un producto para configurar cantidades
`; } connectedCallback() { this.shadowRoot.getElementById("search").oninput = (e) => { this.searchQuery = e.target.value; this.renderList(); }; this.load(); } async load() { this.loading = true; this.renderList(); try { // Cargar productos y cantidades en paralelo const [productsData, quantitiesData] = await Promise.all([ api.products({ limit: 2000 }), api.listQuantities(), ]); this.products = (productsData.items || []).filter(p => p.stock_status === "instock"); // Crear mapa de conteo de reglas this.ruleCounts = new Map(); for (const c of (quantitiesData.counts || [])) { this.ruleCounts.set(c.woo_product_id, parseInt(c.rule_count, 10)); } this.loading = false; this.renderList(); } catch (e) { console.error("Error loading:", e); this.loading = false; this.renderList(); } } renderList() { const list = this.shadowRoot.getElementById("list"); if (this.loading) { list.innerHTML = `
Cargando...
`; return; } const q = this.searchQuery.toLowerCase().trim(); let filtered = this.products; if (q) { filtered = filtered.filter(p => p.name.toLowerCase().includes(q)); } if (!filtered.length) { list.innerHTML = `
No se encontraron productos
`; return; } // Ordenar: primero los que tienen reglas, luego por nombre filtered.sort((a, b) => { const countA = this.ruleCounts.get(a.woo_product_id) || 0; const countB = this.ruleCounts.get(b.woo_product_id) || 0; if (countA !== countB) return countB - countA; return a.name.localeCompare(b.name); }); list.innerHTML = ""; for (const product of filtered.slice(0, 100)) { const el = document.createElement("div"); el.className = "item" + (this.selectedProduct?.woo_product_id === product.woo_product_id ? " active" : ""); const ruleCount = this.ruleCounts.get(product.woo_product_id) || 0; el.innerHTML = `
${product.name}
$${product.price || 0} / ${product.sell_unit || 'kg'}
${ruleCount} `; el.onclick = () => this.selectProduct(product); list.appendChild(el); } } async selectProduct(product) { this.selectedProduct = product; this.renderList(); // Cargar reglas del producto try { const data = await api.getProductQuantities(product.woo_product_id); this.productRules = data.rules || []; this.renderForm(); } catch (e) { console.error("Error loading product rules:", e); this.productRules = []; this.renderForm(); } } renderForm() { const form = this.shadowRoot.getElementById("form"); if (!this.selectedProduct) { form.innerHTML = `
Selecciona un producto para configurar cantidades
`; return; } const p = this.selectedProduct; // Crear mapa de reglas existentes: "event_type:person_type" -> rule const ruleMap = new Map(); for (const rule of this.productRules) { const key = `${rule.event_type}:${rule.person_type}`; ruleMap.set(key, rule); } // Generar filas de la grilla const rows = FIXED_EVENTS.map(event => { const cells = PERSON_TYPES.map(person => { const key = `${event.id}:${person.id}`; const rule = ruleMap.get(key); const qty = rule?.qty_per_person ?? ""; const unit = rule?.unit || "kg"; return `
`; }).join(""); return ` ${event.label} ${cells} `; }).join(""); form.innerHTML = `
${p.name}
$${p.price || 0} / ${p.sell_unit || 'kg'}
${PERSON_TYPES.map(pt => ``).join("")} ${rows}
Evento${pt.label}
`; this.shadowRoot.getElementById("saveBtn").onclick = () => this.save(); this.shadowRoot.getElementById("clearBtn").onclick = () => this.clear(); } async save() { if (!this.selectedProduct || this.saving) return; // Recolectar valores de la grilla ANTES de renderizar const rules = []; const qtyInputs = this.shadowRoot.querySelectorAll(".qty-input"); for (const input of qtyInputs) { const eventType = input.dataset.event; const personType = input.dataset.person; const qty = parseFloat(input.value); if (!isNaN(qty) && qty > 0) { const unitSelect = this.shadowRoot.querySelector(`.unit-select[data-event="${eventType}"][data-person="${personType}"]`); const unit = unitSelect?.value || "kg"; rules.push({ event_type: eventType, person_type: personType, qty_per_person: qty, unit, }); } } this.saving = true; this.renderForm(); try { await api.saveProductQuantities(this.selectedProduct.woo_product_id, rules); // Actualizar conteo local this.ruleCounts.set(this.selectedProduct.woo_product_id, rules.length); this.productRules = rules; this.saving = false; this.renderList(); this.renderForm(); const status = this.shadowRoot.getElementById("status"); status.textContent = "Guardado"; status.className = "status"; setTimeout(() => { status.textContent = ""; }, 2000); } catch (e) { console.error("Error saving:", e); this.saving = false; this.renderForm(); const status = this.shadowRoot.getElementById("status"); status.textContent = "Error al guardar"; status.className = "status error"; } } clear() { const qtyInputs = this.shadowRoot.querySelectorAll(".qty-input"); for (const input of qtyInputs) { input.value = ""; } } } customElements.define("quantities-crud", QuantitiesCrud);