From 3568e03fc2e69e3ddcd038f21d1a6ba39e4a717d Mon Sep 17 00:00:00 2001 From: Andrew Charlwood Date: Fri, 6 Feb 2026 13:24:33 +0000 Subject: [PATCH] feat: add footer component and complete Phase 2 static layout (Task 2.3) --- IMPLEMENTATION_PLAN.md | 4 ++-- dash_app/app.py | 2 ++ dash_app/components/footer.py | 10 ++++++++ progress.txt | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 dash_app/components/footer.py diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md index b973310..2ed1741 100644 --- a/IMPLEMENTATION_PLAN.md +++ b/IMPLEMENTATION_PLAN.md @@ -149,9 +149,9 @@ Drawer selection → update_drug_selection → app-state store → load_pathway_ - **Checkpoint**: All three components render with correct layout and styling ### 2.3 Footer + full page assembly -- [ ] Create `dash_app/components/footer.py` — `make_footer()` function +- [x] Create `dash_app/components/footer.py` — `make_footer()` function - CSS class `.page-footer`, same text as 01_nhs_classic.html -- [ ] Update `dash_app/app.py` to assemble full page layout: +- [x] Update `dash_app/app.py` to assemble full page layout: - `dmc.MantineProvider(children=[header, sidebar, main_content])` - Main content: KPI row → filter bar → chart card → footer - Add 3 `dcc.Store` components: `id="app-state"`, `id="chart-data"`, `id="reference-data"` diff --git a/dash_app/app.py b/dash_app/app.py index 34d8d4d..9eaaca3 100644 --- a/dash_app/app.py +++ b/dash_app/app.py @@ -7,6 +7,7 @@ from dash_app.components.sidebar import make_sidebar from dash_app.components.kpi_row import make_kpi_row from dash_app.components.filter_bar import make_filter_bar from dash_app.components.chart_card import make_chart_card +from dash_app.components.footer import make_footer app = Dash( __name__, @@ -36,6 +37,7 @@ app.layout = dmc.MantineProvider( make_kpi_row(), make_filter_bar(), make_chart_card(), + make_footer(), ], ), ], diff --git a/dash_app/components/footer.py b/dash_app/components/footer.py new file mode 100644 index 0000000..4197c26 --- /dev/null +++ b/dash_app/components/footer.py @@ -0,0 +1,10 @@ +"""Page footer component.""" +from dash import html + + +def make_footer(): + """Build the page footer matching 01_nhs_classic.html.""" + return html.Footer( + className="page-footer", + children="NHS Norfolk and Waveney ICB \u2014 High Cost Drugs Analysis", + ) diff --git a/progress.txt b/progress.txt index 84e2fe5..51b2ac0 100644 --- a/progress.txt +++ b/progress.txt @@ -302,3 +302,48 @@ Migrating the HCD Analysis frontend from Reflex to Dash (Plotly) + Dash Mantine - Phase 3.1 will need: reference data loading callback (on page load), filter state management callback (toggle pills + dropdowns → app-state), and `register_callbacks(app)` wiring ### Blocked items: - None + +## Iteration 6 — 2026-02-06 +### Task: Phase 2 — Task 2.3 (Footer + full page assembly) +### Why this task: +- Tasks 2.1 and 2.2 complete. Task 2.3 is the final piece of Phase 2. +- Previous iteration (5) explicitly recommended this as the next task. +- Completing this marks Phase 2 done, enabling Phase 3 (Core Callbacks). +### Status: COMPLETE +### What was done: +- Created `dash_app/components/footer.py` with `make_footer()`: + - Returns `html.Footer(className="page-footer")` matching 01_nhs_classic.html line 520 + - Text: "NHS Norfolk and Waveney ICB — High Cost Drugs Analysis" +- Updated `dash_app/app.py`: + - Added `make_footer` import + - Added `make_footer()` as 4th child in main content area (after chart card) +- Full page layout now complete: MantineProvider → [3 stores, Header, Sidebar, Main(KPIs, Filter bar, Chart card, Footer)] +- Note: dcc.Store components and page assembly were already done in earlier iterations. Task 2.3 effectively just needed the footer component. +### Validation results: +- Tier 1 (Code): `from dash_app.components.footer import make_footer` — OK, returns Footer with className="page-footer" +- Tier 1 (App starts): `from dash_app.app import app` — OK, no errors +- Tier 2 (Layout): Verified programmatically: + - MantineProvider: 6 children (3 stores + Header(top-header) + Nav(sidebar) + Main(main)) + - Main: 4 children (Section(kpi-row), Section(filter-bar), Section(chart-card), Footer(page-footer)) + - All component IDs present and correct +### Files changed: +- `dash_app/components/footer.py` — NEW: footer component +- `dash_app/app.py` — Updated: import + added footer to main area +- `IMPLEMENTATION_PLAN.md` — Task 2.3 marked [x] +### Committed: [pending] +### Patterns discovered: +- Phase 2 was incrementally built across iterations 4-6. The layout assembly (app.py) evolved naturally — each iteration added its components. No "big bang" assembly step was needed. +### Next iteration should: +- Start Phase 3: Task 3.1 — Reference data loading + filter state management +- Create `dash_app/callbacks/filters.py` with two callbacks: + 1. `load_reference_data`: fires on page load, calls `queries.load_initial_data()`, populates `reference-data` store + header record count + header last updated + 2. `update_app_state`: fires when chart-type toggle buttons or date dropdowns change, computes `date_filter_id` from initiated+last_seen combo, updates `app-state` store, manages toggle pill active classes +- Create `dash_app/callbacks/__init__.py` with `register_callbacks(app)` function +- Wire `register_callbacks(app)` call in `app.py` after layout definition +- Key IDs to use as inputs: `chart-type-directory`, `chart-type-indication` (n_clicks), `filter-initiated` (value), `filter-last-seen` (value) +- Key IDs to use as outputs: `app-state` (data), `reference-data` (data), `header-record-count` (children), `header-last-updated` (children) +- Date filter ID mapping: initiated "all"/"2yr"/"1yr" + last_seen "6mo"/"12mo" → e.g. "all_6mo", "1yr_12mo" +- For toggle pills, use Output for className to toggle `toggle-pill--active` class +- Read pathways_app/pathways_app.py lines 407-488 to understand the reference data structure +### Blocked items: +- None