Report: filter-pill strip with × to clear individual filters
Three pills under the header: date range, project(s), team(s). Shows comma-joined names when multi-valued (project_name in context is already a comma-joined string from Task 6). × buttons on the project and team pills remove just that filter via a rebuilt querystring; the calendar pill has no × (date range is required). Helper context keys query_string_without_project / _without_team do the rebuild in the view via QueryDict.setlist so multi-value keys are properly stripped (pop() only removes the first occurrence). Pill CSS uses existing design tokens (--bg-inset, --accent, --text-primary, --border-default, --text-tertiary, --bg-card-hover) so dark and light themes work without overrides. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
702bba10ed
commit
ea481bfbf4
@ -30,6 +30,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# === FILTER PILLS === #}
|
||||
<div class="filter-pill-strip d-flex flex-wrap gap-2 mb-4 d-print-none">
|
||||
<span class="filter-pill">
|
||||
<i class="fas fa-calendar me-1"></i>{{ start_date|date:"d M Y" }} – {{ end_date|date:"d M Y" }}
|
||||
</span>
|
||||
<span class="filter-pill">
|
||||
<i class="fas fa-folder me-1"></i>{{ project_name }}
|
||||
{% if selected_project_ids %}
|
||||
<a href="?{{ query_string_without_project|default:query_string }}" class="filter-pill__x" aria-label="Clear project filter">×</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="filter-pill">
|
||||
<i class="fas fa-users me-1"></i>{{ team_name }}
|
||||
{% if selected_team_ids %}
|
||||
<a href="?{{ query_string_without_team|default:query_string }}" class="filter-pill__x" aria-label="Clear team filter">×</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- === PRINT HEADER === -->
|
||||
<div class="d-none d-print-block mb-4">
|
||||
<h2 class="text-center fw-bold mb-1">FoxFitt Construction — Payroll Report</h2>
|
||||
|
||||
@ -2382,6 +2382,17 @@ def generate_report(request):
|
||||
)
|
||||
# Pass the raw query params so the "Download PDF" button can use them
|
||||
context['query_string'] = request.GET.urlencode()
|
||||
# === FILTER PILL CLEAR LINKS ===
|
||||
# For the filter-pill x buttons: rebuild the querystring with one filter removed.
|
||||
# QueryDict.pop() only removes the first occurrence, so for multi-value keys
|
||||
# (e.g. project=1&project=2) we follow up with setlist(key, []) to strip them all.
|
||||
def _qs_without(key):
|
||||
qd = request.GET.copy()
|
||||
qd.pop(key, None)
|
||||
qd.setlist(key, [])
|
||||
return qd.urlencode()
|
||||
context['query_string_without_project'] = _qs_without('project')
|
||||
context['query_string_without_team'] = _qs_without('team')
|
||||
# Pass projects and teams so the "New Report" modal's dropdowns can
|
||||
# populate (same lists the Dashboard modal uses)
|
||||
context['projects'] = Project.objects.all().order_by('name')
|
||||
|
||||
@ -1491,3 +1491,34 @@ body, .card, .modal-content, .form-control, .form-select,
|
||||
.work-log-row:hover td {
|
||||
background: var(--bg-card-hover);
|
||||
}
|
||||
|
||||
/* === Report filter pills === */
|
||||
.filter-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.35rem 0.75rem;
|
||||
font-size: 0.825rem;
|
||||
background: var(--bg-inset);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 999px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.filter-pill i {
|
||||
color: var(--accent);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
.filter-pill__x {
|
||||
margin-left: 0.5rem;
|
||||
padding: 0 0.35rem;
|
||||
color: var(--text-tertiary);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
border-radius: 50%;
|
||||
transition: color 120ms, background-color 120ms;
|
||||
}
|
||||
.filter-pill__x:hover {
|
||||
color: var(--text-primary);
|
||||
background: var(--bg-card-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user