HeatmapViewModel
Complete heatmap data structure optimized for rendering calendar visualizations. Contains all data needed to display a GitHub-style contribution heatmap.
Array of weeks, where each week contains 7 day cells
Maximum daily mileage across all days in the heatmap (used for color scaling)
Total mileage across all days in the heatmap
The current date, used to highlight today’s cell
Example
let viewModel = HeatmapViewModel(
weeks: weeks,
maxMiles: 15.5,
totalMiles: 425.3,
today: Date()
)
// Use in SwiftUI
ForEach(viewModel.weeks, id: \.start) { week in
ForEach(week.values, id: \.date) { cell in
HeatmapCell(
miles: cell.miles,
intensity: cell.miles / viewModel.maxMiles
)
}
}
HeatmapWeek
Represents a single week in the heatmap grid, containing 7 day cells.
Start date of the week (typically Sunday)
Array of 7 cells representing each day of the week
Example
let week = HeatmapWeek(
start: startOfWeek,
values: [
HeatmapCell(date: sunday, miles: 0, activityCount: 0),
HeatmapCell(date: monday, miles: 5.2, activityCount: 1),
HeatmapCell(date: tuesday, miles: 3.1, activityCount: 1),
HeatmapCell(date: wednesday, miles: 0, activityCount: 0),
HeatmapCell(date: thursday, miles: 6.8, activityCount: 2),
HeatmapCell(date: friday, miles: 4.0, activityCount: 1),
HeatmapCell(date: saturday, miles: 10.2, activityCount: 1)
]
)
HeatmapCell
Represents a single day cell in the heatmap visualization.
The date this cell represents
Total miles covered on this day
Number of activities completed on this day
Example
let cell = HeatmapCell(
date: Date(),
miles: 6.2,
activityCount: 1
)
// Calculate intensity for color
let intensity = cell.miles / maxMiles
let color = Color.orange.opacity(intensity)
MonthLabel
Label data for displaying month names above heatmap columns.
Month abbreviation (e.g., “Jan”, “Feb”, “Mar”)
Index of the week column where this label should appear
Example
let labels = [
MonthLabel(label: "Jan", weekIndex: 0),
MonthLabel(label: "Feb", weekIndex: 4),
MonthLabel(label: "Mar", weekIndex: 8)
]
// Use in UI
ForEach(labels, id: \.weekIndex) { label in
Text(label.label)
.position(x: xForWeek(label.weekIndex), y: 0)
}
Building Heatmap Views
Use HeatmapBuilder.buildHeatmapView() to construct a complete view model from heatmap days:
import StratilesCore
let heatmapDays = [
HeatmapDay(date: "2024-01-01", miles: 5.0, activityCount: 1, distanceMeters: 8046.72),
HeatmapDay(date: "2024-01-02", miles: 3.2, activityCount: 1, distanceMeters: 5149.89),
// ... more days
]
let viewModel = HeatmapBuilder.buildHeatmapView(
heatmap: heatmapDays,
weeksToShow: 52
)
print("Total miles: \(viewModel.totalMiles)")
print("Max daily miles: \(viewModel.maxMiles)")
print("Weeks: \(viewModel.weeks.count)")
All heatmap view models conform to:
Sendable - Safe to share across concurrency domains
Hashable - Can be used in Sets and Dictionary keys (HeatmapWeek, HeatmapCell, MonthLabel)
HeatmapViewModel is Sendable only (not Hashable).