import { api } from "../lib/api.js"; import { emit, on } from "../lib/bus.js"; import { modal } from "../lib/modal.js"; class ConversationsCrud extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.items = []; this.selected = null; this.loading = false; this.searchQuery = ""; this.statusFilter = ""; this.stateFilter = ""; this.shadowRoot.innerHTML = `
Conversaciones
Cargando...
Detalle
Selecciona una conversacion
`; } connectedCallback() { this.shadowRoot.getElementById("search").oninput = (e) => { this.searchQuery = e.target.value; clearTimeout(this._searchTimer); this._searchTimer = setTimeout(() => this.load(), 300); }; this.shadowRoot.getElementById("status").onchange = (e) => { this.statusFilter = e.target.value; this.load(); }; this.shadowRoot.getElementById("state").onchange = (e) => { this.stateFilter = e.target.value; this.load(); }; this._unsubUpsert = on("conversation:upsert", (conv) => { const idx = this.items.findIndex(x => x.chat_id === conv.chat_id); if (idx >= 0) this.items[idx] = conv; else this.items.unshift(conv); this.renderList(); }); this.load(); } disconnectedCallback() { this._unsubUpsert?.(); } async load() { this.loading = true; this.renderList(); try { const data = await api.conversations({ q: this.searchQuery, status: this.statusFilter, state: this.stateFilter }); this.items = data.items || []; this.loading = false; this.renderList(); } catch (e) { console.error("Error loading conversations:", 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 conversaciones
`; return; } list.innerHTML = ""; for (const item of this.items) { const el = document.createElement("div"); el.className = "item" + (this.selected?.chat_id === item.chat_id ? " active" : ""); const dotClass = item.status === "ok" ? "ok" : (item.status === "warn" ? "warn" : "err"); const time = item.last_activity ? new Date(item.last_activity).toLocaleString() : "—"; el.innerHTML = `
${item.from || item.chat_id}
${item.chat_id}
state: ${item.state || "—"} intent: ${item.intent || "—"} ${time}
`; el.onclick = () => { this.selected = item; this.renderList(); this.renderDetail(); }; list.appendChild(el); } } renderDetail() { const detail = this.shadowRoot.getElementById("detail"); const title = this.shadowRoot.getElementById("detailTitle"); if (!this.selected) { title.textContent = "Detalle"; detail.innerHTML = `
Selecciona una conversacion
`; return; } const c = this.selected; title.textContent = c.from || c.chat_id; detail.innerHTML = `
${c.chat_id}
${c.from || "—"}
${c.state || "—"}
${c.intent || "—"}
${c.status || "—"}
${c.last_activity ? new Date(c.last_activity).toLocaleString() : "—"}
${c.last_run_id || "—"}
`; detail.scrollTop = 0; this.shadowRoot.getElementById("openChat").onclick = () => { emit("ui:selectedChat", { chat_id: c.chat_id }); emit("ui:switchView", { view: "chat" }); }; this.shadowRoot.getElementById("retryLast").onclick = async () => { try { await api.retryLast(c.chat_id); modal.success("Retry ejecutado"); } catch (e) { modal.error("Error: " + (e.message || e)); } }; this.shadowRoot.getElementById("deleteConv").onclick = async () => { const confirmed = await modal.confirm(`¿Eliminar la conversación de "${c.chat_id}"?`); if (!confirmed) return; try { await api.deleteConversation(c.chat_id); this.selected = null; await this.load(); this.renderDetail(); } catch (e) { modal.error("Error: " + (e.message || e)); } }; } } customElements.define("conversations-crud", ConversationsCrud);