feat: Complete Phase 5 dashboard implementation
Implement full 5-tab Toronto Neighbourhood Dashboard with real data connectivity: Dashboard Structure: - Overview tab with livability scores and rankings - Housing tab with affordability metrics - Safety tab with crime statistics - Demographics tab with population/income data - Amenities tab with parks, schools, transit Figure Factories (portfolio_app/figures/): - bar_charts.py: ranking, stacked, horizontal bars - scatter.py: scatter plots, bubble charts - radar.py: spider/radar charts - demographics.py: donut, age pyramid, income distribution Service Layer (portfolio_app/toronto/services/): - neighbourhood_service.py: queries dbt marts for all tab data - geometry_service.py: generates GeoJSON from PostGIS - Graceful error handling when database unavailable Callbacks (portfolio_app/pages/toronto/callbacks/): - map_callbacks.py: choropleth updates, map click handling - chart_callbacks.py: supporting chart updates - selection_callbacks.py: dropdown handlers, KPI updates Data Pipeline (scripts/data/): - load_toronto_data.py: orchestration script with CLI flags Lessons Learned: - Graceful error handling in service layers - Modular callback structure for multi-tab dashboards - Figure factory pattern for reusable charts Closes: #64, #65, #66, #67, #68, #69, #70 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Sprint 9-10 - Modular Callback Structure for Multi-Tab Dashboards
|
||||
|
||||
## Context
|
||||
Implementing a 5-tab Toronto Neighbourhood Dashboard with multiple callbacks per tab (map updates, chart updates, KPI updates, selection handling).
|
||||
|
||||
## Problem
|
||||
Initial callback implementation approach would have placed all callbacks in a single file, leading to:
|
||||
- A monolithic file with 500+ lines
|
||||
- Difficult-to-navigate code
|
||||
- Callbacks for different tabs interleaved
|
||||
- Testing difficulties
|
||||
|
||||
## Solution
|
||||
Organized callbacks into three focused modules:
|
||||
|
||||
```
|
||||
callbacks/
|
||||
├── __init__.py # Imports all modules to register callbacks
|
||||
├── map_callbacks.py # Choropleth updates, map click handling
|
||||
├── chart_callbacks.py # Supporting chart updates (scatter, trend, donut)
|
||||
└── selection_callbacks.py # Dropdown population, KPI updates
|
||||
```
|
||||
|
||||
Key patterns:
|
||||
1. **Group by responsibility**, not by tab - all map-related callbacks together
|
||||
2. **Use noqa comments** for imports that register callbacks as side effects
|
||||
3. **Share helper functions** (like `_empty_chart()`) within modules
|
||||
|
||||
```python
|
||||
# callbacks/__init__.py
|
||||
from . import (
|
||||
chart_callbacks, # noqa: F401
|
||||
map_callbacks, # noqa: F401
|
||||
selection_callbacks, # noqa: F401
|
||||
)
|
||||
```
|
||||
|
||||
## Prevention
|
||||
- **Plan callback organization before implementation** - sketch which callbacks go where
|
||||
- **Group by function, not by feature** - keeps related logic together
|
||||
- **Keep modules under 400 lines** - split if exceeding
|
||||
- **Test imports early** - verify callbacks register correctly
|
||||
|
||||
## Tags
|
||||
dash, callbacks, architecture, python, code-organization, maintainability
|
||||
Reference in New Issue
Block a user