Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Workout Analytics Dashboard</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> | |
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> | |
<style> | |
.custom-scrollbar::-webkit-scrollbar { | |
width: 6px; | |
height: 6px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-track { | |
background: #f1f1f1; | |
border-radius: 10px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-thumb { | |
background: #888; | |
border-radius: 10px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-thumb:hover { | |
background: #555; | |
} | |
.chart-container { | |
position: relative; | |
height: 100%; | |
width: 100%; | |
} | |
.progress-ring__circle { | |
transition: stroke-dashoffset 0.5s; | |
transform: rotate(-90deg); | |
transform-origin: 50% 50%; | |
} | |
.blink { | |
animation: blink-animation 1.5s steps(5, start) infinite; | |
} | |
@keyframes blink-animation { | |
to { | |
visibility: hidden; | |
} | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 font-sans"> | |
<div class="container mx-auto px-4 py-8"> | |
<div class="flex justify-between items-center mb-8"> | |
<h1 class="text-3xl font-bold text-gray-800">Workout Performance Analytics</h1> | |
<div class="flex space-x-4"> | |
<div class="relative"> | |
<select class="appearance-none bg-white border border-gray-300 rounded-md py-2 pl-3 pr-8 text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
<option>Last 7 Days</option> | |
<option selected>Last 30 Days</option> | |
<option>Last 90 Days</option> | |
<option>Custom Range</option> | |
</select> | |
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"> | |
<i class="fas fa-chevron-down"></i> | |
</div> | |
</div> | |
<button class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md flex items-center"> | |
<i class="fas fa-download mr-2"></i> Export | |
</button> | |
</div> | |
</div> | |
<!-- Summary Cards --> | |
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> | |
<div class="bg-white rounded-xl shadow-md p-6 flex items-center"> | |
<div class="p-3 rounded-full bg-blue-100 text-blue-600 mr-4"> | |
<i class="fas fa-dumbbell text-xl"></i> | |
</div> | |
<div> | |
<p class="text-gray-500 text-sm">Total Volume</p> | |
<h3 class="text-2xl font-bold">12,450 kg</h3> | |
<p class="text-green-500 text-sm flex items-center"> | |
<i class="fas fa-arrow-up mr-1"></i> 8.2% from last month | |
</p> | |
</div> | |
</div> | |
<div class="bg-white rounded-xl shadow-md p-6 flex items-center"> | |
<div class="p-3 rounded-full bg-purple-100 text-purple-600 mr-4"> | |
<i class="fas fa-clock text-xl"></i> | |
</div> | |
<div> | |
<p class="text-gray-500 text-sm">Avg Rest Time</p> | |
<h3 class="text-2xl font-bold">72s</h3> | |
<p class="text-red-500 text-sm flex items-center"> | |
<i class="fas fa-arrow-down mr-1"></i> 5.3% from last month | |
</p> | |
</div> | |
</div> | |
<div class="bg-white rounded-xl shadow-md p-6 flex items-center"> | |
<div class="p-3 rounded-full bg-green-100 text-green-600 mr-4"> | |
<i class="fas fa-fire text-xl"></i> | |
</div> | |
<div> | |
<p class="text-gray-500 text-sm">Workout Intensity</p> | |
<h3 class="text-2xl font-bold">78%</h3> | |
<p class="text-green-500 text-sm flex items-center"> | |
<i class="fas fa-arrow-up mr-1"></i> 12.1% from last month | |
</p> | |
</div> | |
</div> | |
<div class="bg-white rounded-xl shadow-md p-6 flex items-center"> | |
<div class="p-3 rounded-full bg-orange-100 text-orange-600 mr-4"> | |
<i class="fas fa-heartbeat text-xl"></i> | |
</div> | |
<div> | |
<p class="text-gray-500 text-sm">Avg Heart Rate</p> | |
<h3 class="text-2xl font-bold">142 bpm</h3> | |
<p class="text-green-500 text-sm flex items-center"> | |
<i class="fas fa-arrow-up mr-1"></i> 3.7% from last month | |
</p> | |
</div> | |
</div> | |
</div> | |
<!-- Main Charts --> | |
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8"> | |
<!-- Workout Volume & Intensity Chart --> | |
<div class="bg-white rounded-xl shadow-md p-6"> | |
<div class="flex justify-between items-center mb-4"> | |
<h2 class="text-xl font-semibold text-gray-800">Workout Volume & Intensity</h2> | |
<div class="flex space-x-2"> | |
<button class="px-3 py-1 text-sm bg-blue-100 text-blue-600 rounded-md">Volume</button> | |
<button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-md">Intensity</button> | |
<button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-md">Both</button> | |
</div> | |
</div> | |
<div class="chart-container"> | |
<canvas id="volumeIntensityChart"></canvas> | |
</div> | |
</div> | |
<!-- Rest Periods & Recovery Chart --> | |
<div class="bg-white rounded-xl shadow-md p-6"> | |
<div class="flex justify-between items-center mb-4"> | |
<h2 class="text-xl font-semibold text-gray-800">Rest Periods & Recovery</h2> | |
<div class="flex items-center text-sm text-gray-500"> | |
<i class="fas fa-info-circle mr-1"></i> Optimal range: 60-90s | |
</div> | |
</div> | |
<div class="chart-container"> | |
<canvas id="restRecoveryChart"></canvas> | |
</div> | |
</div> | |
</div> | |
<!-- Secondary Charts --> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8"> | |
<!-- Muscle Group Distribution --> | |
<div class="bg-white rounded-xl shadow-md p-6"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Muscle Group Distribution</h2> | |
<div class="chart-container"> | |
<canvas id="muscleGroupChart"></canvas> | |
</div> | |
</div> | |
<!-- Weight Progression --> | |
<div class="bg-white rounded-xl shadow-md p-6"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Weight Progression</h2> | |
<div class="chart-container"> | |
<canvas id="weightProgressionChart"></canvas> | |
</div> | |
</div> | |
<!-- Workout Consistency --> | |
<div class="bg-white rounded-xl shadow-md p-6"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Workout Consistency</h2> | |
<div class="flex items-center justify-center h-48"> | |
<svg class="w-40 h-40"> | |
<circle | |
class="text-gray-200" | |
stroke-width="10" | |
stroke="currentColor" | |
fill="transparent" | |
r="60" | |
cx="80" | |
cy="80" | |
/> | |
<circle | |
class="progress-ring__circle text-blue-600" | |
stroke-width="10" | |
stroke-linecap="round" | |
stroke="currentColor" | |
fill="transparent" | |
r="60" | |
cx="80" | |
cy="80" | |
stroke-dasharray="377" | |
stroke-dashoffset="75.4" | |
/> | |
</svg> | |
<div class="absolute text-center"> | |
<span class="text-3xl font-bold">80%</span> | |
<p class="text-gray-500 text-sm">Completion Rate</p> | |
</div> | |
</div> | |
<div class="mt-4 text-center"> | |
<p class="text-gray-600">You've completed 16 of 20 planned workouts this month</p> | |
</div> | |
</div> | |
</div> | |
<!-- Detailed Metrics Table --> | |
<div class="bg-white rounded-xl shadow-md overflow-hidden mb-8"> | |
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center"> | |
<h2 class="text-xl font-semibold text-gray-800">Workout Session Details</h2> | |
<div class="relative"> | |
<input type="text" placeholder="Search workouts..." class="pl-8 pr-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
<i class="fas fa-search absolute left-3 top-3 text-gray-400"></i> | |
</div> | |
</div> | |
<div class="overflow-x-auto custom-scrollbar"> | |
<table class="min-w-full divide-y divide-gray-200"> | |
<thead class="bg-gray-50"> | |
<tr> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Workout</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Volume (kg)</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Avg Rest</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Intensity</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">HR Max</th> | |
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Recovery</th> | |
</tr> | |
</thead> | |
<tbody class="bg-white divide-y divide-gray-200"> | |
<tr class="hover:bg-gray-50"> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">Jun 12, 2023</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">Upper Body</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">2,450</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">68s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<div class="flex items-center"> | |
<div class="h-2 w-16 bg-gray-200 rounded-full mr-2"> | |
<div class="h-2 bg-green-500 rounded-full" style="width: 75%"></div> | |
</div> | |
<span>75%</span> | |
</div> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">158 bpm</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800">Excellent</span> | |
</td> | |
</tr> | |
<tr class="hover:bg-gray-50"> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">Jun 10, 2023</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">Leg Day</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">3,120</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">82s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<div class="flex items-center"> | |
<div class="h-2 w-16 bg-gray-200 rounded-full mr-2"> | |
<div class="h-2 bg-yellow-500 rounded-full" style="width: 65%"></div> | |
</div> | |
<span>65%</span> | |
</div> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">162 bpm</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<span class="px-2 py-1 text-xs rounded-full bg-yellow-100 text-yellow-800">Good</span> | |
</td> | |
</tr> | |
<tr class="hover:bg-gray-50"> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">Jun 8, 2023</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">Full Body</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">2,780</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">71s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<div class="flex items-center"> | |
<div class="h-2 w-16 bg-gray-200 rounded-full mr-2"> | |
<div class="h-2 bg-green-500 rounded-full" style="width: 80%"></div> | |
</div> | |
<span>80%</span> | |
</div> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">155 bpm</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800">Excellent</span> | |
</td> | |
</tr> | |
<tr class="hover:bg-gray-50"> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">Jun 5, 2023</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-blue-600">Upper Body</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">2,310</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">65s</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<div class="flex items-center"> | |
<div class="h-2 w-16 bg-gray-200 rounded-full mr-2"> | |
<div class="h-2 bg-red-500 rounded-full" style="width: 45%"></div> | |
</div> | |
<span>45%</span> | |
</div> | |
</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">148 bpm</td> | |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
<span class="px-2 py-1 text-xs rounded-full bg-red-100 text-red-800">Poor</span> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<div class="px-6 py-4 border-t border-gray-200 flex items-center justify-between"> | |
<div class="text-sm text-gray-500"> | |
Showing <span class="font-medium">1</span> to <span class="font-medium">4</span> of <span class="font-medium">16</span> workouts | |
</div> | |
<div class="flex space-x-2"> | |
<button class="px-3 py-1 border border-gray-300 rounded-md text-sm bg-white text-gray-700 hover:bg-gray-50">Previous</button> | |
<button class="px-3 py-1 border border-gray-300 rounded-md text-sm bg-blue-600 text-white hover:bg-blue-700">1</button> | |
<button class="px-3 py-1 border border-gray-300 rounded-md text-sm bg-white text-gray-700 hover:bg-gray-50">2</button> | |
<button class="px-3 py-1 border border-gray-300 rounded-md text-sm bg-white text-gray-700 hover:bg-gray-50">3</button> | |
<button class="px-3 py-1 border border-gray-300 rounded-md text-sm bg-white text-gray-700 hover:bg-gray-50">Next</button> | |
</div> | |
</div> | |
</div> | |
<!-- Insights Section --> | |
<div class="bg-white rounded-xl shadow-md p-6 mb-8"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Performance Insights</h2> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<div class="border-l-4 border-blue-500 pl-4"> | |
<h3 class="text-lg font-medium text-gray-800 mb-2">Positive Trend</h3> | |
<p class="text-gray-600">Your workout volume has increased by 8.2% compared to last month, indicating progressive overload which is essential for muscle growth.</p> | |
</div> | |
<div class="border-l-4 border-yellow-500 pl-4"> | |
<h3 class="text-lg font-medium text-gray-800 mb-2">Attention Needed</h3> | |
<p class="text-gray-600">Your average rest periods have decreased by 5.3%. While this may increase workout density, ensure you're getting adequate recovery between sets.</p> | |
</div> | |
<div class="border-l-4 border-green-500 pl-4"> | |
<h3 class="text-lg font-medium text-gray-800 mb-2">Excellent Progress</h3> | |
<p class="text-gray-600">Your workout intensity has improved significantly (+12.1%), showing you're pushing yourself appropriately during sessions.</p> | |
</div> | |
<div class="border-l-4 border-purple-500 pl-4"> | |
<h3 class="text-lg font-medium text-gray-800 mb-2">Recommendation</h3> | |
<p class="text-gray-600">Consider adding 1-2 additional lower body sessions per week to balance your muscle group distribution (currently 65% upper body focus).</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Volume & Intensity Chart | |
const volumeIntensityCtx = document.getElementById('volumeIntensityChart').getContext('2d'); | |
const volumeIntensityChart = new Chart(volumeIntensityCtx, { | |
type: 'line', | |
data: { | |
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'], | |
datasets: [ | |
{ | |
label: 'Workout Volume (kg)', | |
data: [8500, 9200, 8800, 10200, 11000, 12450], | |
borderColor: 'rgba(59, 130, 246, 1)', | |
backgroundColor: 'rgba(59, 130, 246, 0.05)', | |
borderWidth: 2, | |
fill: true, | |
tension: 0.3, | |
yAxisID: 'y' | |
}, | |
{ | |
label: 'Workout Intensity (%)', | |
data: [65, 68, 70, 72, 75, 78], | |
borderColor: 'rgba(16, 185, 129, 1)', | |
backgroundColor: 'rgba(16, 185, 129, 0.05)', | |
borderWidth: 2, | |
borderDash: [5, 5], | |
tension: 0.3, | |
yAxisID: 'y1' | |
} | |
] | |
}, | |
options: { | |
responsive: true, | |
interaction: { | |
mode: 'index', | |
intersect: false, | |
}, | |
plugins: { | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
let label = context.dataset.label || ''; | |
if (label) { | |
label += ': '; | |
} | |
if (context.datasetIndex === 0) { | |
label += context.parsed.y.toLocaleString() + ' kg'; | |
} else { | |
label += context.parsed.y + '%'; | |
} | |
return label; | |
} | |
} | |
}, | |
legend: { | |
position: 'top', | |
}, | |
annotation: { | |
annotations: { | |
line1: { | |
type: 'line', | |
yMin: 70, | |
yMax: 70, | |
borderColor: 'rgba(16, 185, 129, 0.5)', | |
borderWidth: 1, | |
borderDash: [6, 6], | |
label: { | |
content: 'Target Intensity', | |
enabled: true, | |
position: 'right' | |
} | |
} | |
} | |
} | |
}, | |
scales: { | |
y: { | |
type: 'linear', | |
display: true, | |
position: 'left', | |
title: { | |
display: true, | |
text: 'Volume (kg)' | |
}, | |
grid: { | |
drawOnChartArea: false | |
} | |
}, | |
y1: { | |
type: 'linear', | |
display: true, | |
position: 'right', | |
title: { | |
display: true, | |
text: 'Intensity (%)' | |
}, | |
min: 50, | |
max: 100, | |
grid: { | |
drawOnChartArea: false | |
} | |
} | |
} | |
} | |
}); | |
// Rest & Recovery Chart | |
const restRecoveryCtx = document.getElementById('restRecoveryChart').getContext('2d'); | |
const restRecoveryChart = new Chart(restRecoveryCtx, { | |
type: 'bar', | |
data: { | |
labels: ['Jun 5', 'Jun 8', 'Jun 10', 'Jun 12', 'Jun 15', 'Jun 18', 'Jun 22', 'Jun 25', 'Jun 28'], | |
datasets: [ | |
{ | |
label: 'Rest Period (s)', | |
data: [65, 71, 82, 68, 75, 70, 67, 73, 69], | |
backgroundColor: 'rgba(124, 58, 237, 0.7)', | |
borderColor: 'rgba(124, 58, 237, 1)', | |
borderWidth: 1, | |
yAxisID: 'y' | |
}, | |
{ | |
label: 'Recovery Score', | |
data: [62, 85, 72, 88, 78, 82, 75, 80, 84], | |
type: 'line', | |
borderColor: 'rgba(245, 158, 11, 1)', | |
backgroundColor: 'rgba(245, 158, 11, 0.1)', | |
borderWidth: 2, | |
pointRadius: 4, | |
pointBackgroundColor: 'rgba(245, 158, 11, 1)', | |
tension: 0.3, | |
yAxisID: 'y1' | |
} | |
] | |
}, | |
options: { | |
responsive: true, | |
plugins: { | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
let label = context.dataset.label || ''; | |
if (label) { | |
label += ': '; | |
} | |
if (context.datasetIndex === 0) { | |
label += context.parsed.y + 's'; | |
} else { | |
label += context.parsed.y + '/100'; | |
} | |
return label; | |
} | |
} | |
}, | |
legend: { | |
position: 'top', | |
}, | |
annotation: { | |
annotations: { | |
box1: { | |
type: 'box', | |
yMin: 60, | |
yMax: 90, | |
backgroundColor: 'rgba(124, 58, 237, 0.05)', | |
borderColor: 'rgba(124, 58, 237, 0.3)', | |
borderWidth: 1, | |
label: { | |
content: 'Optimal Rest Range', | |
enabled: true, | |
position: 'top' | |
} | |
} | |
} | |
} | |
}, | |
scales: { | |
y: { | |
type: 'linear', | |
display: true, | |
position: 'left', | |
title: { | |
display: true, | |
text: 'Rest Period (seconds)' | |
}, | |
min: 50, | |
max: 100 | |
}, | |
y1: { | |
type: 'linear', | |
display: true, | |
position: 'right', | |
title: { | |
display: true, | |
text: 'Recovery Score' | |
}, | |
min: 50, | |
max: 100, | |
grid: { | |
drawOnChartArea: false | |
} | |
} | |
} | |
} | |
}); | |
// Muscle Group Chart | |
const muscleGroupCtx = document.getElementById('muscleGroupChart').getContext('2d'); | |
const muscleGroupChart = new Chart(muscleGroupCtx, { | |
type: 'doughnut', | |
data: { | |
labels: ['Chest', 'Back', 'Legs', 'Shoulders', 'Arms', 'Core'], | |
datasets: [{ | |
data: [25, 20, 15, 15, 15, 10], | |
backgroundColor: [ | |
'rgba(59, 130, 246, 0.8)', | |
'rgba(16, 185, 129, 0.8)', | |
'rgba(245, 158, 11, 0.8)', | |
'rgba(124, 58, 237, 0.8)', | |
'rgba(239, 68, 68, 0.8)', | |
'rgba(14, 165, 233, 0.8)' | |
], | |
borderColor: [ | |
'rgba(59, 130, 246, 1)', | |
'rgba(16, 185, 129, 1)', | |
'rgba(245, 158, 11, 1)', | |
'rgba(124, 58, 237, 1)', | |
'rgba(239, 68, 68, 1)', | |
'rgba(14, 165, 233, 1)' | |
], | |
borderWidth: 1 | |
}] | |
}, | |
options: { | |
responsive: true, | |
plugins: { | |
legend: { | |
position: 'right', | |
}, | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
const label = context.label || ''; | |
const value = context.raw || 0; | |
const total = context.dataset.data.reduce((a, b) => a + b, 0); | |
const percentage = Math.round((value / total) * 100); | |
return `${label}: ${percentage}% (${value} sessions)`; | |
} | |
} | |
} | |
}, | |
cutout: '65%' | |
} | |
}); | |
// Weight Progression Chart | |
const weightProgressionCtx = document.getElementById('weightProgressionChart').getContext('2d'); | |
const weightProgressionChart = new Chart(weightProgressionCtx, { | |
type: 'line', | |
data: { | |
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], | |
datasets: [ | |
{ | |
label: 'Bench Press (kg)', | |
data: [60, 62, 65, 67, 70, 72], | |
borderColor: 'rgba(59, 130, 246, 1)', | |
backgroundColor: 'rgba(59, 130, 246, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
fill: true | |
}, | |
{ | |
label: 'Squat (kg)', | |
data: [80, 82, 85, 87, 90, 95], | |
borderColor: 'rgba(16, 185, 129, 1)', | |
backgroundColor: 'rgba(16, 185, 129, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
fill: true | |
}, | |
{ | |
label: 'Deadlift (kg)', | |
data: [90, 92, 95, 100, 105, 110], | |
borderColor: 'rgba(245, 158, 11, 1)', | |
backgroundColor: 'rgba(245, 158, 11, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
fill: true | |
} | |
] | |
}, | |
options: { | |
responsive: true, | |
plugins: { | |
legend: { | |
position: 'top', | |
}, | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
return context.dataset.label + ': ' + context.parsed.y + 'kg'; | |
} | |
} | |
} | |
}, | |
scales: { | |
y: { | |
beginAtZero: false, | |
min: 50, | |
title: { | |
display: true, | |
text: 'Weight (kg)' | |
} | |
} | |
} | |
} | |
}); | |
// Animate progress ring | |
document.addEventListener('DOMContentLoaded', function() { | |
const circle = document.querySelector('.progress-ring__circle'); | |
const radius = circle.r.baseVal.value; | |
const circumference = 2 * Math.PI * radius; | |
circle.style.strokeDasharray = circumference; | |
circle.style.strokeDashoffset = circumference - (0.8 * circumference); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=PhoenixBomb/workout-board" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |