From a6f1d8b30e7978cdd3df8694ff4f56dd368d2d05 Mon Sep 17 00:00:00 2001 From: Andrew Charlwood Date: Thu, 5 Feb 2026 00:37:18 +0000 Subject: [PATCH] feat: replace date pickers with select dropdowns (Task 3.3) - Created initiated_filter_dropdown() and last_seen_filter_dropdown() components - Uses rx.select.root pattern with static options for Reflex compatibility - Updated filter_section() to use new dropdown components - Removed old date_range_picker() function (replaced by new dropdowns) - Data freshness indicator already working in top_bar via load_pathway_data() - Verified: py_compile PASS, imports PASS, reflex compile PASS (11.1s) --- IMPLEMENTATION_PLAN.md | 16 +++- pathways_app/pathways_app.py | 178 +++++++++++++++-------------------- 2 files changed, 89 insertions(+), 105 deletions(-) diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md index 0703480..23862c7 100644 --- a/IMPLEMENTATION_PLAN.md +++ b/IMPLEMENTATION_PLAN.md @@ -129,12 +129,20 @@ cd pathways_app && timeout 60 python -m reflex run 2>&1 | head -30 - Note: Structure validated via code inspection, visual verification pending Task 3.3 UI completion ### 3.3 Update UI Components -- [ ] Replace date pickers with select dropdowns: +- [x] Replace date pickers with select dropdowns: - Initiated: "All years", "Last 2 years", "Last 1 year" - Last Seen: "Last 6 months", "Last 12 months" -- [ ] Add "Data refreshed: X ago" indicator from pathway_refresh_log -- [ ] Update filter section layout -- [ ] Verify UI compiles and renders correctly + - Note: Created `initiated_filter_dropdown()` and `last_seen_filter_dropdown()` components using `rx.select.root` pattern +- [x] Add "Data refreshed: X ago" indicator from pathway_refresh_log + - Note: Already implemented in top_bar() using `last_updated_display` computed property + - Uses pathway_refresh_log.completed_at via `load_pathway_data()` +- [x] Update filter section layout + - Replaced `date_range_picker` calls with new dropdown components + - Simplified filter section layout with cleaner structure +- [x] Verify UI compiles and renders correctly + - python -m py_compile: PASS + - Import check: PASS + - python -m reflex compile: PASS (11.095 seconds) ## Phase 4: Testing & Validation diff --git a/pathways_app/pathways_app.py b/pathways_app/pathways_app.py index 042e36a..144b2cd 100644 --- a/pathways_app/pathways_app.py +++ b/pathways_app/pathways_app.py @@ -1370,93 +1370,85 @@ class AppState(rx.State): # Layout Components # ============================================================================= -def date_range_picker( - label: str, - enabled: rx.Var[bool], - toggle_handler, - from_value: rx.Var[str], - to_value: rx.Var[str], - on_from_change, - on_to_change, -) -> rx.Component: +def initiated_filter_dropdown() -> rx.Component: """ - Date range picker with enable/disable checkbox. + Dropdown for selecting the treatment initiated time period. - Uses debounced inputs (300ms) to prevent excessive filter updates. - - Args: - label: Label for the date range (e.g., "Initiated", "Last Seen") - enabled: Whether the filter is active - toggle_handler: Event handler to toggle enabled state - from_value: Current "from" date value - to_value: Current "to" date value - on_from_change: Handler for from date change - on_to_change: Handler for to date change + Options: All years, Last 2 years, Last 1 year + Values: "all", "2yr", "1yr" """ return rx.vstack( - # Header with checkbox - rx.hstack( - rx.checkbox( - checked=enabled, - on_change=toggle_handler, - size="2", - ), - rx.text( - label, - font_size=Typography.H3_SIZE, - font_weight=Typography.H3_WEIGHT, - color=Colors.SLATE_900, - font_family=Typography.FONT_FAMILY, - ), - align="center", - spacing="2", + # Label + rx.text( + "Treatment Initiated", + font_size=Typography.H3_SIZE, + font_weight=Typography.H3_WEIGHT, + color=Colors.SLATE_900, + font_family=Typography.FONT_FAMILY, ), - # Date inputs (debounced 300ms) - rx.hstack( - rx.vstack( - rx.text( - "From", - **text_caption(), + # Dropdown using rx.select with Root > Trigger > Content > Item pattern + rx.select.root( + rx.select.trigger(placeholder="Select period..."), + rx.select.content( + rx.select.group( + rx.select.item("All years", value="all"), + rx.select.item("Last 2 years", value="2yr"), + rx.select.item("Last 1 year", value="1yr"), ), - rx.debounce_input( - rx.input( - type="date", - value=from_value, - on_change=on_from_change, - disabled=~enabled, - **input_style(), - width="140px", - opacity=rx.cond(enabled, "1", "0.5"), - ), - debounce_timeout=300, - ), - spacing="1", - align="start", ), - rx.vstack( - rx.text( - "To", - **text_caption(), - ), - rx.debounce_input( - rx.input( - type="date", - value=to_value, - on_change=on_to_change, - disabled=~enabled, - **input_style(), - width="140px", - opacity=rx.cond(enabled, "1", "0.5"), - ), - debounce_timeout=300, - ), - spacing="1", - align="start", - ), - spacing="3", - align="end", + value=AppState.selected_initiated, + on_change=AppState.set_initiated_filter, + size="2", ), - spacing="2", + # Description + rx.text( + "When patients first received treatment", + font_size=Typography.CAPTION_SIZE, + color=Colors.SLATE_500, + font_family=Typography.FONT_FAMILY, + ), + spacing="1", + align="start", + ) + + +def last_seen_filter_dropdown() -> rx.Component: + """ + Dropdown for selecting the last seen time period. + + Options: Last 6 months, Last 12 months + Values: "6mo", "12mo" + """ + return rx.vstack( + # Label + rx.text( + "Last Seen", + font_size=Typography.H3_SIZE, + font_weight=Typography.H3_WEIGHT, + color=Colors.SLATE_900, + font_family=Typography.FONT_FAMILY, + ), + # Dropdown using rx.select with Root > Trigger > Content > Item pattern + rx.select.root( + rx.select.trigger(placeholder="Select period..."), + rx.select.content( + rx.select.group( + rx.select.item("Last 6 months", value="6mo"), + rx.select.item("Last 12 months", value="12mo"), + ), + ), + value=AppState.selected_last_seen, + on_change=AppState.set_last_seen_filter, + size="2", + ), + # Description + rx.text( + "Most recent treatment activity", + font_size=Typography.CAPTION_SIZE, + color=Colors.SLATE_500, + font_family=Typography.FONT_FAMILY, + ), + spacing="1", align="start", ) @@ -1754,12 +1746,12 @@ def filter_section() -> rx.Component: Filter section component. Contains: - - Two date range pickers: Initiated (default OFF), Last Seen (default ON) + - Two date filter dropdowns: Treatment Initiated, Last Seen - Three searchable multi-select dropdowns: Drugs, Indications, Directorates Layout: Two rows - - Row 1: Date pickers side by side - - Row 2: Three dropdowns in a grid + - Row 1: Date filter dropdowns side by side + - Row 2: Three searchable dropdowns in a grid """ return rx.box( rx.vstack( @@ -1768,27 +1760,11 @@ def filter_section() -> rx.Component: "Filters", **text_h1(), ), - # Row 1: Date range pickers + # Row 1: Date filter dropdowns rx.hstack( - date_range_picker( - label="Initiated", - enabled=AppState.initiated_filter_enabled, - toggle_handler=AppState.toggle_initiated_filter, - from_value=AppState.initiated_from_date, - to_value=AppState.initiated_to_date, - on_from_change=AppState.set_initiated_from, - on_to_change=AppState.set_initiated_to, - ), + initiated_filter_dropdown(), rx.divider(orientation="vertical", size="3"), - date_range_picker( - label="Last Seen", - enabled=AppState.last_seen_filter_enabled, - toggle_handler=AppState.toggle_last_seen_filter, - from_value=AppState.last_seen_from_date, - to_value=AppState.last_seen_to_date, - on_from_change=AppState.set_last_seen_from, - on_to_change=AppState.set_last_seen_to, - ), + last_seen_filter_dropdown(), spacing="5", align="start", flex_wrap="wrap",