Dashboard improvements

This commit is contained in:
JKuijperM 2026-02-09 17:11:13 +01:00
parent d37d0f95f1
commit 3154cfac22
3 changed files with 209 additions and 188 deletions

View File

@ -65,9 +65,22 @@ a.danger {
padding: 24px;
}
.dashboard-context {
margin-bottom: 1rem;
}
.dashboard-context h2 {
margin: 0;
}
.muted {
color: #6b7280;
font-size: 0.85rem;
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 500px));
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 20px
}
@ -79,7 +92,7 @@ a.danger {
}
.card-chart {
max-width: 500px;
max-width: 300px;
}
.card-chart canvas {
@ -87,6 +100,11 @@ a.danger {
height: 220px !important;
}
.chart-box {
height: 300px;
margin-bottom: 2rem;
}
.tag{
display: inline-block;
padding: 2px 6px;
@ -104,7 +122,7 @@ a.danger {
.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-file, minmax(180px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
margin: 1.5rem 0;
}
@ -128,6 +146,18 @@ a.danger {
margin-top: 0.25rem;
}
/* .comparison strong {
color:#b91c1c;
} */
.comparison strong.positive {
color: #166534;
}
.comparison strong.negative {
color:#b91c1c;
}
table {
width: 100%;
border-collapse: collapse;
@ -205,4 +235,52 @@ tbody tr:hover {
.message.warning {
background: #fef3c7;
color: #92400e;
}
.dashboard-filters {
margin: 1rem 0 1.5rem;
padding: 1rem;
background: #f9fafb;
border-radius: 8px;
}
.dashboard-filters form {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
align-items: center;
}
.dashboard-filters select,
.dashboard-filters button {
padding: 0.4rem 0.6rem;
}
.dashboard-filters .checkbox {
display: flex;
gap: 0.3rem;
align-items: center;
}
.dashboard-presets {
display: flex;
gap: 0.5rem;
}
.preset {
padding: 0.35rem 0.6rem;
border-radius: 6px;
background: #e5e7eb;
text-decoration: none;
color: #111827;
font-size: 0.85rem;
}
.preset:hover {
background: #d1d5db;
}
.preset.active {
background: #2563eb;
color: white;
}

View File

@ -3,45 +3,70 @@
{% block title %}Dashboard{% endblock %}
{% block content %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<section class="dashboard-context">
<h2>
{% if selected_account_obj %}
{{ selected_account_obj.name }}
{% else %}
Todas las cuentas
{% endif %}
</h2>
<h1>
Dashboard
{% if selected_account_obj %}
— {{ selected_account_obj.name }}
{% endif %}
</h1>
<p class="muted">
{% if selected_month %}
{{ selected_month }}/{{ selected_year}}
{% else %}
Año {{ selected_year }}
{% endif %}
</p>
</section>
<!-- ========================= -->
<!-- Filters -->
<!-- ========================= -->
<div>
<a href="{% url 'dashboard' %}?period=this_month">Este mes</a> |
<a href="{% url 'dashboard' %}?period=last_month">Mes anterior</a> |
<a href="{% url 'dashboard' %}?period=this_year">Este año</a>
</div>
<br>
<section class="dashboard-filters">
<div class="dashboard-presets">
<a href="{% url 'dashboard' %}" data-period="this_month" class="preset {% if period == 'this_month' %}active{% endif %}">
Este mes
</a>
<a href="{% url 'dashboard' %}" data-period="last_month" class="preset {% if period == 'last_month' %}active{% endif %}">
Mes anterior
</a>
<a href="{% url 'dashboard' %}" data-period="this_year" class="preset {% if period == 'this_year' %}active{% endif %}">
Este año
</a>
</div>
<br>
<form method="get">
<select name="account" id="account">
<option value="">Todas las cuentas</option>
{% for acc in accounts %}
<option value="{{ acc.id }}"
{% if selected_account == acc.id %}selected{% endif %}
>
{{ acc.name }}
</option>
{% endfor %}
</select>
<form method="get" class="filters">
<label>
Año:
<select name="year">
{% for y in year_list %}
<option value="{{ y }}"
{% if y == selected_year %}selected{% endif %}
>
{{y}}
{{ y }}
</option>
{% endfor %}
</select>
</label>
<label>
Mes:
<select name="month">
<option value="">Todos</option>
<option value="">Todo el año</option>
{% for m in months %}
<option value="{{ m }}"
{% if m == selected_month %}selected{% endif %}
@ -50,43 +75,39 @@
</option>
{% endfor %}
</select>
</label>
<label>
<input type="checkbox" name="compare" value="1"
{% if compare_enabled %}checked{% endif %}>
Comparar con periodo anterior
</label>
<label class="checkbox">
<input type="checkbox" name="compare" value="1"
{% if compare_enabled %}checked{% endif %}>
Comparar
</label>
<label for="account">Cuenta:</label>
<select name="account" id="account">
<option value="">Todas</option>
{% for acc in accounts %}
<option value="{{ acc.id }}"
{% if selected_account == acc.id %}selected{% endif %}
>
{{ acc.name }}
</option>
{% endfor %}
</select>
<button type="submit">Aplicar</button>
</form>
<button type="submit">Aplicar</button>
</form>
</section>
<p>
Mostrando:
<strong>{{ selected_year }}</strong>
{% if selected_month %}/<strong>{{ selected_month }}</strong>{% endif %}
</p>
<p>Comparado con el periodo inmediatamente anterior</p>
<script>
document.querySelectorAll('.dashboard-presets a').forEach(link => {
link.addEventListener('click', e => {
e.preventDefault();
<hr>
const period = link.dataset.period;
const isActive = link.classList.contains('active');
if (isActive) {
window.location.href = link.href;
} else {
window.location.href = `${link.href}?period=${period}`
}
});
});
</script>
<!-- ========================= -->
<!-- KPIs -->
<!-- ========================= -->
<section class="kpi-grid">
<div class="kpi-card">
@ -111,145 +132,15 @@
</section>
{% if compare_enabled %}
<section class="kpi compare">
<h3>Comparación con periodo anterior</h3>
{% if kpi_previous_total == 0 %}
<p><em>No hay datos en el periodo anterior</em></p>
{% else %}
<p>
Total anterior: <strong>{{ kpi_previous_total|floatformat:2 }}</strong>
</p>
{% endif %}
<div>
Diferencia:
{% if kpi_trend == "up" %}
<span style="color:red;">▲ {{ kpi_difference|floatformat:2 }}€</span>
{% elif kpi_trend == "down" %}
<span style="color:green;">▼ {{ kpi_difference_abs|floatformat:2 }}€</span>
{% else %}
<span>0€</span>
{% endif %}
</div>
<p>
Variación:
{% if kpi_percentage is not None %}
{{ kpi_percentage|floatformat:2 }}%
{% else %}
Variación: N/D
{% endif %}
</p>
</section>
{% endif %}
<!-- ========================= -->
<!-- Expenses by category -->
<!-- Charts -->
<!-- ========================= -->
<h2>Gastos por categoría</h2>
{% if not by_category %}
<p>No hay gastos para este periodo.</p>
{% else %}
<table>
<thead>
<tr>
<th>Categoría</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for row in by_category %}
<tr>
<td>{{ row.category__name }}</td>
<td>{{ row.total }}</td>
</tr>
{% empty %}
<tr>
<td colspan="2">Sin datos</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if compare_enabled %}
<h3>Comparativa por categoría</h3>
<section class="chart-box">
<canvas id="mainChart"></canvas>
</section>
<table>
<thead>
<tr>
<th>Categoría</th>
<th>Actual</th>
<th>Anterior</th>
<th>Diferencia</th>
</tr>
</thead>
<tbody>
{% for row in category_comparison %}
<tr>
<td>{{ row.category }}</td>
<td>{{ row.current|floatformat:2 }}€</td>
<td>{{ row.previous }}</td>
<td>
{% if row.difference > 0 %}
<span style="color:red;">▲ {{ row.difference|floatformat:2 }}€</span>
{% elif row.difference < 0 %}
<span style="color:green;">▼ {{ row.difference_abs|floatformat:2 }}€</span>
{% else %}
=
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<hr>
<!-- ========================= -->
<!-- Expenses by month -->
<!-- ========================= -->
<h2>Gastos por mes</h2>
<ul>
{% for row in by_month %}
<li>Mes {{ row.month }} → {{ row.total }}</li>
{% endfor %}
</ul>
<!-- ========================= -->
<!-- Chart -->
<!-- ========================= -->
<h2>Distribución mensual (año completo)</h2>
<canvas id="expensesChart"></canvas>
<script>
const labels = {{ chart_labels|safe }};
const data = {{ chart_data|safe }};
const ctx = document.getElementById('expensesChart');
new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets:[{
label: 'Gastos',
data: data,
}]
}
});
</script>
<hr>
<h2>Evolución anual por cuenta ({{ selected_year }})</h2>
<h3>Evolución anual por cuenta ({{ selected_year }})</h3>
<div class="dashboard-grid">
{% for acc in accounts_charts %}
@ -262,6 +153,23 @@
{% endfor %}
</div>
<script>
const labels = {{ chart_labels|safe }};
const data = {{ chart_data|safe }};
const ctx = document.getElementById('mainChart');
new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets:[{
label: 'Gastos',
data: data,
}]
}
});
</script>
<script>
const monthLabels = {{ chart_labels|safe }};
@ -289,4 +197,38 @@
</script>
{% if compare_enabled %}
<section class="comparison">
<h3>Comparativa</h3>
<p>
Diferencia:
<strong class="{% if kpi_trend == 'up' %}positive{% endif %}">
{% if kpi_trend == "up" %}+{% endif %}
{{ kpi_difference_abs|floatformat:2 }} €
</strong>
{% if kpi_percentage %}
({{ kpi_percentage|floatformat:1 }}%)
{% endif %}
</p>
</section>
{% endif %}
<table>
<thead>
<tr>
<th>Categoría</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for row in by_category %}
<tr>
<td>{{ row.category__name }}</td>
<td>{{ row.total|floatformat:2 }} €</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -530,6 +530,7 @@ def dashboard(request):
'selected_account_obj': selected_account_obj,
'kpi_balance': kpi_balance,
'accounts_charts': accounts_charts,
'period':period,
})