feat: add two-view architecture with sidebar navigation (Task 10.2)

- Add active_view and selected_comparison_directorate to app-state
- Sidebar: rename to Patient Pathways + add Trust Comparison nav item
- View container pattern: two view divs toggled by active_view
- Navigation callback: sidebar clicks switch views + update active state
- Trust Comparison placeholder landing page with tc-landing structure
This commit is contained in:
Andrew Charlwood
2026-02-06 21:38:12 +00:00
parent 94b1ac640a
commit 7d51efc25e
6 changed files with 116 additions and 19 deletions
+2
View File
@@ -7,8 +7,10 @@ def register_callbacks(app):
from dash_app.callbacks.chart import register_chart_callbacks
from dash_app.callbacks.kpi import register_kpi_callbacks
from dash_app.callbacks.modals import register_modal_callbacks
from dash_app.callbacks.navigation import register_navigation_callbacks
register_filter_callbacks(app)
register_chart_callbacks(app)
register_kpi_callbacks(app)
register_modal_callbacks(app)
register_navigation_callbacks(app)
+17 -5
View File
@@ -73,13 +73,15 @@ def register_filter_callbacks(app):
Input("filter-last-seen", "value"),
Input("all-drugs-chips", "value"),
Input("trust-chips", "value"),
Input("nav-patient-pathways", "n_clicks"),
Input("nav-trust-comparison", "n_clicks"),
State("app-state", "data"),
)
def update_app_state(
_dir_clicks, _ind_clicks, initiated, last_seen, selected_drugs,
selected_trusts, current_state
selected_trusts, _nav_pp_clicks, _nav_tc_clicks, current_state
):
"""Update app-state when chart type toggle, date filters, drug chips, or trust chips change."""
"""Update app-state when chart type toggle, date filters, drug/trust chips, or sidebar nav change."""
if not current_state:
current_state = {
"chart_type": "directory",
@@ -89,6 +91,8 @@ def register_filter_callbacks(app):
"selected_drugs": [],
"selected_directorates": [],
"selected_trusts": [],
"active_view": "patient-pathways",
"selected_comparison_directorate": None,
}
triggered_id = ctx.triggered_id
@@ -100,6 +104,13 @@ def register_filter_callbacks(app):
elif triggered_id == "chart-type-indication":
chart_type = "indication"
# Determine active view from sidebar nav
active_view = current_state.get("active_view", "patient-pathways")
if triggered_id == "nav-patient-pathways":
active_view = "patient-pathways"
elif triggered_id == "nav-trust-comparison":
active_view = "trust-comparison"
# Compute date_filter_id from dropdown values
date_filter_id = f"{initiated}_{last_seen}"
@@ -112,12 +123,13 @@ def register_filter_callbacks(app):
"date_filter_id": date_filter_id,
"selected_drugs": selected_drugs or [],
"selected_trusts": selected_trusts or [],
"active_view": active_view,
}
# Toggle pill CSS classes
base = "toggle-pill"
active = f"{base} toggle-pill--active"
dir_class = active if chart_type == "directory" else base
ind_class = active if chart_type == "indication" else base
active_cls = f"{base} toggle-pill--active"
dir_class = active_cls if chart_type == "directory" else base
ind_class = active_cls if chart_type == "indication" else base
return updated_state, dir_class, ind_class
+29
View File
@@ -0,0 +1,29 @@
"""Callbacks for view switching between Patient Pathways and Trust Comparison."""
from dash import Input, Output
def register_navigation_callbacks(app):
"""Register view switching callbacks."""
@app.callback(
Output("patient-pathways-view", "style"),
Output("trust-comparison-view", "style"),
Output("nav-patient-pathways", "className"),
Output("nav-trust-comparison", "className"),
Input("app-state", "data"),
)
def switch_view(app_state):
"""Show/hide views and update sidebar active state based on active_view."""
if not app_state:
return {}, {"display": "none"}, "sidebar__item sidebar__item--active", "sidebar__item"
view = app_state.get("active_view", "patient-pathways")
show = {}
hide = {"display": "none"}
active_cls = "sidebar__item sidebar__item--active"
inactive_cls = "sidebar__item"
if view == "patient-pathways":
return show, hide, active_cls, inactive_cls
else:
return hide, show, inactive_cls, active_cls