133 lines
6.9 KiB
HTML
133 lines
6.9 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Historial{% endblock %}
|
|
{% block header %}Historial de Envíos{% endblock %}
|
|
{% block content %}
|
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
|
|
<div class="px-6 py-4 border-b border-gray-200">
|
|
<form class="flex flex-wrap items-end gap-4">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">Tipo</label>
|
|
<select name="tipo" class="px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
<option value="">Todos</option>
|
|
<option value="terceros" {{ 'selected' if filtro_tipo == 'terceros' }}>Terceros</option>
|
|
<option value="transaccion" {{ 'selected' if filtro_tipo == 'transaccion' }}>Transacción</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">Estado</label>
|
|
<select name="status" class="px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
<option value="">Todos</option>
|
|
<option value="success" {{ 'selected' if filtro_status == 'success' }}>Exitoso</option>
|
|
<option value="error" {{ 'selected' if filtro_status == 'error' }}>Error</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">Factura</label>
|
|
<input type="text" name="factura" value="{{ filtro_factura }}"
|
|
class="px-3 py-1.5 border border-gray-300 rounded-lg text-sm" placeholder="Buscar factura...">
|
|
</div>
|
|
<button type="submit" class="px-4 py-1.5 bg-blue-600 text-white rounded-lg text-sm hover:bg-blue-700">
|
|
<i class="fas fa-search mr-1"></i> Filtrar
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if envios %}
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="text-left text-gray-500 border-b border-gray-200">
|
|
<th class="pb-3 font-medium">ID</th>
|
|
<th class="pb-3 font-medium">Tipo</th>
|
|
<th class="pb-3 font-medium">Factura</th>
|
|
<th class="pb-3 font-medium">Estado</th>
|
|
<th class="pb-3 font-medium">Pacientes</th>
|
|
<th class="pb-3 font-medium">Servicios</th>
|
|
<th class="pb-3 font-medium">Respuesta API</th>
|
|
<th class="pb-3 font-medium">Fecha</th>
|
|
<th class="pb-3 font-medium">Usuario</th>
|
|
<th class="pb-3 font-medium"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for e in envios %}
|
|
<tr class="border-b border-gray-50 hover:bg-gray-50">
|
|
<td class="py-3 text-gray-600">{{ e.id }}</td>
|
|
<td class="py-3">
|
|
<span class="px-2 py-1 rounded text-xs font-medium {% if e.tipo == 'terceros' %}bg-blue-100 text-blue-700{% else %}bg-purple-100 text-purple-700{% endif %}">
|
|
{{ e.tipo }}
|
|
</span>
|
|
</td>
|
|
<td class="py-3 text-gray-600 font-medium">{{ e.factura or '-' }}</td>
|
|
<td class="py-3">
|
|
<span class="px-2 py-1 rounded text-xs font-medium {% if e.status == 'success' %}bg-green-100 text-green-700{% else %}bg-red-100 text-red-700{% endif %}">
|
|
{{ 'Exitoso' if e.status == 'success' else 'Error' }}
|
|
</span>
|
|
</td>
|
|
<td class="py-3 text-gray-600">{{ e.pacientes_count or 0 }}</td>
|
|
<td class="py-3 text-gray-600">{{ e.servicios_count or 0 }}</td>
|
|
<td class="py-3 text-gray-500 text-xs max-w-xs truncate">{{ e.respuesta_api[:80] if e.respuesta_api else '-' }}</td>
|
|
<td class="py-3 text-gray-500 text-xs">{{ e.created_at[:19] }}</td>
|
|
<td class="py-3 text-gray-500">{{ e.username }}</td>
|
|
<td class="py-3">
|
|
<button onclick='showDetail({{ e.id|tojson }}, {{ e.json_enviado|tojson if e.json_enviado else "null" }})'
|
|
class="text-blue-600 hover:text-blue-800">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-12 text-gray-400">
|
|
<i class="fas fa-inbox text-5xl mb-4 block"></i>
|
|
<p>No hay registros con los filtros seleccionados</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal JSON -->
|
|
<div id="json-modal" class="fixed inset-0 z-50 hidden">
|
|
<div class="absolute inset-0 bg-black/50" onclick="closeModal()"></div>
|
|
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-2xl bg-white rounded-xl shadow-2xl max-h-[80vh] overflow-hidden">
|
|
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center">
|
|
<h3 class="font-semibold text-gray-800"><i class="fas fa-code mr-2 text-blue-500"></i>JSON Enviado</h3>
|
|
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div class="p-6 overflow-y-auto max-h-[calc(80vh-80px)]">
|
|
<pre id="modal-json" class="text-xs font-mono bg-gray-50 rounded-lg p-4 overflow-x-auto"></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function showDetail(id, json) {
|
|
if (!json) { showToast('No hay JSON disponible', 'info'); return; }
|
|
const pre = document.getElementById('modal-json');
|
|
try {
|
|
const obj = typeof json === 'string' ? JSON.parse(json) : json;
|
|
pre.innerHTML = syntaxHighlight(obj);
|
|
} catch(e) {
|
|
pre.textContent = json;
|
|
}
|
|
document.getElementById('json-modal').classList.remove('hidden');
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('json-modal').classList.add('hidden');
|
|
}
|
|
|
|
function syntaxHighlight(obj) {
|
|
let json = JSON.stringify(obj, null, 2);
|
|
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
return json.replace(/("(?:[^"\\]|\\.)*")(?=\s*:)/g, '<span class="text-blue-600">$1</span>')
|
|
.replace(/:(\s*)("(?:[^"\\]|\\.)*")/g, ': $1<span class="text-green-600">$2</span>')
|
|
.replace(/:(\s*)(\d+)/g, ': $1<span class="text-orange-600">$2</span>')
|
|
.replace(/:(\s*)(null|true|false)/g, ': $1<span class="text-purple-600">$2</span>');
|
|
}
|
|
</script>
|
|
{% endblock %}
|