feat: show-closed toggle, closed badge, reopen button, bulk purge

GET /web/cases now honours ?show_closed=1: the toggle link flips the
listing between open-only (default) and open+closed (muted styling,
grey "geschlossen" badge, countdown "wird in N Tagen entfernt" when
auto_delete_days > 0). Each closed row shows a Lucide rotate-ccw
reopen button in the same slot where the close button sits on open
cases; selection checkboxes are suppressed so bulk-close cannot touch
closed cases.

GET /web/cases/:id honours ?show_closed=1 too: without the query a
closed case still 404s (keeps the default listing clean), with it the
detail page renders the reopen form in the header. The case_page
template swaps the icon based on is_closed.

The purge-closed bulk button from the earlier commit finally gets a
UI: it appears below the listing when show_closed=1 is active AND at
least one closed case is visible, with a JS confirm() + the
server-side confirm=yes guard. Two integration tests (listing +
detail) cover the happy path.
This commit is contained in:
2026-04-21 10:58:00 +02:00
parent f358da215d
commit 23e828df45
4 changed files with 356 additions and 33 deletions
+32
View File
@@ -261,6 +261,37 @@
>{% else %}<span class="status-badge open">offen</span>{% endif
%}
</span>
{% if is_closed %}
<form
class="delete-form"
method="post"
action="/web/cases/{{ case_id }}/reopen"
>
<button
type="submit"
class="delete-btn"
title="Fall wiedereröffnen"
aria-label="Fall wiedereröffnen"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="18"
height="18"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"
></path>
<path d="M3 3v5h5"></path>
</svg>
</button>
</form>
{% else %}
<form
class="delete-form"
method="post"
@@ -293,6 +324,7 @@
</svg>
</button>
</form>
{% endif %}
</h1>
{% match recorded_at_iso %} {% when Some with (iso) %}
<p class="case-time">