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>
54 lines
1.8 KiB
Markdown
54 lines
1.8 KiB
Markdown
# Sprint 9-10 - Figure Factory Pattern for Reusable Charts
|
|
|
|
## Context
|
|
Creating multiple chart types across 5 dashboard tabs, with consistent styling and behavior needed across all visualizations.
|
|
|
|
## Problem
|
|
Without a standardized approach, each callback would create figures inline with:
|
|
- Duplicated styling code (colors, fonts, backgrounds)
|
|
- Inconsistent hover templates
|
|
- Hard-to-maintain figure creation logic
|
|
- No reuse between tabs
|
|
|
|
## Solution
|
|
Created a `figures/` module with factory functions:
|
|
|
|
```
|
|
figures/
|
|
├── __init__.py # Exports all factories
|
|
├── choropleth.py # Map visualizations
|
|
├── bar_charts.py # ranking_bar, stacked_bar, horizontal_bar
|
|
├── scatter.py # scatter_figure, bubble_chart
|
|
├── radar.py # radar_figure, comparison_radar
|
|
└── demographics.py # age_pyramid, donut_chart
|
|
```
|
|
|
|
Factory pattern benefits:
|
|
1. **Consistent styling** - dark theme applied once
|
|
2. **Type-safe interfaces** - clear parameters for each chart type
|
|
3. **Easy testing** - factories can be unit tested with sample data
|
|
4. **Reusability** - same factory used across multiple tabs
|
|
|
|
Example factory signature:
|
|
```python
|
|
def create_ranking_bar(
|
|
data: list[dict],
|
|
name_column: str,
|
|
value_column: str,
|
|
title: str = "",
|
|
top_n: int = 5,
|
|
bottom_n: int = 5,
|
|
top_color: str = "#4CAF50",
|
|
bottom_color: str = "#F44336",
|
|
) -> go.Figure:
|
|
```
|
|
|
|
## Prevention
|
|
- **Create factories early** - before implementing callbacks
|
|
- **Design generic interfaces** - factories should work with any data matching the schema
|
|
- **Apply styling in one place** - use constants for colors, fonts
|
|
- **Test factories independently** - with synthetic data before integration
|
|
|
|
## Tags
|
|
plotly, dash, design-patterns, python, visualization, reusability, code-organization
|