import { api } from "../lib/api.js"; class RecommendationsCrud extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.items = []; this.selected = null; this.loading = false; this.searchQuery = ""; this.editMode = null; // 'create' | 'edit' | null this.shadowRoot.innerHTML = `
Reglas de Recomendacion
Cargando...
Detalle
Seleccioná una regla o creá una nueva
`; } connectedCallback() { this.shadowRoot.getElementById("search").oninput = (e) => { this.searchQuery = e.target.value; clearTimeout(this._searchTimer); this._searchTimer = setTimeout(() => this.load(), 300); }; this.shadowRoot.getElementById("newBtn").onclick = () => this.showCreateForm(); this.load(); } async load() { this.loading = true; this.renderList(); try { const data = await api.recommendations({ q: this.searchQuery, limit: 200 }); this.items = data.items || []; this.loading = false; this.renderList(); } catch (e) { console.error("Error loading recommendations:", e); this.items = []; this.loading = false; this.renderList(); } } renderList() { const list = this.shadowRoot.getElementById("list"); if (this.loading) { list.innerHTML = `
Cargando...
`; return; } if (!this.items.length) { list.innerHTML = `
No se encontraron reglas
`; return; } list.innerHTML = ""; for (const item of this.items) { const el = document.createElement("div"); el.className = "item" + (this.selected?.id === item.id ? " active" : ""); const trigger = item.trigger || {}; const keywords = (trigger.keywords || []).join(", ") || "—"; const queries = (item.queries || []).slice(0, 3).join(", "); const hasMore = (item.queries || []).length > 3; el.innerHTML = `
${item.rule_key} ${item.active ? "Activa" : "Inactiva"} P: ${item.priority}
Keywords: ${keywords}
→ ${queries}${hasMore ? "..." : ""}
`; el.onclick = () => { this.selected = item; this.editMode = "edit"; this.renderList(); this.renderForm(); }; list.appendChild(el); } } showCreateForm() { this.selected = null; this.editMode = "create"; this.renderList(); this.renderForm(); } renderForm() { const form = this.shadowRoot.getElementById("form"); const title = this.shadowRoot.getElementById("formTitle"); if (!this.editMode) { title.textContent = "Detalle"; form.innerHTML = `
Seleccioná una regla o creá una nueva
`; return; } const isCreate = this.editMode === "create"; title.textContent = isCreate ? "Nueva Regla" : "Editar Regla"; const rule_key = this.selected?.rule_key || ""; const trigger = this.selected?.trigger || {}; const queries = this.selected?.queries || []; const ask_slots = this.selected?.ask_slots || []; const active = this.selected?.active !== false; const priority = this.selected?.priority || 100; // Convert arrays to comma-separated strings for display const triggerKeywords = (trigger.keywords || []).join(", "); const queriesText = (queries || []).join(", "); const askSlotsText = Array.isArray(ask_slots) ? ask_slots.map(s => typeof s === "string" ? s : s?.slot || s?.keyword || "").filter(Boolean).join(", ") : ""; form.innerHTML = `
Sin espacios, en minusculas con guiones bajos
Mayor = primero
Palabras que activan esta regla, separadas por coma
Productos a buscar cuando se activa la regla, separados por coma
El bot preguntara al usuario sobre estos temas de forma natural
${!isCreate ? `` : ""}
`; this.shadowRoot.getElementById("saveBtn").onclick = () => this.save(); this.shadowRoot.getElementById("cancelBtn").onclick = () => this.cancel(); if (!isCreate) { this.shadowRoot.getElementById("deleteBtn").onclick = () => this.delete(); } } parseCommaSeparated(str) { return String(str || "") .split(",") .map(s => s.trim().toLowerCase()) .filter(Boolean); } async save() { const ruleKey = this.shadowRoot.getElementById("ruleKeyInput").value.trim().toLowerCase().replace(/\s+/g, "_"); const priority = parseInt(this.shadowRoot.getElementById("priorityInput").value, 10) || 100; const active = this.shadowRoot.getElementById("activeInput").checked; // Parse comma-separated values into arrays const triggerKeywords = this.parseCommaSeparated(this.shadowRoot.getElementById("triggerInput").value); const queries = this.parseCommaSeparated(this.shadowRoot.getElementById("queriesInput").value); const askSlotsKeywords = this.parseCommaSeparated(this.shadowRoot.getElementById("askSlotsInput").value); if (!ruleKey) { alert("El rule_key es requerido"); return; } // Build trigger object with keywords array const trigger = triggerKeywords.length > 0 ? { keywords: triggerKeywords } : {}; // Ask slots as simple array of keywords (LLM will formulate questions naturally) const ask_slots = askSlotsKeywords; const data = { rule_key: ruleKey, trigger, queries, ask_slots, active, priority, }; try { if (this.editMode === "create") { await api.createRecommendation(data); } else { await api.updateRecommendation(this.selected.id, data); } this.editMode = null; this.selected = null; await this.load(); this.renderForm(); } catch (e) { console.error("Error saving recommendation:", e); alert("Error guardando: " + (e.message || e)); } } async delete() { if (!this.selected?.id) return; if (!confirm(`¿Eliminar la regla "${this.selected.rule_key}"?`)) return; try { await api.deleteRecommendation(this.selected.id); this.editMode = null; this.selected = null; await this.load(); this.renderForm(); } catch (e) { console.error("Error deleting recommendation:", e); alert("Error eliminando: " + (e.message || e)); } } cancel() { this.editMode = null; this.selected = null; this.renderList(); this.renderForm(); } } customElements.define("recommendations-crud", RecommendationsCrud);