Spaces:
Running
Running
<html lang="fr"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Track Lift - Suivi de Musculation</title> | |
<style> | |
:root { | |
--bg-dark: #121212; | |
--bg-card: #1e1e1e; | |
--text-light: #e0e0e0; | |
--accent: #4CAF50; | |
--accent-dark: #3a8a3d; | |
--danger: #f44336; | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
} | |
body { | |
background-color: var(--bg-dark); | |
color: var(--text-light); | |
min-height: 100vh; | |
padding-bottom: 80px; /* Pour le menu fixe en bas */ | |
} | |
.container { | |
width: 100%; | |
max-width: 800px; | |
margin: 0 auto; | |
padding: 1rem; | |
} | |
header { | |
padding: 1rem 0; | |
text-align: center; | |
border-bottom: 1px solid #333; | |
margin-bottom: 1rem; | |
} | |
h1, h2, h3 { | |
color: var(--accent); | |
} | |
.btn { | |
background-color: var(--accent); | |
color: white; | |
border: none; | |
padding: 0.6rem 1.2rem; | |
border-radius: 4px; | |
cursor: pointer; | |
font-weight: bold; | |
transition: background-color 0.2s; | |
} | |
.btn:hover { | |
background-color: var(--accent-dark); | |
} | |
.btn-outline { | |
background-color: transparent; | |
color: var(--accent); | |
border: 1px solid var(--accent); | |
} | |
.btn-danger { | |
background-color: var(--danger); | |
} | |
input, select, textarea { | |
width: 100%; | |
padding: 0.6rem; | |
margin-bottom: 1rem; | |
background-color: #2a2a2a; | |
border: 1px solid #444; | |
border-radius: 4px; | |
color: var(--text-light); | |
} | |
input[type="checkbox"] { | |
width: auto; | |
margin-right: 0.5rem; | |
} | |
.card { | |
background-color: var(--bg-card); | |
border-radius: 8px; | |
padding: 1rem; | |
margin-bottom: 1rem; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); | |
} | |
.form-group { | |
margin-bottom: 1rem; | |
} | |
.form-row { | |
display: flex; | |
gap: 0.5rem; | |
margin-bottom: 0.5rem; | |
} | |
.form-row > * { | |
flex: 1; | |
margin-bottom: 0; | |
} | |
label { | |
display: block; | |
margin-bottom: 0.3rem; | |
color: #bbb; | |
} | |
.exercise { | |
border-left: 3px solid var(--accent); | |
padding-left: 1rem; | |
margin-bottom: 1.5rem; | |
} | |
.exercise-header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 0.5rem; | |
} | |
.series-container { | |
margin-left: 0.5rem; | |
margin-top: 0.5rem; | |
} | |
.series { | |
background-color: #252525; | |
padding: 0.7rem; | |
border-radius: 4px; | |
margin-bottom: 0.5rem; | |
} | |
.nav-bottom { | |
position: fixed; | |
bottom: 0; | |
left: 0; | |
width: 100%; | |
background-color: #1a1a1a; | |
display: flex; | |
justify-content: space-around; | |
padding: 0.7rem 0; | |
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3); | |
} | |
.nav-item { | |
text-align: center; | |
color: #888; | |
text-decoration: none; | |
font-size: 0.85rem; | |
transition: color 0.2s; | |
} | |
.nav-item.active { | |
color: var(--accent); | |
} | |
.nav-icon { | |
font-size: 1.4rem; | |
margin-bottom: 0.2rem; | |
} | |
.workout-card { | |
border-left: 3px solid var(--accent); | |
cursor: pointer; | |
transition: transform 0.2s; | |
} | |
.workout-card:hover { | |
transform: translateX(5px); | |
} | |
.workout-header { | |
display: flex; | |
justify-content: space-between; | |
} | |
.stat-card { | |
text-align: center; | |
padding: 1rem; | |
} | |
.stat-value { | |
font-size: 1.8rem; | |
color: var(--accent); | |
font-weight: bold; | |
} | |
.stats-grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); | |
gap: 1rem; | |
} | |
.hidden { | |
display: none; | |
} | |
#app-container > div { | |
display: none; | |
} | |
#app-container > div.active { | |
display: block; | |
} | |
.flex-between { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.badge { | |
background-color: var(--accent); | |
color: white; | |
padding: 0.2rem 0.5rem; | |
border-radius: 10px; | |
font-size: 0.8rem; | |
} | |
.spinner { | |
border: 4px solid rgba(0, 0, 0, 0.1); | |
width: 36px; | |
height: 36px; | |
border-radius: 50%; | |
border-left-color: var(--accent); | |
animation: spin 1s linear infinite; | |
margin: 2rem auto; | |
display: none; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
.exercise-summary { | |
margin: 0.3rem 0; | |
padding: 0.3rem 0; | |
border-bottom: 1px solid #333; | |
} | |
.satisfaction { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
flex-direction: column; | |
margin-top: 1rem; | |
} | |
.satisfaction-value { | |
font-size: 2rem; | |
color: var(--accent); | |
margin-top: 0.5rem; | |
} | |
/* Pour les téléphones */ | |
@media (max-width: 600px) { | |
.form-row { | |
flex-direction: column; | |
gap: 0; | |
} | |
.container { | |
padding: 0.5rem; | |
} | |
h1 { | |
font-size: 1.5rem; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<header> | |
<h1>Track Lift</h1> | |
<p>Suivi de vos séances de musculation</p> | |
</header> | |
<div id="app-container"> | |
<!-- Page d'accueil / Liste des séances --> | |
<div id="home-page" class="active"> | |
<div class="flex-between"> | |
<h2>Mes séances</h2> | |
<button id="new-workout-btn" class="btn">Nouvelle séance</button> | |
</div> | |
<div id="workouts-list" class="workout-list"> | |
<!-- Liste des séances qui sera remplie dynamiquement --> | |
<div class="spinner"></div> | |
<p id="empty-workout-message" class="hidden" style="text-align: center; margin-top: 2rem;"> | |
Aucune séance enregistrée. Créez votre première séance avec le bouton ci-dessus. | |
</p> | |
</div> | |
</div> | |
<!-- Page Nouvelle Séance --> | |
<div id="new-workout-page" class="hidden"> | |
<div class="flex-between"> | |
<h2>Nouvelle séance</h2> | |
<button id="save-workout-btn" class="btn">Enregistrer</button> | |
</div> | |
<div class="card"> | |
<div class="form-group"> | |
<label for="workout-name">Nom de la séance</label> | |
<input type="text" id="workout-name" placeholder="Ex: Push, Jambes, Full body..."> | |
</div> | |
<div class="form-row"> | |
<div class="form-group"> | |
<label for="workout-date">Date</label> | |
<input type="date" id="workout-date"> | |
</div> | |
<div class="form-group"> | |
<label for="workout-duration">Durée (minutes)</label> | |
<input type="number" id="workout-duration" min="1" placeholder="60"> | |
</div> | |
</div> | |
</div> | |
<h3 style="margin: 1rem 0;">Exercices</h3> | |
<div id="exercises-container"> | |
<!-- Exercices ajoutés dynamiquement --> | |
</div> | |
<button id="add-exercise-btn" class="btn btn-outline" style="width: 100%; margin-top: 1rem;"> | |
+ Ajouter un exercice | |
</button> | |
<div class="card" style="margin-top: 2rem;"> | |
<div class="form-group"> | |
<label for="satisfaction">Niveau de satisfaction (1-100%)</label> | |
<input type="range" id="satisfaction" min="1" max="100" value="75"> | |
<div class="satisfaction"> | |
<span>Satisfaction</span> | |
<div class="satisfaction-value">75%</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Page Détail Séance --> | |
<div id="workout-details-page" class="hidden"> | |
<div class="flex-between"> | |
<h2 id="detail-workout-name">Détail de la séance</h2> | |
<button id="back-to-home" class="btn btn-outline">Retour</button> | |
</div> | |
<div class="card"> | |
<div class="workout-details-info"> | |
<div class="form-row"> | |
<p><strong>Date:</strong> <span id="detail-date"></span></p> | |
<p><strong>Durée:</strong> <span id="detail-duration"></span> min</p> | |
</div> | |
</div> | |
</div> | |
<div class="stats-grid" style="margin-top: 1rem;"> | |
<div class="card stat-card"> | |
<div class="stat-value" id="detail-tonnage">0</div> | |
<div>Tonnage total (kg)</div> | |
</div> | |
<div class="card stat-card"> | |
<div class="stat-value" id="detail-satisfaction">0%</div> | |
<div>Satisfaction</div> | |
</div> | |
<div class="card stat-card"> | |
<div class="stat-value" id="detail-exercises-count">0</div> | |
<div>Exercices</div> | |
</div> | |
</div> | |
<h3 style="margin: 1.5rem 0 1rem;">Exercices réalisés</h3> | |
<div id="detail-exercises-container"> | |
<!-- Exercices affichés dynamiquement --> | |
</div> | |
<button id="delete-workout-btn" class="btn btn-danger" style="width: 100%; margin-top: 2rem;"> | |
Supprimer cette séance | |
</button> | |
</div> | |
<!-- Page Statistiques --> | |
<div id="stats-page" class="hidden"> | |
<h2>Statistiques</h2> | |
<div class="stats-grid"> | |
<div class="card stat-card"> | |
<div class="stat-value" id="stats-workout-count">0</div> | |
<div>Séances totales</div> | |
</div> | |
<div class="card stat-card"> | |
<div class="stat-value" id="stats-avg-tonnage">0</div> | |
<div>Tonnage moyen</div> | |
</div> | |
<div class="card stat-card"> | |
<div class="stat-value" id="stats-avg-satisfaction">0%</div> | |
<div>Satisfaction moyenne</div> | |
</div> | |
</div> | |
<h3 style="margin: 1.5rem 0 1rem;">Dernières tendances</h3> | |
<div class="card"> | |
<p style="text-align: center; margin: 1rem 0;"> | |
Les statistiques détaillées seront calculées après plusieurs séances enregistrées. | |
</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Menu de navigation en bas --> | |
<nav class="nav-bottom"> | |
<a href="#" class="nav-item active" data-page="home-page"> | |
<div class="nav-icon">📋</div> | |
<div>Séances</div> | |
</a> | |
<a href="#" class="nav-item" data-page="stats-page"> | |
<div class="nav-icon">📊</div> | |
<div>Stats</div> | |
</a> | |
</nav> | |
<script> | |
// Structure de données | |
let workouts = []; | |
const STORAGE_KEY = 'workout-tracker-data'; | |
// Éléments DOM | |
const appContainer = document.getElementById('app-container'); | |
const navItems = document.querySelectorAll('.nav-item'); | |
const newWorkoutBtn = document.getElementById('new-workout-btn'); | |
const saveWorkoutBtn = document.getElementById('save-workout-btn'); | |
const addExerciseBtn = document.getElementById('add-exercise-btn'); | |
const exercisesContainer = document.getElementById('exercises-container'); | |
const workoutsList = document.getElementById('workouts-list'); | |
const backToHomeBtn = document.getElementById('back-to-home'); | |
const deleteWorkoutBtn = document.getElementById('delete-workout-btn'); | |
const satisfactionRange = document.getElementById('satisfaction'); | |
const satisfactionValue = document.querySelector('.satisfaction-value'); | |
const emptyWorkoutMessage = document.getElementById('empty-workout-message'); | |
// Variables globales | |
let currentWorkoutId = null; | |
// Initialisation | |
document.addEventListener('DOMContentLoaded', () => { | |
loadWorkouts(); | |
renderWorkoutsList(); | |
initEventListeners(); | |
setTodayDate(); | |
}); | |
// Définir la date d'aujourd'hui par défaut | |
function setTodayDate() { | |
const today = new Date().toISOString().split('T')[0]; | |
document.getElementById('workout-date').value = today; | |
} | |
// Charger les données depuis le stockage local | |
function loadWorkouts() { | |
const savedData = localStorage.getItem(STORAGE_KEY); | |
if (savedData) { | |
workouts = JSON.parse(savedData); | |
} | |
} | |
// Sauvegarder les données dans le stockage local | |
function saveWorkouts() { | |
localStorage.setItem(STORAGE_KEY, JSON.stringify(workouts)); | |
} | |
// Initialiser les événements | |
function initEventListeners() { | |
// Navigation | |
navItems.forEach(item => { | |
item.addEventListener('click', (e) => { | |
e.preventDefault(); | |
const targetPage = item.getAttribute('data-page'); | |
// Changer la page active | |
document.querySelectorAll('#app-container > div').forEach(page => { | |
page.classList.remove('active'); | |
}); | |
document.getElementById(targetPage).classList.add('active'); | |
// Mettre à jour la navigation | |
navItems.forEach(navItem => navItem.classList.remove('active')); | |
item.classList.add('active'); | |
// Si on va à la page statistiques, mettre à jour les stats | |
if (targetPage === 'stats-page') { | |
updateStats(); | |
} | |
}); | |
}); | |
// Nouvelle séance | |
newWorkoutBtn.addEventListener('click', () => { | |
showPage('new-workout-page'); | |
clearNewWorkoutForm(); | |
currentWorkoutId = null; | |
}); | |
// Enregistrer la séance | |
saveWorkoutBtn.addEventListener('click', saveWorkout); | |
// Ajouter un exercice | |
addExerciseBtn.addEventListener('click', addExercise); | |
// Retour à l'accueil | |
backToHomeBtn.addEventListener('click', () => { | |
showPage('home-page'); | |
}); | |
// Supprimer une séance | |
deleteWorkoutBtn.addEventListener('click', deleteWorkout); | |
// Affichage du pourcentage de satisfaction en temps réel | |
satisfactionRange.addEventListener('input', () => { | |
satisfactionValue.textContent = `${satisfactionRange.value}%`; | |
}); | |
} | |
// Afficher une page spécifique | |
function showPage(pageId) { | |
document.querySelectorAll('#app-container > div').forEach(page => { | |
page.classList.remove('active'); | |
}); | |
document.getElementById(pageId).classList.add('active'); | |
// Mettre à jour la navigation | |
const navItem = document.querySelector(`.nav-item[data-page="${pageId}"]`); | |
if (navItem) { | |
navItems.forEach(item => item.classList.remove('active')); | |
navItem.classList.add('active'); | |
} | |
} | |
// Ajouter un exercice au formulaire | |
function addExercise() { | |
const exerciseId = `exercise-${Date.now()}`; | |
const exerciseDiv = document.createElement('div'); | |
exerciseDiv.className = 'exercise card'; | |
exerciseDiv.setAttribute('data-exercise-id', exerciseId); | |
exerciseDiv.innerHTML = ` | |
<div class="exercise-header"> | |
<input type="text" placeholder="Nom de l'exercice" class="exercise-name"> | |
<button class="btn btn-danger remove-exercise" style="padding: 0.3rem 0.6rem;">×</button> | |
</div> | |
<div class="form-row"> | |
<div class="form-group"> | |
<label> | |
<input type="checkbox" class="unilateral-checkbox"> Exercice unilatéral | |
</label> | |
</div> | |
</div> | |
<div class="series-container"> | |
<!-- Les séries seront ajoutées ici --> | |
</div> | |
<button class="btn btn-outline add-series" style="width: 100%; margin-top: 0.5rem;"> | |
+ Ajouter une série | |
</button> | |
`; | |
exercisesContainer.appendChild(exerciseDiv); | |
// Ajouter les écouteurs d'événements | |
const removeBtn = exerciseDiv.querySelector('.remove-exercise'); | |
removeBtn.addEventListener('click', () => { | |
exerciseDiv.remove(); | |
}); | |
const addSeriesBtn = exerciseDiv.querySelector('.add-series'); | |
addSeriesBtn.addEventListener('click', () => { | |
addSeries(exerciseDiv.querySelector('.series-container')); | |
}); | |
// Ajouter la première série automatiquement | |
addSeries(exerciseDiv.querySelector('.series-container')); | |
} | |
// Ajouter une série à un exercice | |
function addSeries(container) { | |
const seriesId = `series-${Date.now()}`; | |
const seriesDiv = document.createElement('div'); | |
seriesDiv.className = 'series'; | |
seriesDiv.setAttribute('data-series-id', seriesId); | |
seriesDiv.innerHTML = ` | |
<div class="form-row"> | |
<div class="form-group"> | |
<label>Répétitions</label> | |
<input type="number" class="reps" min="1" placeholder="12"> | |
</div> | |
<div class="form-group"> | |
<label>Charge (kg)</label> | |
<input type="number" class="weight" min="0" step="0.5" placeholder="20"> | |
</div> | |
<div class="form-group" style="flex: 0.5;"> | |
<label> | |
<input type="checkbox" class="degressive-checkbox"> Série dégressive | |
</label> | |
</div> | |
<button class="btn btn-danger remove-series" style="align-self: flex-end; padding: 0.3rem 0.6rem; flex: 0.2;">×</button> | |
</div> | |
`; | |
container.appendChild(seriesDiv); | |
// Écouteur pour supprimer une série | |
const removeBtn = seriesDiv.querySelector('.remove-series'); | |
removeBtn.addEventListener('click', () => { | |
seriesDiv.remove(); | |
}); | |
} | |
// Sauvegarder la séance | |
function saveWorkout() { | |
// Récupérer les données de base | |
const workoutName = document.getElementById('workout-name').value.trim(); | |
const workoutDate = document.getElementById('workout-date').value; | |
const workoutDuration = parseInt(document.getElementById('workout-duration').value) || 0; | |
const satisfaction = parseInt(document.getElementById('satisfaction').value); | |
// Vérifier les données obligatoires | |
if (!workoutName) { | |
alert("Veuillez saisir un nom pour la séance"); | |
return; | |
} | |
if (!workoutDate) { | |
alert("Veuillez saisir une date"); | |
return; | |
} | |
if (workoutDuration <= 0) { | |
alert("Veuillez saisir une durée valide"); | |
return; | |
} | |
// Récupérer les exercices | |
const exercises = []; | |
const exerciseElements = exercisesContainer.querySelectorAll('.exercise'); | |
if (exerciseElements.length === 0) { | |
alert("Ajoutez au moins un exercice"); | |
return; | |
} | |
for (const exerciseEl of exerciseElements) { | |
const exerciseName = exerciseEl.querySelector('.exercise-name').value.trim(); | |
const isUnilateral = exerciseEl.querySelector('.unilateral-checkbox').checked; | |
if (!exerciseName) { | |
alert("Veuillez saisir un nom pour chaque exercice"); | |
return; | |
} | |
// Récupérer les séries | |
const series = []; | |
const seriesElements = exerciseEl.querySelectorAll('.series'); | |
if (seriesElements.length === 0) { | |
alert(`Ajoutez au moins une série à l'exercice "${exerciseName}"`); | |
return; | |
} | |
for (const seriesEl of seriesElements) { | |
const reps = parseInt(seriesEl.querySelector('.reps').value) || 0; | |
const weight = parseFloat(seriesEl.querySelector('.weight').value) || 0; | |
const isDegressive = seriesEl.querySelector('.degressive-checkbox').checked; | |
if (reps <= 0) { | |
alert(`Veuillez saisir un nombre de répétitions valide pour l'exercice "${exerciseName}"`); | |
return; | |
} | |
series.push({ | |
reps, | |
weight, | |
isDegressive | |
}); | |
} | |
exercises.push({ | |
name: exerciseName, | |
isUnilateral, | |
series | |
}); | |
} | |
// Calculer le tonnage total | |
let totalTonnage = 0; | |
exercises.forEach(exercise => { | |
exercise.series.forEach(series => { | |
// Si l'exercice est unilatéral, on multiplie par 2 le tonnage | |
const weightFactor = exercise.isUnilateral ? 2 : 1; | |
totalTonnage += series.reps * series.weight * weightFactor; | |
}); | |
}); | |
// Créer l'objet séance | |
const workout = { | |
id: currentWorkoutId || `workout-${Date.now()}`, | |
name: workoutName, | |
date: workoutDate, | |
duration: workoutDuration, | |
exercises, | |
totalTonnage, | |
satisfaction | |
}; | |
// Ajouter ou mettre à jour la séance | |
if (currentWorkoutId) { | |
// Mise à jour d'une séance existante | |
const index = workouts.findIndex(w => w.id === currentWorkoutId); | |
if (index !== -1) { | |
workouts[index] = workout; | |
} | |
} else { | |
// Nouvelle séance | |
workouts.push(workout); | |
} | |
// Sauvegarder les données | |
saveWorkouts(); | |
// Retourner à la liste des séances | |
showPage('home-page'); | |
renderWorkoutsList(); | |
} | |
// Afficher la liste des séances | |
function renderWorkoutsList() { | |
// Vider la liste | |
workoutsList.innerHTML = ''; | |
// Afficher le message si pas de séances | |
if (workouts.length === 0) { | |
emptyWorkoutMessage.classList.remove('hidden'); | |
return; | |
} | |
emptyWorkoutMessage.classList.add('hidden'); | |
// Trier les séances par date (la plus récente en premier) | |
const sortedWorkouts = [...workouts].sort((a, b) => { | |
return new Date(b.date) - new Date(a.date); | |
}); | |
// Générer le HTML pour chaque séance | |
sortedWorkouts.forEach(workout => { | |
const workoutDate = new Date(workout.date).toLocaleDateString('fr-FR'); | |
const workoutDiv = document.createElement('div'); | |
workoutDiv.className = 'card workout-card'; | |
workoutDiv.setAttribute('data-workout-id', workout.id); | |
workoutDiv.innerHTML = ` | |
<div class="workout-header"> | |
<h3>${workout.name}</h3> | |
<div class="badge">${workoutDate}</div> | |
</div> | |
<div class="workout-details"> | |
<p><strong>Durée:</strong> ${workout.duration} min</p> | |
<p><strong>Exercices:</strong> ${workout.exercises.length}</p> | |
<p><strong>Tonnage:</strong> ${workout.totalTonnage.toFixed(1)} kg</p> | |
<p><strong>Satisfaction:</strong> ${workout.satisfaction}%</p> | |
</div> | |
`; | |
// Ajouter l'écouteur pour afficher les détails | |
workoutDiv.addEventListener('click', () => { | |
displayWorkoutDetails(workout.id); | |
}); | |
workoutsList.appendChild(workoutDiv); | |
}); | |
// Mettre à jour les statistiques globales | |
updateStats(); | |
} | |
// Afficher les détails d'une séance | |
function displayWorkoutDetails(workoutId) { | |
const workout = workouts.find(w => w.id === workoutId); | |
if (!workout) return; | |
// Mettre à jour les informations de base | |
document.getElementById('detail-workout-name').textContent = workout.name; | |
document.getElementById('detail-date').textContent = new Date(workout.date).toLocaleDateString('fr-FR'); | |
document.getElementById('detail-duration').textContent = workout.duration; | |
document.getElementById('detail-tonnage').textContent = workout.totalTonnage.toFixed(1); | |
document.getElementById('detail-satisfaction').textContent = `${workout.satisfaction}%`; | |
document.getElementById('detail-exercises-count').textContent = workout.exercises.length; | |
// Afficher les exercices | |
const exercisesContainer = document.getElementById('detail-exercises-container'); | |
exercisesContainer.innerHTML = ''; | |
workout.exercises.forEach(exercise => { | |
const exerciseDiv = document.createElement('div'); | |
exerciseDiv.className = 'card'; | |
let seriesHtml = ''; | |
exercise.series.forEach(series => { | |
const degressiveLabel = series.isDegressive ? ' <span class="badge">Dégressive</span>' : ''; | |
const weightFactor = exercise.isUnilateral ? 2 : 1; | |
const seriesTonnage = series.reps * series.weight * weightFactor; | |
seriesHtml += ` | |
<div class="exercise-summary"> | |
<div class="flex-between"> | |
<span>${series.reps} répétitions × ${series.weight} kg${degressiveLabel}</span> | |
<span>${seriesTonnage.toFixed(1)} kg</span> | |
</div> | |
</div> | |
`; | |
}); | |
const unilateralLabel = exercise.isUnilateral ? ' <span class="badge">Unilatéral</span>' : ''; | |
exerciseDiv.innerHTML = ` | |
<h3>${exercise.name}${unilateralLabel}</h3> | |
<div class="series-summary"> | |
${seriesHtml} | |
</div> | |
`; | |
exercisesContainer.appendChild(exerciseDiv); | |
}); | |
// Stocker l'ID pour les éditions/suppressions | |
currentWorkoutId = workoutId; | |
// Afficher la page | |
showPage('workout-details-page'); | |
} | |
// Supprimer une séance | |
function deleteWorkout() { | |
if (!currentWorkoutId) return; | |
const confirmDelete = confirm("Êtes-vous sûr de vouloir supprimer cette séance ?"); | |
if (!confirmDelete) return | |
// Continuation du script précédent | |
if (!confirmDelete) return; | |
// Filtrer la séance à supprimer | |
workouts = workouts.filter(w => w.id !== currentWorkoutId); | |
// Sauvegarder les données | |
saveWorkouts(); | |
// Retourner à la liste des séances | |
showPage('home-page'); | |
renderWorkoutsList(); | |
} | |
// Effacer le formulaire de nouvelle séance | |
function clearNewWorkoutForm() { | |
document.getElementById('workout-name').value = ''; | |
document.getElementById('workout-duration').value = ''; | |
setTodayDate(); | |
exercisesContainer.innerHTML = ''; | |
document.getElementById('satisfaction').value = 75; | |
satisfactionValue.textContent = '75%'; | |
} | |
// Mettre à jour les statistiques | |
function updateStats() { | |
if (workouts.length === 0) { | |
document.getElementById('stats-workout-count').textContent = '0'; | |
document.getElementById('stats-avg-tonnage').textContent = '0'; | |
document.getElementById('stats-avg-satisfaction').textContent = '0%'; | |
return; | |
} | |
// Nombre total de séances | |
document.getElementById('stats-workout-count').textContent = workouts.length; | |
// Tonnage moyen | |
const totalTonnage = workouts.reduce((sum, workout) => sum + workout.totalTonnage, 0); | |
const avgTonnage = totalTonnage / workouts.length; | |
document.getElementById('stats-avg-tonnage').textContent = avgTonnage.toFixed(1); | |
// Satisfaction moyenne | |
const totalSatisfaction = workouts.reduce((sum, workout) => sum + workout.satisfaction, 0); | |
const avgSatisfaction = totalSatisfaction / workouts.length; | |
document.getElementById('stats-avg-satisfaction').textContent = `${Math.round(avgSatisfaction)}%`; | |
} | |
</script> | |
</body> | |
</html> |