From 39b52a3fa4513e1da53af94ccc65d84ad91889d0 Mon Sep 17 00:00:00 2001 From: Darek Date: Mon, 13 Apr 2026 09:53:21 -0500 Subject: [PATCH] Replace browser confirm() dialogs with custom modal; add live label preview on battery add form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - base.html: add CSS/HTML/JS for styled in-app confirmation modal (dark-mode compatible via CSS vars) - device_list, battery_detail: convert onsubmit confirm() to declarative data-confirm attributes - dashboard: convert bulk Delete/Install buttons to use modal helpers (submitWithAction pattern) - app.py: pass brand_counts dict to battery_add template - battery_add.html: show live "Will create: Brand 001 → Brand 003" preview as brand/quantity change - tests: add two tests covering brand_counts server-side rendering --- app.py | 8 ++++- templates/base.html | 59 +++++++++++++++++++++++++++++++++++ templates/battery_add.html | 21 +++++++++++++ templates/battery_detail.html | 4 +-- templates/dashboard.html | 33 ++++++++++++++------ templates/device_list.html | 6 ++-- tests/test_acceptance.py | 18 +++++++++++ 7 files changed, 135 insertions(+), 14 deletions(-) diff --git a/app.py b/app.py index 2d17b5c..5ec4089 100644 --- a/app.py +++ b/app.py @@ -95,8 +95,14 @@ def create_app(config_object="config"): .filter(Battery.storage_location.isnot(None)) .distinct().order_by(Battery.storage_location).all() ] + brand_counts = { + r[0]: r[1] + for r in db.query(Battery.brand, func.count(Battery.id)) + .group_by(Battery.brand).all() + } return render_template("battery_add.html", form_count=1, brands=brands, - storage_locations=storage_locations) + storage_locations=storage_locations, + brand_counts=brand_counts) # ------------------------------------------------------------------ # # Battery — detail diff --git a/templates/base.html b/templates/base.html index a373208..97a5ea9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -56,6 +56,13 @@ --count-retired: #64748b; } + /* Confirmation modal */ + #confirm-modal { display:none; position:fixed; inset:0; z-index:1000; background:rgba(0,0,0,.45); align-items:center; justify-content:center; } + #confirm-modal.open { display:flex; } + #confirm-modal-box { background:var(--bg-card); border-radius:8px; padding:1.5rem; max-width:400px; width:calc(100% - 2rem); box-shadow:0 8px 24px rgba(0,0,0,.25); } + #confirm-modal-msg { margin-bottom:1.25rem; color:var(--text-body); font-size:0.95rem; line-height:1.5; } + #confirm-modal-actions { display:flex; gap:0.75rem; justify-content:flex-end; } + /* ─── Dark mode variables ────────────────────────────────────────── */ @media (prefers-color-scheme: dark) { :root { @@ -326,10 +333,62 @@ {% block content %}{% endblock %} + + diff --git a/templates/battery_add.html b/templates/battery_add.html index be3a4b9..c187b43 100644 --- a/templates/battery_add.html +++ b/templates/battery_add.html @@ -27,6 +27,7 @@ Labels are auto-generated (e.g. Eneloop 001, Eneloop 002) +
@@ -96,6 +97,8 @@