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)
This commit is contained in:
Andrew Charlwood
2026-02-05 00:37:18 +00:00
parent 8f2425a9ae
commit a6f1d8b30e
2 changed files with 89 additions and 105 deletions
+12 -4
View File
@@ -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 - Note: Structure validated via code inspection, visual verification pending Task 3.3 UI completion
### 3.3 Update UI Components ### 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" - Initiated: "All years", "Last 2 years", "Last 1 year"
- Last Seen: "Last 6 months", "Last 12 months" - Last Seen: "Last 6 months", "Last 12 months"
- [ ] Add "Data refreshed: X ago" indicator from pathway_refresh_log - Note: Created `initiated_filter_dropdown()` and `last_seen_filter_dropdown()` components using `rx.select.root` pattern
- [ ] Update filter section layout - [x] Add "Data refreshed: X ago" indicator from pathway_refresh_log
- [ ] Verify UI compiles and renders correctly - 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 ## Phase 4: Testing & Validation
+65 -89
View File
@@ -1370,94 +1370,86 @@ class AppState(rx.State):
# Layout Components # Layout Components
# ============================================================================= # =============================================================================
def date_range_picker( def initiated_filter_dropdown() -> rx.Component:
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:
""" """
Date range picker with enable/disable checkbox. Dropdown for selecting the treatment initiated time period.
Uses debounced inputs (300ms) to prevent excessive filter updates. Options: All years, Last 2 years, Last 1 year
Values: "all", "2yr", "1yr"
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
""" """
return rx.vstack( return rx.vstack(
# Header with checkbox # Label
rx.hstack(
rx.checkbox(
checked=enabled,
on_change=toggle_handler,
size="2",
),
rx.text( rx.text(
label, "Treatment Initiated",
font_size=Typography.H3_SIZE, font_size=Typography.H3_SIZE,
font_weight=Typography.H3_WEIGHT, font_weight=Typography.H3_WEIGHT,
color=Colors.SLATE_900, color=Colors.SLATE_900,
font_family=Typography.FONT_FAMILY, font_family=Typography.FONT_FAMILY,
), ),
align="center", # Dropdown using rx.select with Root > Trigger > Content > Item pattern
spacing="2", 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"),
), ),
# Date inputs (debounced 300ms) ),
rx.hstack( value=AppState.selected_initiated,
rx.vstack( on_change=AppState.set_initiated_filter,
size="2",
),
# Description
rx.text( rx.text(
"From", "When patients first received treatment",
**text_caption(), font_size=Typography.CAPTION_SIZE,
), color=Colors.SLATE_500,
rx.debounce_input( font_family=Typography.FONT_FAMILY,
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", spacing="1",
align="start", align="start",
), )
rx.vstack(
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( rx.text(
"To", "Last Seen",
**text_caption(), font_size=Typography.H3_SIZE,
font_weight=Typography.H3_WEIGHT,
color=Colors.SLATE_900,
font_family=Typography.FONT_FAMILY,
), ),
rx.debounce_input( # Dropdown using rx.select with Root > Trigger > Content > Item pattern
rx.input( rx.select.root(
type="date", rx.select.trigger(placeholder="Select period..."),
value=to_value, rx.select.content(
on_change=on_to_change, rx.select.group(
disabled=~enabled, rx.select.item("Last 6 months", value="6mo"),
**input_style(), rx.select.item("Last 12 months", value="12mo"),
width="140px",
opacity=rx.cond(enabled, "1", "0.5"),
), ),
debounce_timeout=300, ),
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", spacing="1",
align="start", align="start",
),
spacing="3",
align="end",
),
spacing="2",
align="start",
) )
@@ -1754,12 +1746,12 @@ def filter_section() -> rx.Component:
Filter section component. Filter section component.
Contains: 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 - Three searchable multi-select dropdowns: Drugs, Indications, Directorates
Layout: Two rows Layout: Two rows
- Row 1: Date pickers side by side - Row 1: Date filter dropdowns side by side
- Row 2: Three dropdowns in a grid - Row 2: Three searchable dropdowns in a grid
""" """
return rx.box( return rx.box(
rx.vstack( rx.vstack(
@@ -1768,27 +1760,11 @@ def filter_section() -> rx.Component:
"Filters", "Filters",
**text_h1(), **text_h1(),
), ),
# Row 1: Date range pickers # Row 1: Date filter dropdowns
rx.hstack( rx.hstack(
date_range_picker( initiated_filter_dropdown(),
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,
),
rx.divider(orientation="vertical", size="3"), rx.divider(orientation="vertical", size="3"),
date_range_picker( last_seen_filter_dropdown(),
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,
),
spacing="5", spacing="5",
align="start", align="start",
flex_wrap="wrap", flex_wrap="wrap",