133 lines
2.8 KiB
JavaScript
133 lines
2.8 KiB
JavaScript
// Heatmap Component using Cal-Heatmap library
|
|
|
|
let cal = null;
|
|
|
|
/**
|
|
* Initialize the Cal-Heatmap component
|
|
* @param {Array} sessions - Array of session objects
|
|
*/
|
|
function initHeatmap(sessions) {
|
|
const container = document.getElementById('heatmap');
|
|
if (!container) return;
|
|
|
|
// Transform sessions data for Cal-Heatmap
|
|
const heatmapData = transformSessionsForHeatmap(sessions);
|
|
|
|
// Initialize Cal-Heatmap
|
|
cal = new CalHeatmap();
|
|
|
|
const currentYear = new Date().getFullYear();
|
|
|
|
cal.paint({
|
|
itemSelector: '#heatmap',
|
|
domain: {
|
|
type: 'month',
|
|
label: {
|
|
position: 'bottom'
|
|
},
|
|
},
|
|
subDomain: {
|
|
type: 'day'
|
|
},
|
|
data: {
|
|
source: heatmapData,
|
|
type: 'json',
|
|
x: 'date',
|
|
y: 'value'
|
|
},
|
|
date: {
|
|
start: new Date(currentYear, 0, 1),
|
|
max: new Date(currentYear, 11, 31)
|
|
},
|
|
range: 12,
|
|
scale: {
|
|
color: {
|
|
type: 'threshold',
|
|
range: ['#ebedf0', '#9be9a8', '#40c463', '#30a14e', '#216e39'],
|
|
domain: [1, 2, 3, 4]
|
|
}
|
|
},
|
|
itemName: ['workout', 'workouts'],
|
|
subDomainTextFormat: '%d',
|
|
tooltip: true
|
|
});
|
|
|
|
// Set up navigation controls
|
|
setupHeatmapControls();
|
|
}
|
|
|
|
/**
|
|
* Transform sessions array into format suitable for Cal-Heatmap
|
|
* @param {Array} sessions - Array of session objects
|
|
* @returns {Array} Transformed data for Cal-Heatmap
|
|
*/
|
|
function transformSessionsForHeatmap(sessions) {
|
|
const dateCounts = {};
|
|
|
|
sessions.forEach(session => {
|
|
const date = session.date;
|
|
// Count number of muscle groups trained (as measure of intensity)
|
|
const value = session.muscle_groups.length;
|
|
|
|
if (dateCounts[date]) {
|
|
dateCounts[date] += value;
|
|
} else {
|
|
dateCounts[date] = value;
|
|
}
|
|
});
|
|
|
|
// Convert to array format expected by Cal-Heatmap
|
|
return Object.entries(dateCounts).map(([date, value]) => ({
|
|
date,
|
|
value
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Update heatmap with new sessions data
|
|
* @param {Array} sessions - Array of session objects
|
|
*/
|
|
function updateHeatmap(sessions) {
|
|
if (!cal) {
|
|
initHeatmap(sessions);
|
|
return;
|
|
}
|
|
|
|
const heatmapData = transformSessionsForHeatmap(sessions);
|
|
|
|
// Update the heatmap data
|
|
cal.fill(heatmapData);
|
|
}
|
|
|
|
/**
|
|
* Set up navigation controls for the heatmap (previous/next)
|
|
*/
|
|
function setupHeatmapControls() {
|
|
const prevBtn = document.getElementById('heatmapPrev');
|
|
const nextBtn = document.getElementById('heatmapNext');
|
|
|
|
if (prevBtn && cal) {
|
|
prevBtn.addEventListener('click', () => {
|
|
cal.previous();
|
|
});
|
|
}
|
|
|
|
if (nextBtn && cal) {
|
|
nextBtn.addEventListener('click', () => {
|
|
cal.next();
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Destroy and reinitialize the heatmap
|
|
* @param {Array} sessions - Array of session objects
|
|
*/
|
|
function reinitializeHeatmap(sessions) {
|
|
if (cal) {
|
|
cal.destroy();
|
|
cal = null;
|
|
}
|
|
initHeatmap(sessions);
|
|
}
|