All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 13s
Add 3 new stat cards (Last Workout, Personal Records, Adherence Rate), recent activity table, progression timeline chart, and muscle group recency heatmap to the dashboard. Remove Total Volume card. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.9 KiB
HTML
91 lines
2.9 KiB
HTML
<article>
|
|
<header><h3>Progression Timeline</h3></header>
|
|
<div id="progression-container">
|
|
<canvas id="progression-chart" style="max-height:350px;"></canvas>
|
|
<div style="margin-top:0.5rem;">
|
|
<label for="progression-filter" style="display:inline; margin-right:0.5rem;">Exercise:</label>
|
|
<select id="progression-filter" style="display:inline-block; width:auto;">
|
|
<option value="all">All Exercises</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<p id="progression-empty" style="display:none;">No progression data yet.</p>
|
|
</article>
|
|
<script>
|
|
(function() {
|
|
var timeline = {{ progression_timeline_json|safe }};
|
|
var exerciseData = timeline.exercises || {};
|
|
var names = Object.keys(exerciseData);
|
|
|
|
if (names.length === 0) {
|
|
document.getElementById('progression-container').style.display = 'none';
|
|
document.getElementById('progression-empty').style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
var colors = [
|
|
'rgba(99, 102, 241, 1)',
|
|
'rgba(34, 197, 94, 1)',
|
|
'rgba(234, 179, 8, 1)',
|
|
'rgba(249, 115, 22, 1)',
|
|
'rgba(239, 68, 68, 1)',
|
|
'rgba(168, 85, 247, 1)',
|
|
'rgba(20, 184, 166, 1)',
|
|
'rgba(236, 72, 153, 1)',
|
|
];
|
|
|
|
var datasets = [];
|
|
var filterSelect = document.getElementById('progression-filter');
|
|
|
|
names.forEach(function(name, i) {
|
|
var d = exerciseData[name];
|
|
datasets.push({
|
|
label: name,
|
|
data: d.dates.map(function(dt, j) {
|
|
return {x: dt, y: d.weights[j]};
|
|
}),
|
|
borderColor: colors[i % colors.length],
|
|
backgroundColor: colors[i % colors.length].replace('1)', '0.2)'),
|
|
tension: 0.3,
|
|
pointRadius: 3,
|
|
hidden: false,
|
|
});
|
|
var opt = document.createElement('option');
|
|
opt.value = i;
|
|
opt.textContent = name;
|
|
filterSelect.appendChild(opt);
|
|
});
|
|
|
|
var chart = new Chart(document.getElementById('progression-chart'), {
|
|
type: 'line',
|
|
data: {datasets: datasets},
|
|
options: {
|
|
responsive: true,
|
|
plugins: {
|
|
legend: {labels: {color: '#ccc'}},
|
|
},
|
|
scales: {
|
|
x: {
|
|
type: 'time',
|
|
time: {unit: 'week'},
|
|
ticks: {color: '#ccc'},
|
|
},
|
|
y: {
|
|
beginAtZero: false,
|
|
title: {display: true, text: 'Weight (lbs)', color: '#ccc'},
|
|
ticks: {color: '#ccc'},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
filterSelect.addEventListener('change', function() {
|
|
var val = this.value;
|
|
chart.data.datasets.forEach(function(ds, i) {
|
|
ds.hidden = (val !== 'all' && i !== parseInt(val));
|
|
});
|
|
chart.update();
|
|
});
|
|
})();
|
|
</script>
|