From ae4b9c136f505b4da3f25b0f02fb4eba33b2d921 Mon Sep 17 00:00:00 2001 From: zwitschi Date: Tue, 21 Oct 2025 07:43:10 +0200 Subject: [PATCH] feat: Introduce reusable template components and enhance styling utilities for consistent UI --- docs/architecture.md | 27 ++++++ static/css/main.css | 44 +++++++-- templates/consumption.html | 57 +++++------- templates/costs.html | 140 +++++++++++------------------ templates/partials/components.html | 37 ++++++++ 5 files changed, 175 insertions(+), 130 deletions(-) create mode 100644 templates/partials/components.html diff --git a/docs/architecture.md b/docs/architecture.md index 6fe411c..c1bf06f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -14,6 +14,7 @@ The backend leverages SQLAlchemy for ORM mapping to a PostgreSQL database. - **Service layer** (`services/`): houses business logic. `services/reporting.py` produces statistical summaries, while `services/simulation.py` provides the Monte Carlo integration point. - **Persistence** (`models/`, `config/database.py`): SQLAlchemy models map to PostgreSQL tables in schema `bricsium_platform`. Relationships connect scenarios to derived domain entities. - **Presentation** (`templates/`, `components/`): server-rendered views extend a shared `base.html` layout with a persistent left sidebar, pull global styles from `static/css/main.css`, and surface data entry (scenario and parameter forms) alongside the Chart.js-powered dashboard. + - **Reusable partials** (`templates/partials/components.html`): macro library that standardises select inputs, feedback/empty states, and table wrappers so pages remain consistent while keeping DOM hooks stable for existing JavaScript modules. - **Middleware** (`middleware/validation.py`): applies JSON validation before requests reach routers. - **Testing** (`tests/unit/`): pytest suite covering route and service behavior. @@ -94,6 +95,32 @@ For extended diagrams and setup instructions reference: ### UI Frontend-Backend Integration Requirements — 2025-10-20 +### Reusable Template Components — 2025-10-21 + +To reduce duplication across form-centric pages, shared Jinja macros live in `templates/partials/components.html`. + +- `select_field(...)`: renders labeled ` - - {% for scenario in scenarios %} - - {% endfor %} - - - -
- Choose a scenario to review its consumption records. -
- + {{ empty_state( "consumption-empty", "Choose a scenario to review its + consumption records." ) }} {% call table_container( + "consumption-table-wrapper", hidden=True, aria_label="Scenario consumption + records" ) %} + + + Amount + Description + + + + {% endcall %}

Add Consumption Record

{% if scenarios %}
- + {{ select_field( "Scenario", "consumption-form-scenario", + name="scenario_id", options=scenarios, required=True, placeholder="Select a + scenario", placeholder_disabled=True ) }}

Add OPEX Entry

{% if scenarios %}
- + {{ select_field( "Scenario", "opex-form-scenario", name="scenario_id", + options=scenarios, required=True, placeholder="Select a scenario", + placeholder_disabled=True ) }}
{% endblock %} {% block scripts %} {{ super() }} diff --git a/templates/partials/components.html b/templates/partials/components.html new file mode 100644 index 0000000..09901fa --- /dev/null +++ b/templates/partials/components.html @@ -0,0 +1,37 @@ +{% macro select_field(label_text, select_id, name=None, options=[], placeholder="Select an option", required=False, include_blank=True, value_attr="id", label_attr="name", placeholder_disabled=False, placeholder_selected=True, selected_value=None) %} + +{% endmacro %} + +{% macro feedback(id, hidden=True, role="status", extra_classes="") %} + +{% endmacro %} + +{% macro empty_state(id, text, hidden=False, extra_classes="") %} + +{% endmacro %} + +{% macro table_container(wrapper_id, hidden=False, aria_label=None, extra_classes="", heading=None, heading_level="h3") %} + +{% endmacro %}