frontend implementation
This commit is contained in:
132
frontend/heatmap.js
Normal file
132
frontend/heatmap.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// 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);
|
||||
}
|
||||
Reference in New Issue
Block a user