Report: hero KPI band (4 cards) replacing All-Time/YTD row

Chapter 0 of the executive redesign: four large cards at the top
showing Paid This Period, Outstanding Now (live, stamped with the
generation time), FoxFitt Avg/Day, and FoxFitt Avg/Month.

Drops the old four-small-cards All-Time/YTD row (YTD specifically
documented as redundant per design doc section 3). All-Time detail
moves into Chapter I in the next task.

New .stat-card--hero variant uses Poppins 1.85rem for the number,
uppercase tracked labels, subtle tertiary sub-lines. tabular-nums
keeps the R-amounts pixel-aligned across cards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Konrad du Plessis 2026-04-22 23:37:39 +02:00
parent 8ea8955b30
commit 9632214f99
2 changed files with 55 additions and 73 deletions

View File

@ -58,89 +58,34 @@
</p>
</div>
<!-- ===================================================================
ALL TIME & THIS YEAR — big-picture context, now shown FIRST so
readers see the lifetime/YTD picture before the selected period.
=================================================================== -->
<div class="row g-3 mb-4">
<!-- All Time by Project -->
{# === HERO KPI BAND === #}
<div class="row g-3 mb-4 hero-kpi-row">
<div class="col-lg-3 col-md-6">
<div class="card h-100">
<div class="card-header py-2">
<h6 class="m-0 fw-bold" style="font-size: 0.8rem;"><i class="fas fa-globe me-1" style="color: var(--accent);"></i>All Time &mdash; Projects</h6>
</div>
<div class="card-body p-0">
{% if alltime_projects %}
<table class="table table-sm mb-0" style="font-size: 0.8rem;">
<thead><tr><th>Project</th><th class="text-end">Cost</th></tr></thead>
<tbody>
{% for item in alltime_projects %}
<tr><td class="text-truncate" style="max-width: 120px;">{{ item.project }}</td><td class="text-end fw-semibold text-nowrap">R {{ item.total|money }}</td></tr>
{% endfor %}
</tbody>
</table>
{% else %}<p class="text-muted text-center py-2 mb-0" style="font-size: 0.8rem;">No data</p>{% endif %}
</div>
<div class="stat-card stat-card--danger stat-card--hero h-100">
<div class="stat-label">Paid This Period</div>
<div class="stat-value">R {{ total_paid_out|money }}</div>
<div class="stat-subline">{{ start_date|date:"d M Y" }} &ndash; {{ end_date|date:"d M Y" }}</div>
</div>
</div>
<!-- All Time by Team -->
<div class="col-lg-3 col-md-6">
<div class="card h-100">
<div class="card-header py-2">
<h6 class="m-0 fw-bold" style="font-size: 0.8rem;"><i class="fas fa-globe me-1" style="color: var(--accent);"></i>All Time &mdash; Teams</h6>
</div>
<div class="card-body p-0">
{% if alltime_teams %}
<table class="table table-sm mb-0" style="font-size: 0.8rem;">
<thead><tr><th>Team</th><th class="text-end">Cost</th></tr></thead>
<tbody>
{% for item in alltime_teams %}
<tr><td class="text-truncate" style="max-width: 120px;">{{ item.team }}</td><td class="text-end fw-semibold text-nowrap">R {{ item.total|money }}</td></tr>
{% endfor %}
</tbody>
</table>
{% else %}<p class="text-muted text-center py-2 mb-0" style="font-size: 0.8rem;">No data</p>{% endif %}
</div>
<div class="stat-card stat-card--warning stat-card--hero h-100">
<div class="stat-label">Outstanding Now</div>
<div class="stat-value">R {{ current_outstanding.total|money }}</div>
<div class="stat-subline">as of {{ current_as_of|date:"H:i" }}</div>
</div>
</div>
<!-- This Year by Project -->
<div class="col-lg-3 col-md-6">
<div class="card h-100">
<div class="card-header py-2">
<h6 class="m-0 fw-bold" style="font-size: 0.8rem;"><i class="fas fa-calendar me-1" style="color: var(--accent);"></i>{{ current_year }} &mdash; Projects</h6>
</div>
<div class="card-body p-0">
{% if year_projects %}
<table class="table table-sm mb-0" style="font-size: 0.8rem;">
<thead><tr><th>Project</th><th class="text-end">Cost</th></tr></thead>
<tbody>
{% for item in year_projects %}
<tr><td class="text-truncate" style="max-width: 120px;">{{ item.project }}</td><td class="text-end fw-semibold text-nowrap">R {{ item.total|money }}</td></tr>
{% endfor %}
</tbody>
</table>
{% else %}<p class="text-muted text-center py-2 mb-0" style="font-size: 0.8rem;">No data</p>{% endif %}
</div>
<div class="stat-card stat-card--info stat-card--hero h-100">
<div class="stat-label">FoxFitt Avg / Day</div>
<div class="stat-value">R {{ company_avg_daily|money }}</div>
<div class="stat-subline">lifetime avg &middot; {{ company_working_days }} working days</div>
</div>
</div>
<!-- This Year by Team -->
<div class="col-lg-3 col-md-6">
<div class="card h-100">
<div class="card-header py-2">
<h6 class="m-0 fw-bold" style="font-size: 0.8rem;"><i class="fas fa-calendar me-1" style="color: var(--accent);"></i>{{ current_year }} &mdash; Teams</h6>
</div>
<div class="card-body p-0">
{% if year_teams %}
<table class="table table-sm mb-0" style="font-size: 0.8rem;">
<thead><tr><th>Team</th><th class="text-end">Cost</th></tr></thead>
<tbody>
{% for item in year_teams %}
<tr><td class="text-truncate" style="max-width: 120px;">{{ item.team }}</td><td class="text-end fw-semibold text-nowrap">R {{ item.total|money }}</td></tr>
{% endfor %}
</tbody>
</table>
{% else %}<p class="text-muted text-center py-2 mb-0" style="font-size: 0.8rem;">No data</p>{% endif %}
</div>
<div class="stat-card stat-card--info stat-card--hero h-100">
<div class="stat-label">FoxFitt Avg / Month</div>
<div class="stat-value">R {{ company_avg_monthly|money }}</div>
<div class="stat-subline">lifetime avg &middot; ~30.44 days/month</div>
</div>
</div>
</div>

View File

@ -1649,3 +1649,40 @@ body, .card, .modal-content, .form-control, .form-select,
font-style: italic;
background: transparent !important;
}
/* === Hero KPI card variant (executive report) === */
/*
A larger, more typographic version of the existing .stat-card,
used for the top-of-report KPI band. Keeps the same --accent-based
colour stripes (stat-card--danger, --warning, --info) but scales
the number, flattens the label to uppercase tracked caps, and adds
a subtle tertiary sub-line for context like "as of 15:42" or the
date range.
*/
.stat-card--hero {
padding: 1.25rem 1.4rem;
min-height: 130px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.stat-card--hero .stat-label {
font-size: 0.7rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-tertiary);
margin-bottom: 0.4rem;
}
.stat-card--hero .stat-value {
font-family: 'Poppins', sans-serif;
font-weight: 600;
font-size: 1.85rem;
line-height: 1;
color: var(--text-primary);
font-variant-numeric: tabular-nums;
}
.stat-card--hero .stat-subline {
font-size: 0.78rem;
color: var(--text-tertiary);
margin-top: 0.6rem;
}