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 = `
`;
}
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 = `
| Evento |
${PERSON_TYPES.map(pt => `${pt.label} | `).join("")}
${rows}
`;
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);