feat(admin): HTML leads list with filter + top empresas + download stats
This commit is contained in:
91
app/templates/admin_leads.html
Normal file
91
app/templates/admin_leads.html
Normal file
@@ -0,0 +1,91 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Admin · Leads — taller-wox{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="admin-section">
|
||||
<div class="admin-header">
|
||||
<div>
|
||||
<p class="eyebrow-light">ADMIN</p>
|
||||
<h1>Leads registrados</h1>
|
||||
<p class="admin-sub">{{ total }} registros · {{ total_downloads }} descargas totales</p>
|
||||
</div>
|
||||
<div class="admin-actions">
|
||||
<a class="btn btn-secondary" href="/admin/leads.csv">Exportar CSV</a>
|
||||
<a class="btn btn-secondary" href="/admin/stats">Ver stats JSON</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-filters">
|
||||
<input type="text" id="filter" placeholder="Filtrar por nombre, email o empresa..." oninput="filterTable()">
|
||||
</div>
|
||||
|
||||
<div class="admin-table-wrap">
|
||||
<table class="admin-table" id="leads-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Nombre</th>
|
||||
<th>Email</th>
|
||||
<th>Empresa</th>
|
||||
<th class="num">Reg.</th>
|
||||
<th>Creado</th>
|
||||
<th>Último</th>
|
||||
<th class="hide-sm">IP</th>
|
||||
<th class="hide-sm">Consent</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for l in leads %}
|
||||
<tr>
|
||||
<td class="muted">{{ l.id }}</td>
|
||||
<td><strong>{{ l.nombre }}</strong></td>
|
||||
<td><a href="mailto:{{ l.email }}">{{ l.email }}</a></td>
|
||||
<td>{{ l.empresa }}</td>
|
||||
<td class="num">{{ l.times_registered }}</td>
|
||||
<td class="muted">{{ l.created_at }}</td>
|
||||
<td class="muted">{{ l.last_seen }}</td>
|
||||
<td class="muted mono hide-sm">{{ l.ip or '—' }}</td>
|
||||
<td class="hide-sm">{% if l.consent %}<span class="pill pill-ok">✓</span>{% else %}<span class="pill pill-no">×</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not leads %}
|
||||
<tr><td colspan="9" class="empty">No hay leads registrados todavía.</td></tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if top_empresas %}
|
||||
<div class="admin-stats">
|
||||
<h2 class="admin-h2">Top empresas</h2>
|
||||
<ul class="empresa-list">
|
||||
{% for e in top_empresas %}
|
||||
<li><span class="empresa-name">{{ e.empresa }}</span><span class="empresa-count">{{ e.count }}</span></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if downloads_por_archivo %}
|
||||
<div class="admin-stats">
|
||||
<h2 class="admin-h2">Descargas por archivo</h2>
|
||||
<ul class="empresa-list">
|
||||
{% for fname, count in downloads_por_archivo.items() %}
|
||||
<li><span class="empresa-name mono">{{ fname }}</span><span class="empresa-count">{{ count }}</span></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function filterTable() {
|
||||
const q = document.getElementById('filter').value.toLowerCase();
|
||||
const rows = document.querySelectorAll('#leads-table tbody tr');
|
||||
rows.forEach(r => {
|
||||
const t = r.textContent.toLowerCase();
|
||||
r.style.display = t.includes(q) ? '' : 'none';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user