# Implementation Plan — Reflex → Dash Migration ## Project Overview Migrate the Reflex web application to Dash (Plotly) + Dash Mantine Components. The backend (`src/`) is untouched — only the frontend changes. ### What Changes - `pathways_app/` (Reflex) → `dash_app/` (Dash + DMC) - `run_dash.py` entry point replaces `reflex run` - CSS extracted from `01_nhs_classic.html` → `dash_app/assets/nhs.css` - Drug/Directory/Indication filters consolidated into a right-side `dmc.Drawer` ### What Stays (DO NOT MODIFY pipeline/analysis logic) - `data_processing/pathway_pipeline.py`, `transforms.py`, `diagnosis_lookup.py` (matching logic) - `analysis/pathway_analyzer.py`, `statistics.py` - `cli/refresh_pathways.py` - `data_processing/schema.py`, `reference_data.py`, `cache.py`, `data_source.py` - SQLite schema and `pathway_nodes` table - `data/` reference files (CSVs, pathways.db) ### What CAN be edited in `src/` (shared utilities) - `visualization/plotly_generator.py` — add/refactor a function to accept list-of-dicts (what Dash produces) instead of only DataFrames - `data_processing/database.py` — add shared query functions for pathway node loading so both Reflex and Dash use the same queries - `core/config.py` — if path resolution needs adjusting ### Dash App Structure ``` dash_app/ ├── __init__.py ├── app.py # Entry point, layout root, dcc.Store components ├── assets/ │ └── nhs.css # Extracted from 01_nhs_classic.html ├── data/ │ ├── queries.py # SQLite queries (extracted from Reflex AppState) │ └── card_browser.py # DimSearchTerm.csv → directorate tree ├── components/ │ ├── header.py # Top header bar │ ├── sidebar.py # Left navigation │ ├── kpi_row.py # 4 KPI cards │ ├── filter_bar.py # Chart type toggle + date dropdowns │ ├── chart_card.py # Chart area with tabs + dcc.Graph │ ├── drawer.py # dmc.Drawer with card browser │ └── footer.py # Page footer ├── callbacks/ │ ├── __init__.py # register_callbacks(app) │ ├── filters.py # Date/chart-type → app-state store │ ├── chart.py # chart-data → go.Icicle figure │ ├── drawer.py # Drawer open/close + drug selection │ └── kpi.py # chart-data → KPI card values └── utils/ └── formatting.py # Cost/patient display formatters ``` ### State Management (3 dcc.Store components) - **app-state** (session): `chart_type`, `initiated`, `last_seen`, `selected_drugs`, `selected_directorates`, `date_filter_id` - **chart-data** (memory): `nodes[]`, `unique_patients`, `total_drugs`, `total_cost` - **reference-data** (session): `available_drugs`, `directorate_tree` (loaded once) ### Callback Chain ``` Page Load → load_reference_data → reference-data store → load_pathway_data → chart-data store ├→ update_kpis → KPI cards └→ update_chart → dcc.Graph Filter change → update_app_state → app-state store → load_pathway_data → (chain above) Drawer selection → update_drug_selection → app-state store → load_pathway_data → (chain above) ``` ### Directorate Card Browser (dmc.Drawer) - Position: right, ~480px wide - **Top card**: "All Drugs" — flat list from `pathway_nodes` level 3. Pick one drug → see it across all directorates/indications. - **Below**: Cards per PrimaryDirectorate (from DimSearchTerm.csv). Each has `dmc.Accordion` with indication items → drug chips inside. - **Clear Filters** button resets all selections. - Data model: `DimSearchTerm.csv` grouped by PrimaryDirectorate → Search_Term → CleanedDrugName --- ## Phase 0: Project Scaffolding ### 0.1 Create dash_app/ skeleton + update pyproject.toml - [x] Create `dash_app/` directory with `__init__.py`, `app.py`, subdirectories (`assets/`, `data/`, `components/`, `callbacks/`, `utils/`) - [x] Create `run_dash.py` at project root (simple `from dash_app.app import app; app.run(debug=True, port=8050)`) - [x] Update `pyproject.toml`: add `dash>=2.14.0`, `dash-mantine-components>=0.14.0` to dependencies (keep `reflex` temporarily) - [x] Create minimal `app.py` with `dash.Dash(__name__)`, DMC provider wrapper, and "Hello Dash" placeholder layout - **Checkpoint**: `python run_dash.py` starts, shows "Hello Dash" at localhost:8050 ✓ ### 0.2 Extract CSS from 01_nhs_classic.html into dash_app/assets/nhs.css - [x] Copy the `