import { api } from "../lib/api.js";
import { emit, on } from "../lib/bus.js";
class ConversationList extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.conversations = [];
this.selected = null;
this.tab = "chats"; // chats | users
this.users = [];
this.selectedUser = null;
this.shadowRoot.innerHTML = `
`;
}
connectedCallback() {
this.shadowRoot.getElementById("tabChats").onclick = () => this.setTab("chats");
this.shadowRoot.getElementById("tabUsers").onclick = () => this.setTab("users");
this.shadowRoot.getElementById("q").oninput = () => {
clearTimeout(this._t);
this._t = setTimeout(() => this.refresh(), 250);
};
this.shadowRoot.getElementById("status").onchange = () => this.refresh();
this.shadowRoot.getElementById("state").onchange = () => this.refresh();
// acciones del usuario seleccionado (solo en tab Users)
this.shadowRoot.getElementById("uaSelect").onclick = () => {
if (!this.selectedUser) return;
emit("ui:selectedChat", { chat_id: this.selectedUser.chat_id });
this.setTab("chats");
};
this.shadowRoot.getElementById("uaDeleteConv").onclick = async () => {
if (!this.selectedUser) return;
const chat_id = this.selectedUser.chat_id;
if (!confirm(`¿Borrar conversación completa de ${chat_id}?`)) return;
await api.deleteConversation(chat_id);
this.selectedUser = null;
await this.refreshUsers();
};
this.shadowRoot.getElementById("uaDeleteUser").onclick = async () => {
if (!this.selectedUser) return;
const chat_id = this.selectedUser.chat_id;
if (!confirm(`¿Borrar usuario ${chat_id}, sus conversaciones y el customer en Woo?`)) return;
await api.deleteUser(chat_id, { deleteWoo: true });
this.selectedUser = null;
await this.refreshUsers();
};
this._unsub1 = on("conversation:upsert", (conv) => {
if (this.tab !== "chats") return;
const idx = this.conversations.findIndex(x => x.chat_id === conv.chat_id);
if (idx >= 0) this.conversations[idx] = conv;
else this.conversations.unshift(conv);
this.render();
});
this.refresh();
}
disconnectedCallback() {
this._unsub1?.();
}
dot(status) {
const cls = status === "ok" ? "ok" : (status === "warn" ? "warn" : "err");
return ``;
}
async refresh() {
try {
if (this.tab === "users") return await this.refreshUsers();
const q = this.shadowRoot.getElementById("q").value || "";
const status = this.shadowRoot.getElementById("status").value || "";
const state = this.shadowRoot.getElementById("state").value || "";
const data = await api.conversations({ q, status, state });
this.conversations = data.items || [];
this.render();
} catch (e) {
console.warn("[conversation-list] refresh failed", e);
}
}
async refreshUsers() {
try {
const q = this.shadowRoot.getElementById("q").value || "";
const data = await api.users({ q, limit: 200 });
this.users = data.items || [];
this.render();
} catch (e) {
console.warn("[conversation-list] refreshUsers failed", e);
}
}
setTab(tab) {
this.tab = tab;
this.shadowRoot.getElementById("tabChats").classList.toggle("active", tab === "chats");
this.shadowRoot.getElementById("tabUsers").classList.toggle("active", tab === "users");
// en users mantenemos el buscador; ocultamos filtros avanzados (status/state)
this.shadowRoot.getElementById("filtersBox").style.display = "block";
const adv = this.shadowRoot.getElementById("status")?.closest(".row");
if (adv) adv.style.display = tab === "chats" ? "flex" : "none";
const qEl = this.shadowRoot.getElementById("q");
qEl.placeholder = tab === "users" ? "Buscar usuario (chat_id / pushName)…" : "Buscar chat_id / teléfono…";
// acciones visibles solo en users (si no hay selección, quedan disabled)
this.renderSelectedUserActions();
this.refresh();
}
renderSelectedUserActions() {
const box = this.shadowRoot.getElementById("userActions");
const inUsers = this.tab === "users";
box.style.display = inUsers ? "block" : "none";
const hasSel = Boolean(this.selectedUser);
const b1 = this.shadowRoot.getElementById("uaSelect");
const b2 = this.shadowRoot.getElementById("uaDeleteConv");
const b3 = this.shadowRoot.getElementById("uaDeleteUser");
if (b1) b1.disabled = !hasSel;
if (b2) b2.disabled = !hasSel;
if (b3) b3.disabled = !hasSel;
}
render() {
const list = this.shadowRoot.getElementById("list");
list.innerHTML = "";
if (this.tab === "users") {
// panel de acciones
this.renderSelectedUserActions();
for (const u of this.users) {
const el = document.createElement("div");
el.className = "item" + (this.selectedUser?.chat_id === u.chat_id ? " active" : "");
const name = u.push_name || u.chat_id.replace(/@.+$/, "");
el.innerHTML = `
${name}
${u.chat_id}
woo_customer_id: ${u.external_customer_id || "—"}
`;
el.onclick = () => {
this.selectedUser = u;
this.render();
};
list.appendChild(el);
}
return;
}
for (const c of this.conversations) {
const el = document.createElement("div");
el.className = "item" + (c.chat_id === this.selected ? " active" : "");
el.innerHTML = `
${this.dot(c.status)}
state: ${c.state}
intent: ${c.intent}
last: ${new Date(c.last_activity).toLocaleTimeString()}
`;
el.onclick = async (e) => {
if (e?.target?.dataset?.del) {
e.stopPropagation();
if (!confirm(`¿Borrar conversación completa de ${c.chat_id}?`)) return;
await api.deleteConversation(c.chat_id);
if (this.selected === c.chat_id) this.selected = null;
await this.refresh();
return;
}
this.selected = c.chat_id;
this.render();
emit("ui:selectedChat", { chat_id: c.chat_id });
};
list.appendChild(el);
}
}
}
customElements.define("conversation-list", ConversationList);