import { api } from "../lib/api.js"; import { modal } from "../lib/modal.js"; import { toast } from "../lib/toast.js"; class SystemUsersCrud extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.users = []; this.selected = null; // user seleccionado (objeto) this.editing = null; // copia editable de selected this.creating = false; // si true, editing es un user nuevo this.loading = false; this.saving = false; this.shadowRoot.innerHTML = `

Operadores

Lista

Detalle

`; } connectedCallback() { this.shadowRoot.getElementById("btnNew").addEventListener("click", () => this.startCreate()); this.load(); } meId() { const u = window.__USER__; return u ? Number(u.id) : null; } async load() { this.loading = true; this.renderList(); try { const data = await api.listSystemUsers(); this.users = data.items || []; this.loading = false; // Si hay seleccionado, refrescar referencia. if (this.selected) { this.selected = this.users.find((u) => Number(u.id) === Number(this.selected.id)) || null; } this.renderList(); this.renderForm(); } catch (e) { this.loading = false; this.renderList(); } } startCreate() { this.creating = true; this.selected = null; this.editing = { email: "", name: "", password: "", active: true }; this.renderList(); this.renderForm(); } selectUser(user) { this.creating = false; this.selected = user; this.editing = { ...user, password: "" }; this.renderList(); this.renderForm(); } renderList() { const list = this.shadowRoot.getElementById("list"); if (this.loading) { list.innerHTML = `
Cargando...
`; return; } if (!this.users.length) { list.innerHTML = `
No hay operadores
`; return; } const meId = this.meId(); list.innerHTML = this.users.map((u) => { const isMe = Number(u.id) === meId; const active = !this.creating && this.selected?.id === u.id ? "active" : ""; const inactive = !u.active ? "inactive" : ""; return `
${this.escapeHtml(u.email)}${isMe ? 'Vos' : ""}${!u.active ? 'Inactivo' : ""}
${this.escapeHtml(u.name)}
`; }).join(""); list.querySelectorAll(".item[data-id]").forEach((el) => { el.addEventListener("click", () => { const u = this.users.find((x) => String(x.id) === el.dataset.id); if (u) this.selectUser(u); }); }); } renderForm() { const title = this.shadowRoot.getElementById("formTitle"); const slot = this.shadowRoot.getElementById("formSlot"); if (!this.editing) { title.textContent = "Detalle"; slot.innerHTML = `
Seleccioná un operador o creá uno nuevo.
`; return; } const isCreate = this.creating; const meId = this.meId(); const isSelf = !isCreate && Number(this.selected?.id) === meId; title.textContent = isCreate ? "Nuevo operador" : `Editar — ${this.selected?.email || ""}`; slot.innerHTML = `
${!isCreate ? '
El email no se puede cambiar (volvete a crear el operador si hace falta).
' : ""}
${isCreate ? '
Mínimo 8 caracteres.
' : ""}
${isCreate ? "" : `
${isSelf ? '
No podés desactivarte a vos mismo.
' : ""}
`}
${isCreate || isSelf ? "" : ''}
`; this.shadowRoot.getElementById("btnCancel").addEventListener("click", () => { this.creating = false; this.editing = this.selected ? { ...this.selected, password: "" } : null; this.renderForm(); }); this.shadowRoot.getElementById("btnSave").addEventListener("click", () => this.save()); this.shadowRoot.getElementById("btnDelete")?.addEventListener("click", () => this.remove()); } async save() { const f = this.shadowRoot; const email = f.getElementById("fEmail").value.trim(); const name = f.getElementById("fName").value.trim(); const password = f.getElementById("fPassword").value; const activeEl = f.getElementById("fActive"); const active = activeEl ? activeEl.value === "true" : true; if (this.creating) { if (!email) return toast({ kind: "error", text: "Email requerido" }); if (!name) return toast({ kind: "error", text: "Nombre requerido" }); if (!password || password.length < 8) return toast({ kind: "error", text: "Contraseña mínimo 8 caracteres" }); } else { if (!name) return toast({ kind: "error", text: "Nombre requerido" }); if (password && password.length < 8) return toast({ kind: "error", text: "Contraseña mínimo 8 caracteres" }); } this.saving = true; this.renderForm(); try { if (this.creating) { await api.createSystemUser({ email, name, password, active }); toast({ kind: "ok", text: "Operador creado" }); } else { const payload = { name, active }; if (password) payload.password = password; await api.updateSystemUser(this.selected.id, payload); toast({ kind: "ok", text: "Cambios guardados" }); } this.creating = false; await this.load(); } catch (e) { // safeFetch ya muestra toast } finally { this.saving = false; this.renderForm(); } } async remove() { if (!this.selected) return; const ok = await modal.confirm(`¿Eliminar al operador ${this.selected.email}? Pierde acceso al sistema.`, { confirmText: "Eliminar", cancelText: "Cancelar" }); if (!ok) return; try { await api.deleteSystemUser(this.selected.id); toast({ kind: "ok", text: "Operador eliminado" }); this.selected = null; this.editing = null; await this.load(); } catch (e) {} } escapeHtml(s) { return String(s ?? "").replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } } customElements.define("system-users-crud", SystemUsersCrud);