import { api } from "../lib/api.js";
class ProductsCrud extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.items = [];
this.selected = null;
this.loading = false;
this.searchQuery = "";
this.stockFilter = false;
this.shadowRoot.innerHTML = `
Detalle
Seleccioná un producto para ver detalles
`;
}
connectedCallback() {
this.shadowRoot.getElementById("search").oninput = (e) => {
this.searchQuery = e.target.value;
clearTimeout(this._searchTimer);
this._searchTimer = setTimeout(() => this.load(), 300);
};
this.shadowRoot.getElementById("syncBtn").onclick = () => this.syncFromWoo();
// Stats click handlers
this.shadowRoot.getElementById("statTotal").onclick = () => {
this.stockFilter = false;
this.renderList();
this.updateStatStyles();
};
this.shadowRoot.getElementById("statStock").onclick = () => {
this.stockFilter = !this.stockFilter;
this.renderList();
this.updateStatStyles();
};
this.load();
}
updateStatStyles() {
const statTotal = this.shadowRoot.getElementById("statTotal");
const statStock = this.shadowRoot.getElementById("statStock");
statTotal.classList.toggle("active", !this.stockFilter);
statStock.classList.toggle("active", this.stockFilter);
}
async load() {
this.loading = true;
this.renderList();
try {
const data = await api.products({ q: this.searchQuery, limit: 2000 });
this.items = data.items || [];
this.loading = false;
this.renderList();
this.renderStats();
} catch (e) {
console.error("Error loading products:", e);
this.items = [];
this.loading = false;
this.renderList();
}
}
async syncFromWoo() {
const btn = this.shadowRoot.getElementById("syncBtn");
btn.disabled = true;
btn.textContent = "Sincronizando...";
try {
await api.syncProducts();
await this.load();
} catch (e) {
console.error("Error syncing products:", e);
alert("Error sincronizando: " + (e.message || e));
} finally {
btn.disabled = false;
btn.textContent = "Sync Woo";
}
}
renderStats() {
const total = this.items.length;
const inStock = this.items.filter(p => p.stock_status === "instock" || p.payload?.stock_status === "instock").length;
this.shadowRoot.getElementById("totalCount").textContent = total;
this.shadowRoot.getElementById("inStockCount").textContent = inStock;
}
renderList() {
const list = this.shadowRoot.getElementById("list");
if (this.loading) {
list.innerHTML = `Cargando productos...
`;
return;
}
// Filter items based on stock filter
const filteredItems = this.stockFilter
? this.items.filter(p => p.stock_status === "instock" || p.payload?.stock_status === "instock")
: this.items;
if (!filteredItems.length) {
list.innerHTML = `No se encontraron productos
`;
return;
}
list.innerHTML = "";
for (const item of filteredItems) {
const el = document.createElement("div");
el.className = "item" + (this.selected?.woo_product_id === item.woo_product_id ? " active" : "");
const price = item.price != null ? `$${Number(item.price).toLocaleString()}` : "—";
const sku = item.sku || "—";
const stock = item.stock_status || item.payload?.stock_status || "unknown";
const stockBadge = stock === "instock"
? `En stock`
: `Sin stock`;
el.innerHTML = `
${item.name || "Sin nombre"} ${stockBadge}
${price} ·
SKU: ${sku} ·
ID: ${item.woo_product_id}
`;
el.onclick = () => {
this.selected = item;
this.renderList();
this.renderDetail();
// Scroll detail panel to top
const detail = this.shadowRoot.getElementById("detail");
if (detail) detail.scrollTop = 0;
};
list.appendChild(el);
}
}
renderDetail() {
const detail = this.shadowRoot.getElementById("detail");
if (!this.selected) {
detail.innerHTML = `Seleccioná un producto para ver detalles
`;
return;
}
const p = this.selected;
const categories = (p.payload?.categories || []).map(c => c.name).join(", ") || "—";
const attributes = (p.payload?.attributes || []).map(a => `${a.name}: ${a.options?.join(", ")}`).join("; ") || "—";
detail.innerHTML = `
${p.woo_product_id}
${p.price != null ? `$${Number(p.price).toLocaleString()} ${p.currency || ""}` : "—"}
${p.refreshed_at ? new Date(p.refreshed_at).toLocaleString() : "—"}
${JSON.stringify(p.payload || {}, null, 2)}
`;
}
}
customElements.define("products-crud", ProductsCrud);