From b43c144a82264ae45194151f107f75ee2ec9e521 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 20 May 2026 09:34:43 -0500 Subject: [PATCH] feat(vcard-api): modal Ver Usuario con tabs + rol select + roles acumulados MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reemplaza drill-down inline de Usuarios por modal 'Ver' con tabs: General, Perfil, VCards, Wallet, Pagos, Logs, MiniWebs - Añade columna Rol en tabla de usuarios con badge coloreado - Edit Usuario: rol_id ahora es
- - + +
✓ Usuario actualizado correctamente.
@@ -847,12 +964,20 @@ function vcardApiApp() { editVcardError: '', editVcardSuccess: false, - // Drill-down por usuario - drillDownUserId: null, - drillDownSection: '', - drillDownItems: [], - drillDownLoading: false, - drillDownError: '', + // Modal ver usuario (detalle completo) + verModal: false, + verData: null, + verTab: 'general', + verLoading: false, + verError: '', + verSectionItems: [], + verSectionLoading: false, + + // Roles conocidos (seed + acumulados de usuarios) + roles: [ + { id: '63c48dd0f0117680cf0cdb79', nombre: 'administrador' }, + { id: '63c48ddbf0117680cf0cdb7a', nombre: 'cliente' }, + ], get totalPages() { return Math.max(1, Math.ceil(this.total / this.perPage)); @@ -869,6 +994,7 @@ function vcardApiApp() { this.membresiaModal = false; this.editUsuarioModal = false; this.editVcardModal = false; + this.verModal = false; }, async loadConfig() { @@ -937,7 +1063,6 @@ function vcardApiApp() { this.items = []; this.total = 0; this.errorMsg = ''; - this.closeDrillDown(); if (this.hasConfig) this.loadTab(); }, @@ -977,9 +1102,11 @@ function vcardApiApp() { if (d.data && Array.isArray(d.data)) { this.items = d.data; this.total = d.total || d.data.length; + if (this.tab === 'usuarios') this._collectRoles(d.data); } else if (Array.isArray(d)) { this.items = d; this.total = d.length; + if (this.tab === 'usuarios') this._collectRoles(d); } else { this.items = []; this.total = 0; @@ -989,6 +1116,17 @@ function vcardApiApp() { this.loading = false; }, + _collectRoles(users) { + users.forEach(u => { + if (u.rol_id && u.rol && u.rol.nombre) { + const id = u.rol_id; + if (!this.roles.find(r => r.id === id)) { + this.roles.push({ id, nombre: u.rol.nombre }); + } + } + }); + }, + clearFilters(tab) { if (tab === 'pagos') this.filters.pagos = { estado: '', moneda: '', desde: '', hasta: '' }; if (tab === 'transacciones') this.filters.transacciones = { type: '', status: '' }; @@ -1119,47 +1257,44 @@ function vcardApiApp() { this.saving = false; }, - // ─── Drill-down por usuario ────────────────────────────────────────── + // ─── Ver Usuario (detalle completo) ───────────────────────────────── - openDrillDown(u) { + async openVerModal(u) { + this.verData = u; + this.verTab = 'general'; + this.verError = ''; + this.verSectionItems = []; + this.verModal = true; + this.verLoading = true; const id = u.id || u._id; - if (this.drillDownUserId === id) { this.closeDrillDown(); return; } - this.drillDownUserId = id; - this.drillDownSection = 'vcards'; - this.drillDownItems = []; - this.drillDownError = ''; - this.loadDrillDown('vcards'); + try { + const r = await fetch(`/app/vcard-api/usuarios/${id}`); + const d = await r.json(); + if (!r.ok) { this.verError = d.error || `Error ${r.status}`; } + else { this.verData = d; } + } catch(e) { this.verError = e.message; } + this.verLoading = false; }, - closeDrillDown() { - this.drillDownUserId = null; - this.drillDownSection = ''; - this.drillDownItems = []; - this.drillDownError = ''; - }, - - async loadDrillDown(section) { - this.drillDownSection = section; - this.drillDownItems = []; - this.drillDownError = ''; - if (!this.drillDownUserId) return; - this.drillDownLoading = true; + async loadVerSection(section) { + if (!['pagos','logs','miniwebs'].includes(section)) return; + this.verSectionItems = []; + this.verSectionLoading = true; + const id = this.verData && (this.verData.id || this.verData._id); + if (!id) { this.verSectionLoading = false; return; } const map = { - vcards: `/app/vcard-api/usuarios/${this.drillDownUserId}/vcards`, - pagos: `/app/vcard-api/usuarios/${this.drillDownUserId}/pagos`, - transacciones: `/app/vcard-api/usuarios/${this.drillDownUserId}/transacciones`, - logs: `/app/vcard-api/usuarios/${this.drillDownUserId}/logs`, - miniwebs: `/app/vcard-api/usuarios/${this.drillDownUserId}/miniwebs`, + pagos: `/app/vcard-api/usuarios/${id}/pagos`, + logs: `/app/vcard-api/usuarios/${id}/logs`, + miniwebs: `/app/vcard-api/usuarios/${id}/miniwebs`, }; try { const r = await fetch(map[section]); const d = await r.json(); - if (!r.ok) { this.drillDownError = d.error || `Error ${r.status}`; } - else if (d.data && Array.isArray(d.data)) { this.drillDownItems = d.data; } - else if (Array.isArray(d)) { this.drillDownItems = d; } - else { this.drillDownError = 'Respuesta inesperada.'; } - } catch(e) { this.drillDownError = e.message; } - this.drillDownLoading = false; + if (!r.ok) {} + else if (d.data && Array.isArray(d.data)) { this.verSectionItems = d.data; } + else if (Array.isArray(d)) { this.verSectionItems = d; } + } catch(e) {} + this.verSectionLoading = false; }, // ─── Membresía ───────────────────────────────────────────────────────