up
This commit is contained in:
@@ -330,7 +330,8 @@
|
||||
x-text="log.procesado ? 'Procesado' : 'Pendiente'"></span>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-gray-400" x-text="log.CreatedAt ? new Date(log.CreatedAt).toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'}) : '—'"></td>
|
||||
<td class="py-3 px-4">
|
||||
<td class="py-3 px-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<button @click="selectedLog = log; showLogModal = true" title="Ver detalle"
|
||||
class="text-gray-400 hover:text-[#8eb02f] transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
@@ -338,6 +339,17 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Botón Validar: en API_CHECK con datos incompletos, o en cualquier log si contrato no confirmado -->
|
||||
<button x-show="log.tipo === 'API_CHECK' && (!log.payer_email || !log.monto)"
|
||||
@click="validarLog(log)"
|
||||
:disabled="validandoLogID === log.ID"
|
||||
title="Verificar pago en todas las fuentes (Bold API, dLocal, logs)"
|
||||
class="flex items-center gap-1 text-[10px] px-2 py-0.5 rounded border border-indigo-300 text-indigo-600 hover:bg-indigo-50 disabled:opacity-40 transition-colors">
|
||||
<svg x-show="validandoLogID !== log.ID" class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"/></svg>
|
||||
<svg x-show="validandoLogID === log.ID" class="w-3 h-3 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
Validar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -536,6 +548,14 @@
|
||||
<button @click="dlocalTab = 'config'"
|
||||
:class="dlocalTab==='config' ? 'border-b-2 border-[#8eb02f] text-[#6d8c24] font-semibold' : 'text-gray-400 hover:text-gray-600'"
|
||||
class="pb-2 transition-colors">Configuración</button>
|
||||
<button @click="dlocalTab = 'notificaciones'; loadDlocalLogs()"
|
||||
:class="dlocalTab==='notificaciones' ? 'border-b-2 border-[#8eb02f] text-[#6d8c24] font-semibold' : 'text-gray-400 hover:text-gray-600'"
|
||||
class="pb-2 transition-colors flex items-center gap-1">
|
||||
Notificaciones
|
||||
<span x-show="dlocalLogsTotal > 0"
|
||||
class="bg-[#8eb02f] text-white text-[10px] px-1.5 py-0.5 rounded-full"
|
||||
x-text="dlocalLogsTotal"></span>
|
||||
</button>
|
||||
<button @click="dlocalTab = 'planes'; loadDlocalPlanes()"
|
||||
:class="dlocalTab==='planes' ? 'border-b-2 border-[#8eb02f] text-[#6d8c24] font-semibold' : 'text-gray-400 hover:text-gray-600'"
|
||||
class="pb-2 transition-colors">Planes de suscripción</button>
|
||||
@@ -810,6 +830,152 @@
|
||||
|
||||
</div><!-- /sub-tab planes -->
|
||||
|
||||
<!-- ── Sub-tab: Notificaciones dLocal ───────────────────────────── -->
|
||||
<div x-show="dlocalTab === 'notificaciones'">
|
||||
|
||||
<!-- Filtros rápidos -->
|
||||
<div class="flex flex-wrap items-center gap-3 mb-4">
|
||||
<template x-for="stat in dlocalLogsStats" :key="stat.estado">
|
||||
<button @click="dlocalLogsFilter = stat.estado; dlocalLogsPage = 1; loadDlocalLogs()"
|
||||
class="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-xs font-medium transition-all"
|
||||
:class="dlocalLogsFilter === stat.estado
|
||||
? 'border-[#8eb02f] bg-[#f2f9e6] text-[#6d8c24]'
|
||||
: 'border-gray-200 bg-white text-gray-600 hover:border-gray-300'">
|
||||
<span :class="stat.color" class="w-2 h-2 rounded-full inline-block"></span>
|
||||
<span x-text="stat.label"></span>
|
||||
<span class="font-bold" x-text="stat.count"></span>
|
||||
</button>
|
||||
</template>
|
||||
<button @click="loadDlocalLogs()" class="ml-auto text-xs text-[#8eb02f] hover:underline flex items-center gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
||||
</svg>
|
||||
Refrescar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tabla -->
|
||||
<div class="border border-gray-200 rounded-xl overflow-hidden">
|
||||
<div x-show="dlocalLogs.length === 0" class="py-12 text-center text-gray-400 text-sm">
|
||||
Sin notificaciones de dLocal registradas aún.
|
||||
</div>
|
||||
<div x-show="dlocalLogs.length > 0">
|
||||
<table class="w-full text-xs table-auto">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 text-left border-b">
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Tipo / Fuente</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Payment ID</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Referencia</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Email pagador</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Monto</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Estado</th>
|
||||
<th class="py-3 px-4 font-semibold text-gray-500 uppercase tracking-wide text-[10px]">Fecha</th>
|
||||
<th class="py-3 px-4"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="log in dlocalLogs" :key="log.ID">
|
||||
<tr class="border-b last:border-0 hover:bg-gray-50 transition-colors">
|
||||
<td class="py-3 px-4">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold uppercase w-fit"
|
||||
:class="{
|
||||
'bg-green-50 text-green-700': log.estado === 'PAID' || log.estado === 'AUTHORIZED',
|
||||
'bg-red-50 text-red-600': log.estado === 'REJECTED' || log.estado === 'CANCELLED',
|
||||
'bg-yellow-50 text-yellow-700': log.estado === 'PENDING',
|
||||
'bg-gray-50 text-gray-500': !['PAID','AUTHORIZED','REJECTED','CANCELLED','PENDING'].includes(log.estado)
|
||||
}"
|
||||
x-text="log.estado || '—'"></span>
|
||||
<span class="text-[10px] text-gray-400" x-text="log.tipo || log.fuente || ''"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-3 px-4 font-mono text-gray-500" x-text="(log.payment_id||'—').slice(0,16) + ((log.payment_id||'').length > 16 ? '…' : '')"></td>
|
||||
<td class="py-3 px-4 font-mono text-gray-600" x-text="log.referencia || log.order_id || '—'"></td>
|
||||
<td class="py-3 px-4 text-gray-600" x-text="log.payer_email || '—'"></td>
|
||||
<td class="py-3 px-4 font-semibold text-gray-800" x-text="log.monto ? (log.moneda||'$') + ' ' + Number(log.monto).toLocaleString('es-CO') : '—'"></td>
|
||||
<td class="py-3 px-4">
|
||||
<span class="px-2 py-0.5 rounded text-[10px] font-semibold"
|
||||
:class="log.procesado ? 'bg-green-50 text-green-600' : 'bg-yellow-50 text-yellow-600'"
|
||||
x-text="log.procesado ? 'Procesado' : 'Pendiente'"></span>
|
||||
</td>
|
||||
<td class="py-3 px-4 text-gray-400" x-text="log.CreatedAt ? new Date(log.CreatedAt).toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'}) : '—'"></td>
|
||||
<td class="py-3 px-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<button @click="selectedDlocalLog = log; showDlocalLogModal = true" title="Ver detalle"
|
||||
class="text-gray-400 hover:text-[#8eb02f] transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Botón Validar: en logs sin estado PAID o con datos incompletos -->
|
||||
<button x-show="log.estado !== 'PAID' && log.estado !== 'AUTHORIZED' || (!log.payer_email || !log.monto)"
|
||||
@click="validarDlocalLog(log)"
|
||||
:disabled="validandoDlocalLogID === log.ID"
|
||||
title="Verificar pago en todas las fuentes"
|
||||
class="flex items-center gap-1 text-[10px] px-2 py-0.5 rounded border border-indigo-300 text-indigo-600 hover:bg-indigo-50 disabled:opacity-40 transition-colors">
|
||||
<svg x-show="validandoDlocalLogID !== log.ID" class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"/></svg>
|
||||
<svg x-show="validandoDlocalLogID === log.ID" class="w-3 h-3 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
Validar
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Paginación -->
|
||||
<div class="flex items-center justify-between px-4 py-3 border-t bg-gray-50 text-xs text-gray-500">
|
||||
<span>Mostrando <strong x-text="dlocalLogs.length"></strong> de <strong x-text="dlocalLogsTotal"></strong> registros</span>
|
||||
<div class="flex gap-2">
|
||||
<button :disabled="dlocalLogsPage <= 1" @click="dlocalLogsPage--; loadDlocalLogs()"
|
||||
class="px-3 py-1 rounded border border-gray-200 disabled:opacity-40 hover:bg-white">← Ant</button>
|
||||
<span class="px-2 py-1">Pág <strong x-text="dlocalLogsPage"></strong></span>
|
||||
<button :disabled="dlocalLogs.length < dlocalLogsLimit" @click="dlocalLogsPage++; loadDlocalLogs()"
|
||||
class="px-3 py-1 rounded border border-gray-200 disabled:opacity-40 hover:bg-white">Sig →</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /sub-tab notificaciones dlocal -->
|
||||
|
||||
<!-- Modal detalle log dLocal -->
|
||||
<div x-show="showDlocalLogModal" x-transition class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
|
||||
<div @click.outside="showDlocalLogModal = false" class="bg-white rounded-2xl shadow-2xl w-full max-w-lg p-6 relative">
|
||||
<button @click="showDlocalLogModal = false" class="absolute top-4 right-4 text-gray-400 hover:text-gray-700">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h3 class="text-sm font-semibold mb-4 flex items-center gap-2">
|
||||
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold"
|
||||
:class="{
|
||||
'bg-green-50 text-green-700': selectedDlocalLog?.estado === 'PAID' || selectedDlocalLog?.estado === 'AUTHORIZED',
|
||||
'bg-red-50 text-red-600': selectedDlocalLog?.estado === 'REJECTED',
|
||||
'bg-yellow-50 text-yellow-700': selectedDlocalLog?.estado === 'PENDING',
|
||||
}"
|
||||
x-text="selectedDlocalLog?.estado || ''"></span>
|
||||
Detalle de notificación dLocal
|
||||
</h3>
|
||||
<div class="space-y-2 text-xs mb-4">
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Notification ID</span><span class="font-mono text-gray-700 text-right truncate max-w-[220px]" x-text="selectedDlocalLog?.notification_id || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Payment ID</span><span class="font-mono text-gray-700" x-text="selectedDlocalLog?.payment_id || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Order ID</span><span class="font-mono text-gray-700" x-text="selectedDlocalLog?.order_id || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Referencia</span><span class="font-mono text-gray-700" x-text="selectedDlocalLog?.referencia || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Tipo</span><span class="text-gray-700" x-text="selectedDlocalLog?.tipo || selectedDlocalLog?.fuente || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Email pagador</span><span class="text-gray-700" x-text="selectedDlocalLog?.payer_email || '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Monto</span><span class="font-semibold text-gray-800" x-text="selectedDlocalLog?.monto ? (selectedDlocalLog?.moneda||'') + ' ' + Number(selectedDlocalLog.monto).toLocaleString('es-CO') : '—'"></span></div>
|
||||
<div class="flex justify-between py-1.5 border-b"><span class="text-gray-500">Procesado</span><span :class="selectedDlocalLog?.procesado ? 'text-green-600' : 'text-yellow-600'" x-text="selectedDlocalLog?.procesado ? 'Sí' : 'No'"></span></div>
|
||||
<div class="flex justify-between py-1.5"><span class="text-gray-500">Fecha</span><span class="text-gray-600" x-text="selectedDlocalLog?.CreatedAt ? new Date(selectedDlocalLog.CreatedAt).toLocaleString('es-CO') : '—'"></span></div>
|
||||
</div>
|
||||
<div x-show="selectedDlocalLog?.raw">
|
||||
<p class="text-[10px] font-semibold text-gray-400 uppercase mb-1">Payload RAW</p>
|
||||
<pre class="bg-gray-50 border rounded-lg p-3 text-[10px] font-mono text-gray-600 overflow-x-auto max-h-40"
|
||||
x-text="tryPrettyJson(selectedDlocalLog?.raw)"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div><!-- /container -->
|
||||
@@ -844,8 +1010,8 @@ function pasarelasApp() {
|
||||
boldLogsLimit: 25,
|
||||
boldLogsFilter: '',
|
||||
boldLogsStats: [
|
||||
{ tipo: '', label: 'Todos', color: 'bg-gray-400', count: 0 },
|
||||
{ tipo: 'SALE_APPROVED', label: 'Aprobados', color: 'bg-green-400', count: 0 },
|
||||
{ tipo: '', label: 'Todos', color: 'bg-gray-400', count: 0 },
|
||||
{ tipo: 'APROBADOS', label: 'Aprobados', color: 'bg-green-400', count: 0 },
|
||||
{ tipo: 'SALE_REJECTED', label: 'Rechazados', color: 'bg-red-400', count: 0 },
|
||||
{ tipo: 'SALE_REVERSED', label: 'Revertidos', color: 'bg-orange-400', count: 0 },
|
||||
{ tipo: 'CHARGEBACK', label: 'Contracargos', color: 'bg-purple-400', count: 0 },
|
||||
@@ -863,6 +1029,7 @@ function pasarelasApp() {
|
||||
selectedLog: null,
|
||||
showCallbackModal: false,
|
||||
selectedCallback: null,
|
||||
validandoLogID: 0,
|
||||
|
||||
// ─── dLocal ─────────────────────────────────────────────────────
|
||||
dlocalModo: 'dev',
|
||||
@@ -879,6 +1046,22 @@ function pasarelasApp() {
|
||||
// Sub-tabs dLocal
|
||||
dlocalTab: 'config',
|
||||
|
||||
// Notificaciones dLocal
|
||||
dlocalLogs: [],
|
||||
dlocalLogsTotal: 0,
|
||||
dlocalLogsPage: 1,
|
||||
dlocalLogsLimit: 25,
|
||||
dlocalLogsFilter: '',
|
||||
dlocalLogsStats: [
|
||||
{ estado: '', label: 'Todos', color: 'bg-gray-400', count: 0 },
|
||||
{ estado: 'APROBADOS', label: 'Aprobados', color: 'bg-green-400', count: 0 },
|
||||
{ estado: 'PENDING', label: 'Pendientes', color: 'bg-yellow-400', count: 0 },
|
||||
{ estado: 'REJECTED', label: 'Rechazados', color: 'bg-red-400', count: 0 },
|
||||
],
|
||||
showDlocalLogModal: false,
|
||||
selectedDlocalLog: null,
|
||||
validandoDlocalLogID: 0,
|
||||
|
||||
// Planes dLocal
|
||||
dlocalPlanes: [],
|
||||
dlocalPlanesLoading: false,
|
||||
@@ -950,7 +1133,7 @@ function pasarelasApp() {
|
||||
const all = r.data.total || 0;
|
||||
this.boldLogsStats[0].count = all;
|
||||
// Cargar contadores por tipo en paralelo
|
||||
['SALE_APPROVED','SALE_REJECTED','SALE_REVERSED','CHARGEBACK'].forEach((tipo, i) => {
|
||||
['APROBADOS','SALE_REJECTED','SALE_REVERSED','CHARGEBACK'].forEach((tipo, i) => {
|
||||
axios.get(`/app/pasarelas/bold/logs?page=1&limit=1&tipo=${tipo}`)
|
||||
.then(res => { this.boldLogsStats[i+1].count = res.data.total || 0; })
|
||||
.catch(() => {});
|
||||
@@ -980,6 +1163,27 @@ function pasarelasApp() {
|
||||
});
|
||||
},
|
||||
|
||||
async validarLog(log) {
|
||||
this.validandoLogID = log.ID;
|
||||
try {
|
||||
const { data } = await axios.post(`/app/pasarelas/bold/logs/${log.ID}/validar`);
|
||||
if (data.ok && data.data) {
|
||||
// Actualizar la fila en memoria
|
||||
const idx = this.boldLogs.findIndex(l => l.ID === log.ID);
|
||||
if (idx !== -1) this.boldLogs[idx] = data.data;
|
||||
}
|
||||
const msg = data.mensaje || (data.confirmado ? 'Pago confirmado ✓' : 'Datos actualizados');
|
||||
const tipo = data.confirmado ? 'success' : 'info';
|
||||
this.showToast(msg, data.confirmado ? 'success' : 'error');
|
||||
// Recargar stats si el pago se confirmó ahora
|
||||
if (data.confirmado) this.loadBoldLogs();
|
||||
} catch (e) {
|
||||
this.showToast(e.response?.data?.error || 'Error al validar', 'error');
|
||||
} finally {
|
||||
this.validandoLogID = 0;
|
||||
}
|
||||
},
|
||||
|
||||
tryPrettyJson(raw) {
|
||||
if (!raw) return '';
|
||||
try { return JSON.stringify(JSON.parse(raw), null, 2); } catch (_) { return raw; }
|
||||
@@ -1103,6 +1307,42 @@ function pasarelasApp() {
|
||||
navigator.clipboard.writeText(url).then(() => this.showToast('URL copiada: ' + url));
|
||||
},
|
||||
|
||||
async loadDlocalLogs() {
|
||||
try {
|
||||
const params = new URLSearchParams({ page: this.dlocalLogsPage, limit: this.dlocalLogsLimit });
|
||||
if (this.dlocalLogsFilter) params.set('estado', this.dlocalLogsFilter);
|
||||
const r = await axios.get('/app/pasarelas/dlocal/logs?' + params.toString());
|
||||
this.dlocalLogs = r.data.data || [];
|
||||
this.dlocalLogsTotal = r.data.total || 0;
|
||||
if (!this.dlocalLogsFilter) {
|
||||
this.dlocalLogsStats[0].count = r.data.total || 0;
|
||||
['APROBADOS','PENDING','REJECTED'].forEach((e, i) => {
|
||||
axios.get(`/app/pasarelas/dlocal/logs?page=1&limit=1&estado=${e}`)
|
||||
.then(res => { this.dlocalLogsStats[i+1].count = res.data.total || 0; })
|
||||
.catch(() => {});
|
||||
});
|
||||
}
|
||||
} catch (_) {}
|
||||
},
|
||||
|
||||
async validarDlocalLog(log) {
|
||||
this.validandoDlocalLogID = log.ID;
|
||||
try {
|
||||
const { data } = await axios.post(`/app/pasarelas/dlocal/logs/${log.ID}/validar`);
|
||||
if (data.ok && data.data) {
|
||||
const idx = this.dlocalLogs.findIndex(l => l.ID === log.ID);
|
||||
if (idx !== -1) this.dlocalLogs[idx] = data.data;
|
||||
}
|
||||
const msg = data.mensaje || (data.confirmado ? 'Pago confirmado ✓' : 'Datos actualizados');
|
||||
this.showToast(msg, data.confirmado ? 'success' : 'error');
|
||||
if (data.confirmado) this.loadDlocalLogs();
|
||||
} catch (e) {
|
||||
this.showToast(e.response?.data?.error || 'Error al validar', 'error');
|
||||
} finally {
|
||||
this.validandoDlocalLogID = 0;
|
||||
}
|
||||
},
|
||||
|
||||
// ─── Toast ───────────────────────────────────────────────────────
|
||||
showToast(msg, type = 'success') {
|
||||
this.toast = { show: true, msg, type };
|
||||
|
||||
Reference in New Issue
Block a user