Spaces:
Running
Running
Update index.html
Browse files- index.html +75 -75
index.html
CHANGED
@@ -27,9 +27,8 @@
|
|
27 |
body { background-color: var(--bg-dark); color: var(--text-light); min-height: 100vh; padding-bottom: 80px; }
|
28 |
.container { width: 100%; max-width: 800px; margin: 0 auto; padding: 1rem; }
|
29 |
header { padding: 1rem 0; text-align: center; border-bottom: 1px solid var(--border-color); margin-bottom: 1rem; display: flex; flex-direction: column; align-items: center; }
|
30 |
-
/* Style pour rendre le logo cliquable */
|
31 |
#logo-link { display: inline-block; cursor: pointer; text-decoration: none; margin-bottom: 0.5rem; }
|
32 |
-
header img#app-logo { max-width: 250px; height: auto; display: block;
|
33 |
header p { color: var(--text-secondary); font-size: 0.9rem; }
|
34 |
h1, h2, h3, h4 { font-family: var(--font-headings); font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: 0.5px; }
|
35 |
.btn { background-color: var(--accent); color: var(--text-on-accent); border: none; padding: 0.6rem 1.2rem; border-radius: 4px; cursor: pointer; font-weight: bold; font-family: var(--font-headings); text-transform: uppercase; transition: background-color 0.2s, color 0.2s; }
|
@@ -114,10 +113,41 @@
|
|
114 |
.type-trend-card li:last-child { border-bottom: none; }
|
115 |
.type-trend-card li span:first-child { color: var(--text-secondary); font-size: 0.85rem; margin-right: 1rem; }
|
116 |
.type-trend-card li strong { color: var(--accent); }
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
#accueil-page .card p { line-height: 1.6; color: var(--text-light); }
|
119 |
-
#accueil-page .card ul { list-style:
|
120 |
-
#accueil-page .card li { margin-bottom: 0.5rem; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
/* Media Queries */
|
123 |
@media (max-width: 600px) {
|
@@ -176,18 +206,18 @@
|
|
176 |
</div>
|
177 |
|
178 |
<div id="app-container">
|
179 |
-
<!--
|
180 |
<div id="accueil-page">
|
181 |
<h2>Bienvenue !</h2>
|
182 |
-
<div class="card">
|
183 |
<p>
|
184 |
-
Bienvenue sur l'application de suivi de
|
185 |
</p>
|
186 |
<p style="margin-top: 1rem;">
|
187 |
Utilisez cette application pour enregistrer vos séances d'entraînement,
|
188 |
suivre votre progression et analyser vos performances au fil du temps.
|
189 |
</p>
|
190 |
-
<ul
|
191 |
<li>Cliquez sur "Séances" pour voir vos entraînements passés ou en créer un nouveau.</li>
|
192 |
<li>Cliquez sur "Stats" pour visualiser vos statistiques globales.</li>
|
193 |
<li>Gérez vos types de séances personnalisés (Push, Pull, Legs...).</li>
|
@@ -195,10 +225,12 @@
|
|
195 |
<p style="margin-top: 1.5rem; text-align: center;">
|
196 |
Bon entraînement ! 💪
|
197 |
</p>
|
|
|
|
|
198 |
</div>
|
199 |
</div>
|
200 |
|
201 |
-
<!--
|
202 |
<div id="seances-page">
|
203 |
<div class="flex-between">
|
204 |
<h2>Mes séances</h2>
|
@@ -217,7 +249,6 @@
|
|
217 |
<div id="manage-types-page">
|
218 |
<div class="flex-between">
|
219 |
<h2>Gérer les Types</h2>
|
220 |
-
<!-- Bouton retour mène maintenant à la page des séances -->
|
221 |
<button class="btn btn-outline back-to-seances-btn">Retour</button>
|
222 |
</div>
|
223 |
<div class="card">
|
@@ -241,7 +272,6 @@
|
|
241 |
<div id="select-workout-type-page">
|
242 |
<div class="flex-between">
|
243 |
<h2>Démarrer Séance</h2>
|
244 |
-
<!-- Bouton retour mène maintenant à la page des séances -->
|
245 |
<button class="btn btn-outline back-to-seances-btn">Annuler</button>
|
246 |
</div>
|
247 |
<div class="card">
|
@@ -294,7 +324,6 @@
|
|
294 |
<div id="workout-details-page">
|
295 |
<div class="flex-between">
|
296 |
<h2>Détail Séance <span id="detail-workout-type" class="badge type-badge hidden"></span></h2>
|
297 |
-
<!-- Bouton retour mène maintenant à la page des séances -->
|
298 |
<button class="btn btn-outline back-to-seances-btn">Retour</button>
|
299 |
</div>
|
300 |
<div class="card">
|
@@ -334,13 +363,10 @@
|
|
334 |
|
335 |
</div> <!-- Fin #app-container -->
|
336 |
|
337 |
-
<!-- Bottom Navigation
|
338 |
<nav class="nav-bottom">
|
339 |
-
<!-- NOUVEAU lien Accueil -->
|
340 |
<a href="#" class="nav-item" data-page="accueil-page"> <div class="nav-icon">🏠</div> <div>Accueil</div> </a>
|
341 |
-
<!-- Lien Séances (anciennement Home) -->
|
342 |
<a href="#" class="nav-item" data-page="seances-page"> <div class="nav-icon">📋</div> <div>Séances</div> </a>
|
343 |
-
<!-- Lien Stats (inchangé) -->
|
344 |
<a href="#" class="nav-item" data-page="stats-page"> <div class="nav-icon">📊</div> <div>Stats</div> </a>
|
345 |
</nav>
|
346 |
|
@@ -369,7 +395,7 @@
|
|
369 |
const authActionButton = document.getElementById('auth-action-btn');
|
370 |
const authSwitchLink = document.getElementById('auth-switch-link');
|
371 |
const forgotPasswordLink = document.getElementById('forgot-password-link');
|
372 |
-
const logoLink = document.getElementById('logo-link');
|
373 |
const authTitle = document.getElementById('auth-title');
|
374 |
const authSwitchText = document.getElementById('auth-switch-text');
|
375 |
const loginMessage = document.getElementById('login-message');
|
@@ -384,7 +410,7 @@
|
|
384 |
const addExerciseBtn = document.getElementById('add-exercise-btn');
|
385 |
const exercisesContainer = document.getElementById('exercises-container');
|
386 |
const workoutsList = document.getElementById('workouts-list');
|
387 |
-
const backToSeancesBtns = document.querySelectorAll('.back-to-seances-btn');
|
388 |
const deleteWorkoutBtn = document.getElementById('delete-workout-btn');
|
389 |
const satisfactionRange = document.getElementById('satisfaction');
|
390 |
const satisfactionValue = document.querySelector('.satisfaction-value');
|
@@ -413,7 +439,6 @@
|
|
413 |
const typeTrendsContainer = document.getElementById('type-trends-container');
|
414 |
const noTrendsMessage = document.getElementById('no-trends-message');
|
415 |
const trendsSpinner = document.getElementById('trends-spinner');
|
416 |
-
// On garde une référence à la page d'accueil et aux séances pour clarté
|
417 |
const accueilPage = document.getElementById('accueil-page');
|
418 |
const seancesPage = document.getElementById('seances-page');
|
419 |
|
@@ -421,41 +446,29 @@
|
|
421 |
// --- DÉFINITION DES FONCTIONS ---
|
422 |
// ===========================================
|
423 |
|
424 |
-
|
425 |
-
function
|
426 |
-
|
427 |
function initAuthListener() { if (!auth) return; auth.onAuthStateChanged(user => { console.log("Auth state changed:", user ? user.uid : 'null'); currentFirebaseUser = user; if (user) { showApp(); } else { workouts = []; userWorkoutTypes = []; showLoginPage(); } }); }
|
428 |
-
function showLoginPage() {
|
429 |
-
|
430 |
-
function
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
setTodayDate();
|
437 |
-
loadWorkouts(); // Charger les données en arrière plan
|
438 |
-
loadWorkoutTypes();
|
439 |
-
showPage('accueil-page'); // **MODIFIÉ** : Démarrer sur la page d'accueil
|
440 |
-
}
|
441 |
-
|
442 |
-
function handleAuthAction(event) { /* ... inchangé ... */ if (!auth || !authEmailInput || !authPasswordInput || !authActionButton) return; event.preventDefault(); const email = authEmailInput.value; const password = authPasswordInput.value; clearMessage(); if (!email || !password) { showMessage('Email et Mot de passe requis.'); return; } authActionButton.disabled = true; authActionButton.textContent = 'Chargement...'; if (isLoginMode) { auth.signInWithEmailAndPassword(email, password).catch(handleAuthError).finally(() => { authActionButton.disabled = false; authActionButton.textContent = 'Se Connecter'; }); } else { auth.createUserWithEmailAndPassword(email, password).catch(handleAuthError).finally(() => { authActionButton.disabled = false; authActionButton.textContent = 'S\'inscrire'; }); } }
|
443 |
-
function handlePasswordReset(event) { /* ... inchangé ... */ event.preventDefault(); if (!auth) { alert("Service d'authentification non disponible."); return; } clearMessage(); const email = prompt("Veuillez entrer votre adresse email pour recevoir le lien de réinitialisation :"); if (!email) { showMessage("Saisie de l'email annulée.", true); return; } console.log("Tentative d'envoi de l'email de réinitialisation à :", email); auth.sendPasswordResetEmail(email).then(() => { console.log("Email de réinitialisation envoyé."); showMessage("Si un compte existe pour " + email + ", un email de réinitialisation a été envoyé.", false); }).catch((error) => { console.error("Erreur sendPasswordResetEmail:", error); handleAuthError(error); }); }
|
444 |
-
function handleLogout() { /* ... inchangé ... */ if (!auth) return; console.log("Déconnexion..."); auth.signOut().catch(error => { console.error("Logout Error:", error); alert("Erreur lors de la déconnexion."); }); }
|
445 |
-
function authSwitchMode() { /* ... inchangé ... */ isLoginMode = !isLoginMode; clearMessage(); if (authEmailInput) authEmailInput.value = ''; if (authPasswordInput) authPasswordInput.value = ''; if (authTitle) authTitle.textContent = isLoginMode ? 'Connexion' : 'Inscription'; if (authActionButton) authActionButton.textContent = isLoginMode ? 'Se Connecter' : 'S\'inscrire'; if (authSwitchText) authSwitchText.textContent = isLoginMode ? 'Pas encore de compte ?' : 'Déjà un compte ?'; if (authSwitchLink) authSwitchLink.textContent = isLoginMode ? 'Inscrivez-vous ici' : 'Connectez-vous ici'; if (authEmailInput) authEmailInput.focus(); }
|
446 |
-
function handleAuthError(error) { /* ... inchangé ... */ console.error("Erreur Auth Firebase:", error.code, error.message); showMessage(getAuthErrorMessage(error), true); }
|
447 |
-
function getAuthErrorMessage(error) { /* ... inchangé ... */ switch (error.code) { case 'auth/invalid-email': return 'Format d\'email invalide.'; case 'auth/user-disabled': return 'Ce compte utilisateur a été désactivé.'; case 'auth/user-not-found': return 'Aucun utilisateur trouvé avec cet email.'; case 'auth/wrong-password': return 'Mot de passe incorrect.'; case 'auth/email-already-in-use': return 'Cet email est déjà utilisé par un autre compte.'; case 'auth/weak-password': return 'Le mot de passe doit contenir au moins 6 caractères.'; case 'auth/operation-not-allowed': return 'Méthode de connexion non activée.'; case 'auth/missing-password': return 'Mot de passe manquant.'; case 'auth/missing-email': return 'Adresse email manquante.'; default: console.error("Unhandled Auth Error Code:", error.code); return `Erreur (${error.code}). Veuillez réessayer.`; } }
|
448 |
function loadWorkoutTypes() { /* ... inchangé ... */ if (!currentFirebaseUser || !db || !typesSpinner) return; const userId = currentFirebaseUser.uid; console.log("Chargement types pour", userId); userWorkoutTypes = []; typesSpinner.classList.remove('hidden'); db.collection('workoutTypes').where('userId', '==', userId).orderBy('name').get().then(snapshot => { userWorkoutTypes = []; snapshot.forEach(doc => { userWorkoutTypes.push({ id: doc.id, ...doc.data() }); }); console.log("Types chargés:", userWorkoutTypes); renderWorkoutTypesList(); populateWorkoutTypeSelector(); }).catch(handleFirestoreError).finally(() => { typesSpinner.classList.add('hidden'); }); }
|
449 |
function renderWorkoutTypesList() { /* ... inchangé ... */ if (!workoutTypesList || !emptyTypesMessage) return; workoutTypesList.innerHTML = ''; if (userWorkoutTypes.length === 0) { emptyTypesMessage.classList.remove('hidden'); } else { emptyTypesMessage.classList.add('hidden'); userWorkoutTypes.forEach(type => { const li = document.createElement('li'); li.textContent = type.name; workoutTypesList.appendChild(li); }); } }
|
450 |
function handleAddWorkoutType(event) { /* ... inchangé ... */ event.preventDefault(); if (!currentFirebaseUser || !newTypeNameInput || !db || !addTypeError || !addTypeForm) return; const typeName = newTypeNameInput.value.trim(); addTypeError.textContent = ''; addTypeError.style.display = 'none'; if (!typeName) { addTypeError.textContent = "Le nom du type ne peut pas être vide."; addTypeError.style.display = 'block'; return; } if (userWorkoutTypes.some(t => t.name.toLowerCase() === typeName.toLowerCase())) { addTypeError.textContent = "Ce type de séance existe déjà."; addTypeError.style.display = 'block'; return; } console.log("Ajout type:", typeName); const typeData = { userId: currentFirebaseUser.uid, name: typeName, createdAt: firebase.firestore.FieldValue.serverTimestamp() }; const addBtn = addTypeForm.querySelector('button'); if (addBtn) { addBtn.disabled = true; addBtn.textContent = '...'; } db.collection('workoutTypes').add(typeData).then(() => { console.log("Type ajouté avec succès"); newTypeNameInput.value = ''; loadWorkoutTypes(); }).catch(handleFirestoreError).finally(() => { if (addBtn) { addBtn.disabled = false; addBtn.textContent = 'Ajouter'; } }); }
|
451 |
function populateWorkoutTypeSelector() { /* ... inchangé ... */ if (!selectWorkoutTypeDropdown) return; selectWorkoutTypeDropdown.innerHTML = '<option value="">-- Sélectionner Type --</option>'; userWorkoutTypes.forEach(type => { const option = document.createElement('option'); option.value = type.name; option.textContent = type.name; selectWorkoutTypeDropdown.appendChild(option); }); updateStartStructuredBtnState(); }
|
452 |
function updateStartStructuredBtnState() { /* ... inchangé ... */ if (!selectWorkoutTypeDropdown || !startStructuredWorkoutBtn) return; startStructuredWorkoutBtn.disabled = !selectWorkoutTypeDropdown.value; }
|
453 |
-
function loadWorkouts() { /* ... inchangé ... */ if (!currentFirebaseUser || !db || !spinner || !emptyWorkoutMessage || !workoutsList) { console.warn("Cannot load workouts
|
454 |
-
function saveWorkout() { /* ... inchangé ... */ if (!currentFirebaseUser || !db || !exercisesContainer || !saveWorkoutBtn) { alert("Erreur: Impossible de sauvegarder."); return; } const userId = currentFirebaseUser.uid; workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); const workoutNameInput = document.getElementById('workout-name'); const workoutName = workoutNameInput ? workoutNameInput.value.trim() : ''; const workoutDate = workoutDateInput ? workoutDateInput.value : ''; const workoutDurationInput = document.getElementById('workout-duration'); const workoutDuration = workoutDurationInput ? parseInt(workoutDurationInput.value) || 0 : 0; const satisfaction = satisfactionRange ? parseInt(satisfactionRange.value) : 75; if (!selectedWorkoutTypeName) { alert("Erreur interne: Type de séance manquant."); showPage('seances-page'); return; } if (!workoutDate) { alert("Veuillez sélectionner une date."); if(workoutDateInput) workoutDateInput.focus(); return; } if (workoutDuration <= 0) { alert("Veuillez entrer une durée valide
|
455 |
-
function deleteWorkout() { /* ... inchangé ... */ if (!currentFirebaseUser || !currentWorkoutId || !db || !deleteWorkoutBtn) return; const workoutToDelete = workouts.find(w => w && w.id === currentWorkoutId); if (!workoutToDelete) { console.error("Workout to delete not found locally."); return; } const confirmMsg = `Supprimer la séance "${workoutToDelete.name || 'Sans nom'}" du ${new Date(workoutToDelete.date).toLocaleDateString('fr-FR')} ?`; if (!confirm(confirmMsg)) return; console.log("Suppression séance:", currentWorkoutId); deleteWorkoutBtn.disabled = true; deleteWorkoutBtn.textContent = 'Suppression...'; db.collection('workouts').doc(currentWorkoutId).delete().then(() => { console.log("Séance supprimée avec succès:", currentWorkoutId); currentWorkoutId = null; showPage('seances-page'); loadWorkouts(); }).catch(handleFirestoreError).finally(() => { deleteWorkoutBtn.disabled = false; deleteWorkoutBtn.textContent = 'Supprimer Séance'; }); }
|
456 |
function setTodayDate() { /* ... inchangé ... */ if (workoutDateInput) { try { const today = new Date(); const offset = today.getTimezoneOffset(); const localDate = new Date(today.getTime() - (offset*60*1000)); workoutDateInput.value = localDate.toISOString().split('T')[0]; } catch (e) { console.error("Erreur setTodayDate:", e); try { workoutDateInput.value = new Date().toISOString().split('T')[0]; } catch {} } } }
|
457 |
|
458 |
-
function showPage(pageId) {
|
459 |
if (!appContainer) { console.error("App container not found!"); return; }
|
460 |
console.log(`Affichage page: ${pageId}`);
|
461 |
const pages = appContainer.querySelectorAll(':scope > div[id$="-page"]');
|
@@ -465,41 +478,28 @@
|
|
465 |
if (pageToShow) {
|
466 |
pageToShow.classList.add('active');
|
467 |
window.scrollTo(0, 0);
|
468 |
-
|
469 |
-
|
470 |
-
if (pageId === '
|
471 |
-
if (!selectedWorkoutTypeName) {
|
472 |
-
console.warn("Accès new-workout-page sans type.");
|
473 |
-
alert("Veuillez sélectionner un type.");
|
474 |
-
showPage('select-workout-type-page'); return;
|
475 |
-
}
|
476 |
-
renderActiveExerciseForm(); updateWorkoutTypeIndicator();
|
477 |
-
} else if (pageId === 'manage-types-page') loadWorkoutTypes();
|
478 |
else if (pageId === 'select-workout-type-page') populateWorkoutTypeSelector();
|
479 |
else if (pageId === 'stats-page') updateStats();
|
480 |
-
else if (pageId === 'workout-details-page' && !currentWorkoutId) {
|
481 |
-
console.warn("Accès détails sans ID.");
|
482 |
-
alert("Séance non spécifiée.");
|
483 |
-
showPage('seances-page'); return;
|
484 |
-
}
|
485 |
-
// No specific action needed for 'accueil-page' or 'seances-page' here
|
486 |
-
|
487 |
} else {
|
488 |
console.error(`Page ID "${pageId}" non trouvée. Affichage accueil.`);
|
489 |
-
if (accueilPage) accueilPage.classList.add('active'); //
|
490 |
-
pageId = 'accueil-page';
|
491 |
}
|
492 |
|
493 |
-
//
|
494 |
navItems.forEach(item => item.classList.remove('active'));
|
495 |
-
//
|
496 |
const activeNavItem = document.querySelector(`.nav-item[data-page="${pageId}"]`);
|
497 |
if (activeNavItem) {
|
498 |
activeNavItem.classList.add('active');
|
499 |
} else {
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
}
|
504 |
}
|
505 |
|
@@ -517,6 +517,7 @@
|
|
517 |
function renderTypeTrends(trends) { /* ... inchangé ... */ if (!typeTrendsContainer || !noTrendsMessage || !trendsSpinner) { console.error("Cannot render trends: Missing DOM elements."); return;} trendsSpinner.classList.add('hidden'); typeTrendsContainer.innerHTML = ''; const trendTypes = Object.keys(trends); if (trendTypes.length === 0) { noTrendsMessage.classList.remove('hidden'); } else { noTrendsMessage.classList.add('hidden'); trendTypes.sort().forEach(typeName => { const typeData = trends[typeName]; if (!typeData || typeData.length === 0) return; const card = document.createElement('div'); card.className = 'card type-trend-card'; let listItems = ''; typeData.forEach(session => { const formattedDate = session.date ? new Date(session.date).toLocaleDateString('fr-FR', { day: '2-digit', month: 'short' }) : '??'; const tonnageText = (session.tonnage !== undefined && session.tonnage !== null) ? `${session.tonnage.toFixed(1)} kg` : 'N/A'; listItems += `<li><span>${formattedDate}</span> <strong>${tonnageText}</strong></li>`; }); card.innerHTML = `<h4>${typeName} (3 Dernières)</h4><ul>${listItems}</ul>`; typeTrendsContainer.appendChild(card); }); } }
|
518 |
function handleFirestoreError(error) { /* ... inchangé ... */ console.error("Erreur Firestore:", error.code, error.message); alert(`Erreur de base de données: ${error.message}`); }
|
519 |
|
|
|
520 |
// --- ÉCOUTEURS D'ÉVÉNEMENTS ---
|
521 |
function initEventListeners() {
|
522 |
console.log("initEventListeners: Attachement...");
|
@@ -527,7 +528,7 @@
|
|
527 |
if (authSwitchLink) authSwitchLink.addEventListener('click', authSwitchMode); else console.error("!authSwitchLink");
|
528 |
if (forgotPasswordLink) forgotPasswordLink.addEventListener('click', handlePasswordReset); else console.error("!forgotPasswordLink");
|
529 |
if (logoutBtn) logoutBtn.addEventListener('click', handleLogout); else console.error("!logoutBtn");
|
530 |
-
// Nav
|
531 |
navItems.forEach((item) => { if (item) item.addEventListener('click', (e) => { e.preventDefault(); const targetPageId = item.getAttribute('data-page'); if (!currentFirebaseUser && targetPageId !== 'login-page') { showLoginPage(); return; } if (targetPageId) showPage(targetPageId); }); else console.error(`!navItem`); });
|
532 |
// Workout List Actions
|
533 |
if (newWorkoutBtn) newWorkoutBtn.addEventListener('click', () => { if (!currentFirebaseUser) return; showPage('select-workout-type-page'); }); else console.error("!newWorkoutBtn");
|
@@ -539,10 +540,9 @@
|
|
539 |
if (startStructuredWorkoutBtn) startStructuredWorkoutBtn.addEventListener('click', () => { if (selectWorkoutTypeDropdown) { const type = selectWorkoutTypeDropdown.value; if (type) { clearNewWorkoutForm(type); showPage('new-workout-page'); } else { alert("Veuillez sélectionner un type de séance."); } } }); else console.error("!startStructuredWorkoutBtn");
|
540 |
if (startFreeWorkoutBtn) startFreeWorkoutBtn.addEventListener('click', () => { clearNewWorkoutForm("Libre"); showPage('new-workout-page'); }); else console.error("!startFreeWorkoutBtn");
|
541 |
// General Nav (Retour) -> Va maintenant à seances-page
|
542 |
-
backToSeancesBtns.forEach(btn => { if (btn) btn.addEventListener('click', () => showPage('seances-page')); else console.error("!backToSeancesBtn"); });
|
543 |
// New Workout Actions
|
544 |
-
if (cancelNewWorkoutBtn) cancelNewWorkoutBtn.addEventListener('click', () => { if (confirm("Annuler cette séance ? Les données non enregistrées seront perdues.")) showPage('seances-page'); });
|
545 |
-
else console.error("!cancelNewWorkoutBtn");
|
546 |
if (saveWorkoutBtn) saveWorkoutBtn.addEventListener('click', saveWorkout); else console.error("!saveWorkoutBtn");
|
547 |
if (addExerciseBtn) addExerciseBtn.addEventListener('click', handleAddNewExercise); else console.error("!addExerciseBtn");
|
548 |
// Exercise Nav
|
|
|
27 |
body { background-color: var(--bg-dark); color: var(--text-light); min-height: 100vh; padding-bottom: 80px; }
|
28 |
.container { width: 100%; max-width: 800px; margin: 0 auto; padding: 1rem; }
|
29 |
header { padding: 1rem 0; text-align: center; border-bottom: 1px solid var(--border-color); margin-bottom: 1rem; display: flex; flex-direction: column; align-items: center; }
|
|
|
30 |
#logo-link { display: inline-block; cursor: pointer; text-decoration: none; margin-bottom: 0.5rem; }
|
31 |
+
header img#app-logo { max-width: 250px; height: auto; display: block; }
|
32 |
header p { color: var(--text-secondary); font-size: 0.9rem; }
|
33 |
h1, h2, h3, h4 { font-family: var(--font-headings); font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: 0.5px; }
|
34 |
.btn { background-color: var(--accent); color: var(--text-on-accent); border: none; padding: 0.6rem 1.2rem; border-radius: 4px; cursor: pointer; font-weight: bold; font-family: var(--font-headings); text-transform: uppercase; transition: background-color 0.2s, color 0.2s; }
|
|
|
113 |
.type-trend-card li:last-child { border-bottom: none; }
|
114 |
.type-trend-card li span:first-child { color: var(--text-secondary); font-size: 0.85rem; margin-right: 1rem; }
|
115 |
.type-trend-card li strong { color: var(--accent); }
|
116 |
+
|
117 |
+
/* === NOUVEAUX STYLES === */
|
118 |
+
/* Style page d'accueil */
|
119 |
+
#accueil-page .card {
|
120 |
+
border: 2px solid var(--accent); /* Ajout bordure jaune */
|
121 |
+
background-color: #282828; /* Fond légèrement différent pour se démarquer */
|
122 |
+
}
|
123 |
#accueil-page .card p { line-height: 1.6; color: var(--text-light); }
|
124 |
+
#accueil-page .card ul { list-style: none; /* Retrait puces */ padding-left: 0; margin-top: 1rem; color: var(--text-light); }
|
125 |
+
#accueil-page .card li { margin-bottom: 0.6rem; padding-left: 1.5rem; position: relative; }
|
126 |
+
/* Ajout d'une puce personnalisée jaune */
|
127 |
+
#accueil-page .card li::before {
|
128 |
+
content: '✓'; /* Ou un autre symbole comme •, → */
|
129 |
+
color: var(--accent);
|
130 |
+
font-weight: bold;
|
131 |
+
position: absolute;
|
132 |
+
left: 0;
|
133 |
+
top: 0;
|
134 |
+
}
|
135 |
+
/* Style flèche guide */
|
136 |
+
.guide-arrow {
|
137 |
+
text-align: center;
|
138 |
+
margin-top: 1.5rem;
|
139 |
+
font-size: 2.5rem; /* Taille de la flèche */
|
140 |
+
color: var(--accent);
|
141 |
+
animation: bounce 2s infinite; /* Ajoute une petite animation */
|
142 |
+
}
|
143 |
+
/* Animation pour la flèche */
|
144 |
+
@keyframes bounce {
|
145 |
+
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
|
146 |
+
40% { transform: translateY(-10px); }
|
147 |
+
60% { transform: translateY(-5px); }
|
148 |
+
}
|
149 |
+
/* === FIN NOUVEAUX STYLES === */
|
150 |
+
|
151 |
|
152 |
/* Media Queries */
|
153 |
@media (max-width: 600px) {
|
|
|
206 |
</div>
|
207 |
|
208 |
<div id="app-container">
|
209 |
+
<!-- Accueil Page MISE A JOUR -->
|
210 |
<div id="accueil-page">
|
211 |
<h2>Bienvenue !</h2>
|
212 |
+
<div class="card"> <!-- La bordure jaune sera appliquée par le CSS -->
|
213 |
<p>
|
214 |
+
Bienvenue sur l'application de suivi de <strong>Cocktail Fitness</strong> !
|
215 |
</p>
|
216 |
<p style="margin-top: 1rem;">
|
217 |
Utilisez cette application pour enregistrer vos séances d'entraînement,
|
218 |
suivre votre progression et analyser vos performances au fil du temps.
|
219 |
</p>
|
220 |
+
<ul>
|
221 |
<li>Cliquez sur "Séances" pour voir vos entraînements passés ou en créer un nouveau.</li>
|
222 |
<li>Cliquez sur "Stats" pour visualiser vos statistiques globales.</li>
|
223 |
<li>Gérez vos types de séances personnalisés (Push, Pull, Legs...).</li>
|
|
|
225 |
<p style="margin-top: 1.5rem; text-align: center;">
|
226 |
Bon entraînement ! 💪
|
227 |
</p>
|
228 |
+
<!-- Flèche guide ajoutée ici -->
|
229 |
+
<div class="guide-arrow">↓</div>
|
230 |
</div>
|
231 |
</div>
|
232 |
|
233 |
+
<!-- Séances Page -->
|
234 |
<div id="seances-page">
|
235 |
<div class="flex-between">
|
236 |
<h2>Mes séances</h2>
|
|
|
249 |
<div id="manage-types-page">
|
250 |
<div class="flex-between">
|
251 |
<h2>Gérer les Types</h2>
|
|
|
252 |
<button class="btn btn-outline back-to-seances-btn">Retour</button>
|
253 |
</div>
|
254 |
<div class="card">
|
|
|
272 |
<div id="select-workout-type-page">
|
273 |
<div class="flex-between">
|
274 |
<h2>Démarrer Séance</h2>
|
|
|
275 |
<button class="btn btn-outline back-to-seances-btn">Annuler</button>
|
276 |
</div>
|
277 |
<div class="card">
|
|
|
324 |
<div id="workout-details-page">
|
325 |
<div class="flex-between">
|
326 |
<h2>Détail Séance <span id="detail-workout-type" class="badge type-badge hidden"></span></h2>
|
|
|
327 |
<button class="btn btn-outline back-to-seances-btn">Retour</button>
|
328 |
</div>
|
329 |
<div class="card">
|
|
|
363 |
|
364 |
</div> <!-- Fin #app-container -->
|
365 |
|
366 |
+
<!-- Bottom Navigation -->
|
367 |
<nav class="nav-bottom">
|
|
|
368 |
<a href="#" class="nav-item" data-page="accueil-page"> <div class="nav-icon">🏠</div> <div>Accueil</div> </a>
|
|
|
369 |
<a href="#" class="nav-item" data-page="seances-page"> <div class="nav-icon">📋</div> <div>Séances</div> </a>
|
|
|
370 |
<a href="#" class="nav-item" data-page="stats-page"> <div class="nav-icon">📊</div> <div>Stats</div> </a>
|
371 |
</nav>
|
372 |
|
|
|
395 |
const authActionButton = document.getElementById('auth-action-btn');
|
396 |
const authSwitchLink = document.getElementById('auth-switch-link');
|
397 |
const forgotPasswordLink = document.getElementById('forgot-password-link');
|
398 |
+
const logoLink = document.getElementById('logo-link');
|
399 |
const authTitle = document.getElementById('auth-title');
|
400 |
const authSwitchText = document.getElementById('auth-switch-text');
|
401 |
const loginMessage = document.getElementById('login-message');
|
|
|
410 |
const addExerciseBtn = document.getElementById('add-exercise-btn');
|
411 |
const exercisesContainer = document.getElementById('exercises-container');
|
412 |
const workoutsList = document.getElementById('workouts-list');
|
413 |
+
const backToSeancesBtns = document.querySelectorAll('.back-to-seances-btn');
|
414 |
const deleteWorkoutBtn = document.getElementById('delete-workout-btn');
|
415 |
const satisfactionRange = document.getElementById('satisfaction');
|
416 |
const satisfactionValue = document.querySelector('.satisfaction-value');
|
|
|
439 |
const typeTrendsContainer = document.getElementById('type-trends-container');
|
440 |
const noTrendsMessage = document.getElementById('no-trends-message');
|
441 |
const trendsSpinner = document.getElementById('trends-spinner');
|
|
|
442 |
const accueilPage = document.getElementById('accueil-page');
|
443 |
const seancesPage = document.getElementById('seances-page');
|
444 |
|
|
|
446 |
// --- DÉFINITION DES FONCTIONS ---
|
447 |
// ===========================================
|
448 |
|
449 |
+
// (Les définitions des fonctions JavaScript sont ici - identiques à la version précédente, sauf mention contraire)
|
450 |
+
function showMessage(message, isError = true) { if (loginMessage) { loginMessage.textContent = message; loginMessage.className = isError ? 'error' : 'success'; loginMessage.style.display = 'block'; } }
|
451 |
+
function clearMessage() { if (loginMessage) { loginMessage.textContent = ''; loginMessage.style.display = 'none'; } }
|
452 |
function initAuthListener() { if (!auth) return; auth.onAuthStateChanged(user => { console.log("Auth state changed:", user ? user.uid : 'null'); currentFirebaseUser = user; if (user) { showApp(); } else { workouts = []; userWorkoutTypes = []; showLoginPage(); } }); }
|
453 |
+
function showLoginPage() { if(loginPage) loginPage.style.display = 'block'; if(mainAppContent) mainAppContent.style.display = 'none'; isLoginMode = true; authSwitchMode(); }
|
454 |
+
function showApp() { if (!currentFirebaseUser || !mainAppContent) { showLoginPage(); return; } console.log("Affichage App for user:", currentFirebaseUser.email); if(loginPage) loginPage.style.display = 'none'; mainAppContent.style.display = 'block'; if(currentUserDisplay) currentUserDisplay.textContent = currentFirebaseUser.email; setTodayDate(); loadWorkouts(); loadWorkoutTypes(); showPage('accueil-page'); } // Démarre sur accueil
|
455 |
+
function handleAuthAction(event) { if (!auth || !authEmailInput || !authPasswordInput || !authActionButton) return; event.preventDefault(); const email = authEmailInput.value; const password = authPasswordInput.value; clearMessage(); if (!email || !password) { showMessage('Email et Mot de passe requis.'); return; } authActionButton.disabled = true; authActionButton.textContent = 'Chargement...'; if (isLoginMode) { auth.signInWithEmailAndPassword(email, password).catch(handleAuthError).finally(() => { authActionButton.disabled = false; authActionButton.textContent = 'Se Connecter'; }); } else { auth.createUserWithEmailAndPassword(email, password).catch(handleAuthError).finally(() => { authActionButton.disabled = false; authActionButton.textContent = 'S\'inscrire'; }); } } // Ne pas switcher après inscription réussie
|
456 |
+
function handlePasswordReset(event) { event.preventDefault(); if (!auth) { alert("Service d'authentification non disponible."); return; } clearMessage(); const email = prompt("Veuillez entrer votre adresse email pour recevoir le lien de réinitialisation :"); if (!email) { showMessage("Saisie de l'email annulée.", true); return; } console.log("Tentative d'envoi de l'email de réinitialisation à :", email); auth.sendPasswordResetEmail(email).then(() => { console.log("Email de réinitialisation envoyé."); showMessage("Si un compte existe pour " + email + ", un email de réinitialisation a été envoyé.", false); }).catch((error) => { console.error("Erreur sendPasswordResetEmail:", error); handleAuthError(error); }); }
|
457 |
+
function handleLogout() { if (!auth) return; console.log("Déconnexion..."); auth.signOut().catch(error => { console.error("Logout Error:", error); alert("Erreur lors de la déconnexion."); }); }
|
458 |
+
function authSwitchMode() { isLoginMode = !isLoginMode; clearMessage(); if (authEmailInput) authEmailInput.value = ''; if (authPasswordInput) authPasswordInput.value = ''; if (authTitle) authTitle.textContent = isLoginMode ? 'Connexion' : 'Inscription'; if (authActionButton) authActionButton.textContent = isLoginMode ? 'Se Connecter' : 'S\'inscrire'; if (authSwitchText) authSwitchText.textContent = isLoginMode ? 'Pas encore de compte ?' : 'Déjà un compte ?'; if (authSwitchLink) authSwitchLink.textContent = isLoginMode ? 'Inscrivez-vous ici' : 'Connectez-vous ici'; if (authEmailInput) authEmailInput.focus(); }
|
459 |
+
function handleAuthError(error) { console.error("Erreur Auth Firebase:", error.code, error.message); showMessage(getAuthErrorMessage(error), true); }
|
460 |
+
function getAuthErrorMessage(error) { switch (error.code) { case 'auth/invalid-email': return 'Format d\'email invalide.'; case 'auth/user-disabled': return 'Ce compte utilisateur a été désactivé.'; case 'auth/user-not-found': return 'Aucun utilisateur trouvé avec cet email.'; case 'auth/wrong-password': return 'Mot de passe incorrect.'; case 'auth/email-already-in-use': return 'Cet email est déjà utilisé.'; case 'auth/weak-password': return 'Le mot de passe doit faire au moins 6 caractères.'; case 'auth/operation-not-allowed': return 'Méthode de connexion non activée.'; case 'auth/missing-password': return 'Mot de passe manquant.'; case 'auth/missing-email': return 'Adresse email manquante.'; default: console.error("Unhandled Auth Error Code:", error.code); return `Erreur (${error.code}). Veuillez réessayer.`; } }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
function loadWorkoutTypes() { /* ... inchangé ... */ if (!currentFirebaseUser || !db || !typesSpinner) return; const userId = currentFirebaseUser.uid; console.log("Chargement types pour", userId); userWorkoutTypes = []; typesSpinner.classList.remove('hidden'); db.collection('workoutTypes').where('userId', '==', userId).orderBy('name').get().then(snapshot => { userWorkoutTypes = []; snapshot.forEach(doc => { userWorkoutTypes.push({ id: doc.id, ...doc.data() }); }); console.log("Types chargés:", userWorkoutTypes); renderWorkoutTypesList(); populateWorkoutTypeSelector(); }).catch(handleFirestoreError).finally(() => { typesSpinner.classList.add('hidden'); }); }
|
462 |
function renderWorkoutTypesList() { /* ... inchangé ... */ if (!workoutTypesList || !emptyTypesMessage) return; workoutTypesList.innerHTML = ''; if (userWorkoutTypes.length === 0) { emptyTypesMessage.classList.remove('hidden'); } else { emptyTypesMessage.classList.add('hidden'); userWorkoutTypes.forEach(type => { const li = document.createElement('li'); li.textContent = type.name; workoutTypesList.appendChild(li); }); } }
|
463 |
function handleAddWorkoutType(event) { /* ... inchangé ... */ event.preventDefault(); if (!currentFirebaseUser || !newTypeNameInput || !db || !addTypeError || !addTypeForm) return; const typeName = newTypeNameInput.value.trim(); addTypeError.textContent = ''; addTypeError.style.display = 'none'; if (!typeName) { addTypeError.textContent = "Le nom du type ne peut pas être vide."; addTypeError.style.display = 'block'; return; } if (userWorkoutTypes.some(t => t.name.toLowerCase() === typeName.toLowerCase())) { addTypeError.textContent = "Ce type de séance existe déjà."; addTypeError.style.display = 'block'; return; } console.log("Ajout type:", typeName); const typeData = { userId: currentFirebaseUser.uid, name: typeName, createdAt: firebase.firestore.FieldValue.serverTimestamp() }; const addBtn = addTypeForm.querySelector('button'); if (addBtn) { addBtn.disabled = true; addBtn.textContent = '...'; } db.collection('workoutTypes').add(typeData).then(() => { console.log("Type ajouté avec succès"); newTypeNameInput.value = ''; loadWorkoutTypes(); }).catch(handleFirestoreError).finally(() => { if (addBtn) { addBtn.disabled = false; addBtn.textContent = 'Ajouter'; } }); }
|
464 |
function populateWorkoutTypeSelector() { /* ... inchangé ... */ if (!selectWorkoutTypeDropdown) return; selectWorkoutTypeDropdown.innerHTML = '<option value="">-- Sélectionner Type --</option>'; userWorkoutTypes.forEach(type => { const option = document.createElement('option'); option.value = type.name; option.textContent = type.name; selectWorkoutTypeDropdown.appendChild(option); }); updateStartStructuredBtnState(); }
|
465 |
function updateStartStructuredBtnState() { /* ... inchangé ... */ if (!selectWorkoutTypeDropdown || !startStructuredWorkoutBtn) return; startStructuredWorkoutBtn.disabled = !selectWorkoutTypeDropdown.value; }
|
466 |
+
function loadWorkouts() { /* ... inchangé ... */ if (!currentFirebaseUser || !db || !spinner || !emptyWorkoutMessage || !workoutsList) { console.warn("Cannot load workouts"); if(workoutsList) workoutsList.innerHTML = ''; if(emptyWorkoutMessage) emptyWorkoutMessage.classList.remove('hidden'); workouts = []; updateStats(); return; } const userId = currentFirebaseUser.uid; console.log(`Chargement séances pour ${userId}...`); spinner.classList.remove('hidden'); emptyWorkoutMessage.classList.add('hidden'); workoutsList.innerHTML = ''; db.collection('workouts').where('userId', '==', userId).orderBy('date', 'desc').get().then((querySnapshot) => { workouts = []; console.log(`${querySnapshot.size} séances trouvées.`); querySnapshot.forEach((doc) => { const workoutData = doc.data(); workoutData.id = doc.id; workouts.push(workoutData); }); renderWorkoutsList(); updateStats(); }).catch(handleFirestoreError).finally(() => { spinner.classList.add('hidden'); if (workouts.length === 0) { emptyWorkoutMessage.classList.remove('hidden'); } }); }
|
467 |
+
function saveWorkout() { /* ... inchangé - mais redirection vers seances-page ... */ if (!currentFirebaseUser || !db || !exercisesContainer || !saveWorkoutBtn) { alert("Erreur: Impossible de sauvegarder."); return; } const userId = currentFirebaseUser.uid; workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); const workoutNameInput = document.getElementById('workout-name'); const workoutName = workoutNameInput ? workoutNameInput.value.trim() : ''; const workoutDate = workoutDateInput ? workoutDateInput.value : ''; const workoutDurationInput = document.getElementById('workout-duration'); const workoutDuration = workoutDurationInput ? parseInt(workoutDurationInput.value) || 0 : 0; const satisfaction = satisfactionRange ? parseInt(satisfactionRange.value) : 75; if (!selectedWorkoutTypeName) { alert("Erreur interne: Type de séance manquant."); showPage('seances-page'); return; } if (!workoutDate) { alert("Veuillez sélectionner une date."); if(workoutDateInput) workoutDateInput.focus(); return; } if (workoutDuration <= 0) { alert("Veuillez entrer une durée valide."); if(workoutDurationInput) workoutDurationInput.focus(); return; } if (workoutExercisesForm.length === 0) { alert("Veuillez ajouter au moins un exercice."); return; } const exercises = []; let validationError = null; workoutExercisesForm.forEach((exerciseEl, index) => { if (validationError) return; const nameInput = exerciseEl.querySelector('.exercise-name'); const exerciseName = nameInput ? nameInput.value.trim() : ''; const unilateralCheckbox = exerciseEl.querySelector('.unilateral-checkbox'); const isUnilateral = unilateralCheckbox ? unilateralCheckbox.checked : false; if (!exerciseName) { validationError = `Nommez l'exercice #${index + 1}.`; if(nameInput) nameInput.focus(); return; } const series = []; const seriesElements = exerciseEl.querySelectorAll('.series'); if (seriesElements.length === 0) { validationError = `L'exercice "${exerciseName}" n'a pas de série.`; return; } seriesElements.forEach((seriesEl, sIndex) => { if (validationError) return; const repsInput = seriesEl.querySelector('.reps'); const weightInput = seriesEl.querySelector('.weight'); const degressiveCheckbox = seriesEl.querySelector('.degressive-checkbox'); const reps = repsInput ? parseInt(repsInput.value) || 0 : 0; const weight = weightInput ? parseFloat(weightInput.value) || 0 : 0; const isDegressive = degressiveCheckbox ? degressiveCheckbox.checked : false; if (reps <= 0) { validationError = `Reps invalides pour série ${sIndex + 1} (${exerciseName}).`; if(repsInput) repsInput.focus(); return; } if (weight < 0) { validationError = `Charge invalide pour série ${sIndex + 1} (${exerciseName}).`; if(weightInput) weightInput.focus(); return; } series.push({ reps, weight, isDegressive }); }); if (!validationError) { exercises.push({ name: exerciseName, isUnilateral, series }); } }); if (validationError) { alert(validationError); return; } let totalTonnage = 0; exercises.forEach(ex => { (ex.series || []).forEach(s => { totalTonnage += (s.reps || 0) * (s.weight || 0) * (ex.isUnilateral ? 2 : 1); }); }); const finalWorkoutName = workoutName || selectedWorkoutTypeName; const workoutData = { userId: userId, workoutTypeName: selectedWorkoutTypeName, name: finalWorkoutName, date: workoutDate, duration: workoutDuration, exercises: exercises, totalTonnage: totalTonnage, satisfaction: satisfaction, lastUpdated: firebase.firestore.FieldValue.serverTimestamp() }; let savePromise; if (currentWorkoutId) { workoutData.createdAt = workouts.find(w => w.id === currentWorkoutId)?.createdAt || firebase.firestore.FieldValue.serverTimestamp(); savePromise = db.collection('workouts').doc(currentWorkoutId).set(workoutData); } else { workoutData.createdAt = firebase.firestore.FieldValue.serverTimestamp(); savePromise = db.collection('workouts').add(workoutData); } saveWorkoutBtn.disabled = true; saveWorkoutBtn.textContent = 'Sauvegarde...'; savePromise.then((docRefOrVoid) => { const savedId = currentWorkoutId || (docRefOrVoid ? docRefOrVoid.id : 'unknown'); console.log("Séance sauvegardée:", savedId); currentWorkoutId = null; try { if (typeof confetti === 'function') confetti({ particleCount: 150, spread: 90, origin: { y: 0.6 } }); } catch(e) { console.warn("Confetti error:", e)} showPage('seances-page'); loadWorkouts(); }).catch(handleFirestoreError).finally(() => { saveWorkoutBtn.disabled = false; saveWorkoutBtn.textContent = 'Enregistrer Séance'; }); }
|
468 |
+
function deleteWorkout() { /* ... inchangé - mais redirection vers seances-page ... */ if (!currentFirebaseUser || !currentWorkoutId || !db || !deleteWorkoutBtn) return; const workoutToDelete = workouts.find(w => w && w.id === currentWorkoutId); if (!workoutToDelete) { console.error("Workout to delete not found locally."); return; } const confirmMsg = `Supprimer la séance "${workoutToDelete.name || 'Sans nom'}" du ${new Date(workoutToDelete.date).toLocaleDateString('fr-FR')} ?`; if (!confirm(confirmMsg)) return; console.log("Suppression séance:", currentWorkoutId); deleteWorkoutBtn.disabled = true; deleteWorkoutBtn.textContent = 'Suppression...'; db.collection('workouts').doc(currentWorkoutId).delete().then(() => { console.log("Séance supprimée avec succès:", currentWorkoutId); currentWorkoutId = null; showPage('seances-page'); loadWorkouts(); }).catch(handleFirestoreError).finally(() => { deleteWorkoutBtn.disabled = false; deleteWorkoutBtn.textContent = 'Supprimer Séance'; }); }
|
469 |
function setTodayDate() { /* ... inchangé ... */ if (workoutDateInput) { try { const today = new Date(); const offset = today.getTimezoneOffset(); const localDate = new Date(today.getTime() - (offset*60*1000)); workoutDateInput.value = localDate.toISOString().split('T')[0]; } catch (e) { console.error("Erreur setTodayDate:", e); try { workoutDateInput.value = new Date().toISOString().split('T')[0]; } catch {} } } }
|
470 |
|
471 |
+
function showPage(pageId) { // **MODIFIÉ** pour gérer la nav d'accueil
|
472 |
if (!appContainer) { console.error("App container not found!"); return; }
|
473 |
console.log(`Affichage page: ${pageId}`);
|
474 |
const pages = appContainer.querySelectorAll(':scope > div[id$="-page"]');
|
|
|
478 |
if (pageToShow) {
|
479 |
pageToShow.classList.add('active');
|
480 |
window.scrollTo(0, 0);
|
481 |
+
// Actions spécifiques
|
482 |
+
if (pageId === 'new-workout-page') { if (!selectedWorkoutTypeName) { alert("Sélectionnez un type."); showPage('select-workout-type-page'); return; } renderActiveExerciseForm(); updateWorkoutTypeIndicator(); }
|
483 |
+
else if (pageId === 'manage-types-page') loadWorkoutTypes();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
else if (pageId === 'select-workout-type-page') populateWorkoutTypeSelector();
|
485 |
else if (pageId === 'stats-page') updateStats();
|
486 |
+
else if (pageId === 'workout-details-page' && !currentWorkoutId) { alert("Séance non spécifiée."); showPage('seances-page'); return; }
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
} else {
|
488 |
console.error(`Page ID "${pageId}" non trouvée. Affichage accueil.`);
|
489 |
+
if (accueilPage) accueilPage.classList.add('active'); // Fallback sur accueil
|
490 |
+
pageId = 'accueil-page';
|
491 |
}
|
492 |
|
493 |
+
// Mise à jour Nav Bottom
|
494 |
navItems.forEach(item => item.classList.remove('active'));
|
495 |
+
// Active le bouton correspondant directement à la pageId si trouvé
|
496 |
const activeNavItem = document.querySelector(`.nav-item[data-page="${pageId}"]`);
|
497 |
if (activeNavItem) {
|
498 |
activeNavItem.classList.add('active');
|
499 |
} else {
|
500 |
+
// Si pas de bouton direct (ex: page détails), active "Séances" par défaut
|
501 |
+
const seancesNavItem = document.querySelector('.nav-item[data-page="seances-page"]');
|
502 |
+
if(seancesNavItem) seancesNavItem.classList.add('active');
|
503 |
}
|
504 |
}
|
505 |
|
|
|
517 |
function renderTypeTrends(trends) { /* ... inchangé ... */ if (!typeTrendsContainer || !noTrendsMessage || !trendsSpinner) { console.error("Cannot render trends: Missing DOM elements."); return;} trendsSpinner.classList.add('hidden'); typeTrendsContainer.innerHTML = ''; const trendTypes = Object.keys(trends); if (trendTypes.length === 0) { noTrendsMessage.classList.remove('hidden'); } else { noTrendsMessage.classList.add('hidden'); trendTypes.sort().forEach(typeName => { const typeData = trends[typeName]; if (!typeData || typeData.length === 0) return; const card = document.createElement('div'); card.className = 'card type-trend-card'; let listItems = ''; typeData.forEach(session => { const formattedDate = session.date ? new Date(session.date).toLocaleDateString('fr-FR', { day: '2-digit', month: 'short' }) : '??'; const tonnageText = (session.tonnage !== undefined && session.tonnage !== null) ? `${session.tonnage.toFixed(1)} kg` : 'N/A'; listItems += `<li><span>${formattedDate}</span> <strong>${tonnageText}</strong></li>`; }); card.innerHTML = `<h4>${typeName} (3 Dernières)</h4><ul>${listItems}</ul>`; typeTrendsContainer.appendChild(card); }); } }
|
518 |
function handleFirestoreError(error) { /* ... inchangé ... */ console.error("Erreur Firestore:", error.code, error.message); alert(`Erreur de base de données: ${error.message}`); }
|
519 |
|
520 |
+
|
521 |
// --- ÉCOUTEURS D'ÉVÉNEMENTS ---
|
522 |
function initEventListeners() {
|
523 |
console.log("initEventListeners: Attachement...");
|
|
|
528 |
if (authSwitchLink) authSwitchLink.addEventListener('click', authSwitchMode); else console.error("!authSwitchLink");
|
529 |
if (forgotPasswordLink) forgotPasswordLink.addEventListener('click', handlePasswordReset); else console.error("!forgotPasswordLink");
|
530 |
if (logoutBtn) logoutBtn.addEventListener('click', handleLogout); else console.error("!logoutBtn");
|
531 |
+
// Nav Bottom
|
532 |
navItems.forEach((item) => { if (item) item.addEventListener('click', (e) => { e.preventDefault(); const targetPageId = item.getAttribute('data-page'); if (!currentFirebaseUser && targetPageId !== 'login-page') { showLoginPage(); return; } if (targetPageId) showPage(targetPageId); }); else console.error(`!navItem`); });
|
533 |
// Workout List Actions
|
534 |
if (newWorkoutBtn) newWorkoutBtn.addEventListener('click', () => { if (!currentFirebaseUser) return; showPage('select-workout-type-page'); }); else console.error("!newWorkoutBtn");
|
|
|
540 |
if (startStructuredWorkoutBtn) startStructuredWorkoutBtn.addEventListener('click', () => { if (selectWorkoutTypeDropdown) { const type = selectWorkoutTypeDropdown.value; if (type) { clearNewWorkoutForm(type); showPage('new-workout-page'); } else { alert("Veuillez sélectionner un type de séance."); } } }); else console.error("!startStructuredWorkoutBtn");
|
541 |
if (startFreeWorkoutBtn) startFreeWorkoutBtn.addEventListener('click', () => { clearNewWorkoutForm("Libre"); showPage('new-workout-page'); }); else console.error("!startFreeWorkoutBtn");
|
542 |
// General Nav (Retour) -> Va maintenant à seances-page
|
543 |
+
backToSeancesBtns.forEach(btn => { if (btn) btn.addEventListener('click', () => showPage('seances-page')); else console.error("!backToSeancesBtn missing"); }); // **RENOMMÉ**
|
544 |
// New Workout Actions
|
545 |
+
if (cancelNewWorkoutBtn) cancelNewWorkoutBtn.addEventListener('click', () => { if (confirm("Annuler cette séance ? Les données non enregistrées seront perdues.")) showPage('seances-page'); }); else console.error("!cancelNewWorkoutBtn");
|
|
|
546 |
if (saveWorkoutBtn) saveWorkoutBtn.addEventListener('click', saveWorkout); else console.error("!saveWorkoutBtn");
|
547 |
if (addExerciseBtn) addExerciseBtn.addEventListener('click', handleAddNewExercise); else console.error("!addExerciseBtn");
|
548 |
// Exercise Nav
|