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 = `
`;
}
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 = `
`;
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);