Updated home with a mini dashboard and created the base.css
This commit is contained in:
parent
cf3869c370
commit
b75efb1553
21
expenses_manager/expenses/static/expenses/css/base.css
Normal file
21
expenses_manager/expenses/static/expenses/css/base.css
Normal file
@ -0,0 +1,21 @@
|
||||
.dashboard-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 500px));
|
||||
gap: 20px
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-chart {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.card-chart canvas {
|
||||
width: 100% !important;
|
||||
height: 220px !important;
|
||||
}
|
||||
@ -1,53 +1,68 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Home</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<link rel="stylesheet" href="{% static 'expenses/css/base.css' %}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Resumen del mes</h1>
|
||||
<h1>Home</h1>
|
||||
|
||||
<!-- KPIs -->
|
||||
<section>
|
||||
<h2>Indicadores</h2>
|
||||
|
||||
<h2>Resumen del mes</h2>
|
||||
<p>Total: {{ kpi_total }}</p>
|
||||
<p>Gastos: {{ kpi_count }}</p>
|
||||
<p>Categorías: {{ kpi_categories }}</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Últimos gastos</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Total gastado:</strong>
|
||||
{{ kpi_total }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Nº de gastos:</strong>
|
||||
{{ kpi_difference }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<strong>Variación (%):</strong>
|
||||
{% if kpi_percentage is not None %}
|
||||
{{ kpi_percentage|floatformat:2 }} %
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</li>
|
||||
{% for expense in last_expenses %}
|
||||
<li>
|
||||
{{ expense.date }} -
|
||||
{{ expense.category.name }} -
|
||||
{{ expense.amount }}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No hay gastos</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- Actions -->
|
||||
<section>
|
||||
<h2>Acciones</h2>
|
||||
<div class="dashboard-grid">
|
||||
<div class="card card-chart">
|
||||
<h2>Últimos meses</h2>
|
||||
<canvas id="miniChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const labels = {{ mini_chart_labels|safe }};
|
||||
const data = {{ mini_chart_data|safe }};
|
||||
|
||||
const ctx = document.getElementById('miniChart');
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets:[{
|
||||
label: 'Gastos',
|
||||
data: data,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{% url 'dashboard' %}">Ir al dashboard</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'expense_create' %}">Añadir gasto</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
@ -32,66 +32,68 @@ def _get_int(value):
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
def sub_months(year, month, n):
|
||||
month -= n
|
||||
while month <= 0:
|
||||
month += 12
|
||||
year -= 1
|
||||
return year, month
|
||||
|
||||
@login_required
|
||||
def home(request):
|
||||
today = date.today()
|
||||
year = today.year
|
||||
month = today.month
|
||||
expenses = Expense.objects.filter(owner=request.user)
|
||||
|
||||
expenses = Expense.objects.filter(
|
||||
owner=request.user,
|
||||
date__year=year,
|
||||
date__month=month,
|
||||
# Last expenses
|
||||
last_expenses = (
|
||||
expenses
|
||||
.select_related('category')
|
||||
.order_by('-date')[:5]
|
||||
)
|
||||
|
||||
# Current KPIs
|
||||
total_amount = expenses.aggregate(
|
||||
# Simple KPIs (current month)
|
||||
today = date.today()
|
||||
month_expenses = expenses.filter(
|
||||
date__year=today.year,
|
||||
date__month=today.month
|
||||
)
|
||||
|
||||
kpi_total = month_expenses.aggregate(
|
||||
total=Sum('amount')
|
||||
)['total'] or 0
|
||||
|
||||
expense_count = expenses.count()
|
||||
kpi_count = month_expenses.count()
|
||||
|
||||
# ------------------
|
||||
# Previous period
|
||||
# ------------------
|
||||
if month == 1:
|
||||
prev_year = year - 1
|
||||
prev_month = 12
|
||||
else:
|
||||
prev_year = year
|
||||
prev_month = month - 1
|
||||
|
||||
previous_expenses = Expense.objects.filter(
|
||||
owner=request.user,
|
||||
date__year=prev_year,
|
||||
date__month=prev_month,
|
||||
)
|
||||
|
||||
previous_total = (
|
||||
previous_expenses.aggregate(total=Sum('amount'))['total'] or 0
|
||||
)
|
||||
|
||||
difference = total_amount - previous_total
|
||||
|
||||
percentage = (difference / previous_total) * 100 if previous_total else None
|
||||
|
||||
# ------------------
|
||||
# Top categories
|
||||
# ------------------
|
||||
top_categories = (
|
||||
expenses
|
||||
.values('category__name')
|
||||
.annotate(total=Sum('amount'))
|
||||
.order_by('-total')[:3]
|
||||
kpi_categories = (
|
||||
month_expenses
|
||||
.values('category')
|
||||
.distinct()
|
||||
.count()
|
||||
)
|
||||
|
||||
six_months = []
|
||||
for i in range(5, -1, -1):
|
||||
y, m = sub_months(today.year, today.month, i)
|
||||
six_months.append((y, m))
|
||||
|
||||
mini_data = []
|
||||
for y, m in six_months:
|
||||
total = expenses.filter(
|
||||
date__year=y,
|
||||
date__month=m
|
||||
).aggregate(total=Sum('amount'))['total'] or 0
|
||||
|
||||
mini_data.append({
|
||||
'label': f'{m}/{y}',
|
||||
'total': float(total),
|
||||
})
|
||||
|
||||
return render(request, 'expenses/home.html', {
|
||||
'kpi_total': total_amount,
|
||||
'kpi_amount': expense_count,
|
||||
'kpi_difference': difference,
|
||||
'kpi_percentage': percentage,
|
||||
'kpi_previous_total': previous_total,
|
||||
'top_categories': top_categories,
|
||||
'last_expenses': last_expenses,
|
||||
'kpi_total': kpi_total,
|
||||
'kpi_count': kpi_count,
|
||||
'kpi_categories': kpi_categories,
|
||||
'mini_chart_labels': [x['label'] for x in mini_data],
|
||||
'mini_chart_data': [x['total'] for x in mini_data],
|
||||
})
|
||||
|
||||
@login_required
|
||||
|
||||
Loading…
Reference in New Issue
Block a user