Files
personal-portfolio/portfolio_app/components/time_slider.py
lmiranda 077e426d34 feat: add Sprint 5 visualization components and Toronto dashboard
- Add figure factories: choropleth, time_series, summary_cards
- Add shared components: map_controls, time_slider, metric_card
- Create Toronto dashboard page with KPI cards, choropleth maps, and time series
- Add dashboard callbacks for interactivity
- Placeholder data for demonstration until QGIS boundaries are complete

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 16:20:01 -05:00

136 lines
3.4 KiB
Python

"""Time selection components for temporal data filtering."""
from datetime import date
import dash_mantine_components as dmc
def create_year_selector(
id_prefix: str,
min_year: int = 2020,
max_year: int | None = None,
default_year: int | None = None,
label: str = "Select Year",
) -> dmc.Select:
"""Create a year selector dropdown.
Args:
id_prefix: Prefix for component IDs.
min_year: Minimum year option.
max_year: Maximum year option (defaults to current year).
default_year: Initial selected year.
label: Label text for the selector.
Returns:
Mantine Select component.
"""
if max_year is None:
max_year = date.today().year
if default_year is None:
default_year = max_year
years = list(range(max_year, min_year - 1, -1))
options = [{"label": str(year), "value": str(year)} for year in years]
return dmc.Select(
id=f"{id_prefix}-year-selector",
label=label,
data=options,
value=str(default_year),
style={"width": "120px"},
)
def create_time_slider(
id_prefix: str,
min_year: int = 2020,
max_year: int | None = None,
default_range: tuple[int, int] | None = None,
label: str = "Time Range",
) -> dmc.Paper:
"""Create a time range slider component.
Args:
id_prefix: Prefix for component IDs.
min_year: Minimum year for the slider.
max_year: Maximum year for the slider.
default_range: Default (start, end) year range.
label: Label text for the slider.
Returns:
Mantine Paper component containing the slider.
"""
if max_year is None:
max_year = date.today().year
if default_range is None:
default_range = (min_year, max_year)
# Create marks for every year
marks = [
{"value": year, "label": str(year)} for year in range(min_year, max_year + 1)
]
return dmc.Paper(
children=[
dmc.Text(label, fw=500, size="sm", mb="xs"),
dmc.RangeSlider(
id=f"{id_prefix}-time-slider",
min=min_year,
max=max_year,
value=list(default_range),
marks=marks,
step=1,
minRange=1,
style={"marginTop": "20px", "marginBottom": "10px"},
),
],
p="md",
radius="sm",
withBorder=True,
)
def create_month_selector(
id_prefix: str,
default_month: int | None = None,
label: str = "Select Month",
) -> dmc.Select:
"""Create a month selector dropdown.
Args:
id_prefix: Prefix for component IDs.
default_month: Initial selected month (1-12).
label: Label text for the selector.
Returns:
Mantine Select component.
"""
months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
]
options = [{"label": month, "value": str(i + 1)} for i, month in enumerate(months)]
if default_month is None:
default_month = date.today().month
return dmc.Select(
id=f"{id_prefix}-month-selector",
label=label,
data=options,
value=str(default_month),
style={"width": "140px"},
)