Spaces:
Running
Running
Update index.html
Browse files- index.html +93 -258
index.html
CHANGED
@@ -1,273 +1,108 @@
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="fr">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
-
<title>
|
7 |
-
<
|
8 |
-
|
9 |
-
<!-- SDK Firebase (v8) -->
|
10 |
-
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
|
11 |
-
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>
|
12 |
-
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-firestore.js"></script>
|
13 |
-
|
14 |
<style>
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
text-align: center;
|
20 |
-
margin-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
cursor: pointer;
|
24 |
}
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
27 |
</style>
|
28 |
</head>
|
29 |
<body>
|
30 |
-
<div class="
|
31 |
-
<
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
<label for="auth-email">Email</label>
|
44 |
-
<input type="email" id="auth-email" placeholder="[email protected]" required>
|
45 |
-
</div>
|
46 |
-
<!-- Le groupe mot de passe sera caché en mode reset -->
|
47 |
-
<div class="form-group" id="password-group">
|
48 |
-
<label for="auth-password">Mot de passe</label>
|
49 |
-
<input type="password" id="auth-password" placeholder="********"> <!-- Pas required ici car caché parfois -->
|
50 |
-
</div>
|
51 |
-
<p id="login-error"></p>
|
52 |
-
<button type="submit" id="auth-action-btn" class="btn" style="width: 100%;">Se Connecter</button>
|
53 |
-
</form>
|
54 |
-
<!-- Liens pour changer de mode ou reset -->
|
55 |
-
<div class="auth-links">
|
56 |
-
<div class="auth-switch">
|
57 |
-
<span id="auth-switch-text">Pas encore de compte ?</span>
|
58 |
-
<a id="auth-switch-link">Inscrivez-vous ici</a>
|
59 |
-
</div>
|
60 |
-
<!-- Lien Mot de passe oublié (visible en mode connexion) -->
|
61 |
-
<a class="forgot-password-link" id="forgot-password-link">Mot de passe oublié ?</a>
|
62 |
-
<!-- Lien Retour Connexion (visible en mode reset) -->
|
63 |
-
<a class="forgot-password-link hidden" id="back-to-login-link">Retour à la connexion</a>
|
64 |
-
</div>
|
65 |
-
</div>
|
66 |
-
</div>
|
67 |
-
|
68 |
-
<!-- Contenu Principal (structure identique) -->
|
69 |
-
<div id="main-app-content">
|
70 |
-
<!-- ... user-info, app-container, pages, nav-bottom ... -->
|
71 |
-
<div class="user-info"> Connecté: <strong id="current-user-display"></strong> <button id="logout-btn" class="btn btn-outline">Déconnexion</button> </div>
|
72 |
-
<div id="app-container"> <div id="home-page" class="active"> <div class="flex-between"> <h2>Mes séances</h2> <div> <button id="manage-types-btn" class="btn btn-outline" style="margin-right: 0.5rem;">Gérer Types</button> <button id="new-workout-btn" class="btn">Nouvelle séance</button> </div> </div> <div id="workouts-list" class="workout-list" style="margin-top: 1rem;"> <div class="spinner hidden"></div> <p id="empty-workout-message" class="hidden" style="text-align: center; margin-top: 2rem;"> Aucune séance enregistrée. </p> </div> </div> <div id="manage-types-page"> <div class="flex-between"> <h2>Gérer les Types</h2> <button class="btn btn-outline back-to-home-btn">Retour</button> </div> <div class="card"> <h3>Types Existants</h3> <ul id="workout-types-list" style="list-style: none; padding: 0; margin-top: 1rem;"> <li class="hidden" id="empty-types-message">Aucun type défini.</li> </ul> <div class="spinner hidden" id="types-spinner"></div> </div> <div class="card"> <h3>Ajouter un Type</h3> <form id="add-type-form"> <input type="text" id="new-type-name" placeholder="Nom (ex: Dos, Jambes)" required> <button type="submit" class="btn">Ajouter</button> </form> <p id="add-type-error" style="color: var(--danger); font-size: 0.9rem; margin-top: 0.5rem;"></p> </div> </div> <div id="select-workout-type-page"> <div class="flex-between"> <h2>Démarrer Séance</h2> <button class="btn btn-outline back-to-home-btn">Annuler</button> </div> <div class="card"> <h3>Type Prédéfini</h3> <select id="select-workout-type"> <option value="">-- Sélectionner --</option> </select> <button id="start-structured-workout-btn" class="btn" disabled>Démarrer Structurée</button> </div> <div class="card"> <h3>Séance Libre</h3> <button id="start-free-workout-btn" class="btn btn-info">Démarrer Libre</button> </div> </div> <div id="new-workout-page"> <div class="flex-between"> <h2>Nouvelle séance <span id="workout-type-indicator" class="badge type-badge hidden"></span> <span id="current-exercise-indicator" style="font-size: 0.9rem; color: #ccc;"></span></h2> <div> <button id="cancel-new-workout-btn" class="btn btn-outline" style="margin-right: 0.5rem;">Annuler</button> <button id="save-workout-btn" class="btn">Enregistrer</button> </div> </div> <div class="card"> <div class="form-group"> <label for="workout-name">Nom Séance (optionnel)</label> <input type="text" id="workout-name" placeholder="Ex: Push Intense..."> </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 (min)</label> <input type="number" id="workout-duration" min="1" placeholder="60"> </div> </div> </div> <h3 style="margin: 1rem 0;">Exercices</h3> <div class="exercise-navigation card"> <button id="prev-exercise-btn" class="btn btn-outline">< Précédent</button> <span style="align-self: center; color: #ccc;">Exercice Actif</span> <button id="next-exercise-btn" class="btn btn-outline">Suivant ></button> </div> <div id="exercises-container"> </div> <button id="add-exercise-btn" class="btn btn-outline" style="width: 100%; margin-top: 1rem;">+ Ajouter Exercice</button> <div class="card" style="margin-top: 2rem;"> <div class="form-group"> <label for="satisfaction">Satisfaction (1-100%)</label> <input type="range" id="satisfaction" min="1" max="100" value="75"> <div class="satisfaction"> <span></span> <div class="satisfaction-value">75%</div> </div> </div> </div> </div> <div id="workout-details-page"> <div class="flex-between"> <h2>Détail Séance <span id="detail-workout-type" class="badge type-badge hidden"></span></h2> <button class="btn btn-outline back-to-home-btn">Retour</button> </div> <div class="card"> <div class="workout-details-info"> <p><strong>Nom:</strong> <span id="detail-workout-name"></span></p> <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 (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"> </div> <button id="delete-workout-btn" class="btn btn-danger" style="width: 100%; margin-top: 2rem;">Supprimer</button> </div>
|
73 |
-
<div id="stats-page"> <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 Moy.</div> </div> </div> <h3 style="margin: 1.5rem 0 1rem;">Tendances par Type</h3> <div id="type-trends-container"> <p id="no-trends-message" style="text-align: center; color: #888;" class="hidden"> Pas assez de données. </p> <div class="spinner hidden" id="trends-spinner"></div> </div> </div> </div>
|
74 |
-
<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>
|
75 |
-
</div>
|
76 |
-
|
77 |
<script>
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
const
|
90 |
-
|
91 |
-
|
92 |
-
const
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
if (!auth) return;
|
109 |
-
event.preventDefault();
|
110 |
-
const email = authEmailInput.value;
|
111 |
-
loginError.textContent = ''; // Reset error
|
112 |
-
|
113 |
-
// === NOUVELLE LOGIQUE: Gérer le mode Reset ===
|
114 |
-
if (isResetMode) {
|
115 |
-
if (!email) { loginError.textContent = 'Entrez votre email pour réinitialiser.'; return; }
|
116 |
-
authActionButton.disabled = true; authActionButton.textContent = 'Envoi...';
|
117 |
-
console.log("Demande réinitialisation mot de passe pour:", email);
|
118 |
-
auth.sendPasswordResetEmail(email)
|
119 |
-
.then(() => {
|
120 |
-
console.log("Email de réinitialisation envoyé.");
|
121 |
-
loginError.textContent = ''; // Effacer ancienne erreur
|
122 |
-
alert("Email de réinitialisation envoyé à " + email + ". Vérifiez votre boîte de réception (et spams).");
|
123 |
-
switchToLoginMode(); // Revenir au mode connexion après envoi
|
124 |
-
})
|
125 |
-
.catch(handleAuthError) // Utiliser la même fonction pour afficher erreurs
|
126 |
-
.finally(() => {
|
127 |
-
// Le texte du bouton est géré par switchToLoginMode()
|
128 |
-
});
|
129 |
-
return; // Stopper ici si on est en mode reset
|
130 |
-
}
|
131 |
-
// === FIN LOGIQUE RESET ===
|
132 |
-
|
133 |
-
|
134 |
-
// Logique Connexion / Inscription (inchangée, mais vérifier que password existe)
|
135 |
-
const password = authPasswordInput.value;
|
136 |
-
if (!email || !password) { loginError.textContent = 'Email/Pass requis.'; return; }
|
137 |
-
authActionButton.disabled = true; authActionButton.textContent = 'Chargement...';
|
138 |
-
|
139 |
-
if (isLoginMode) {
|
140 |
-
auth.signInWithEmailAndPassword(email, password)
|
141 |
-
.catch(handleAuthError)
|
142 |
-
.finally(() => { authActionButton.disabled = false; authActionButton.textContent = 'Se Connecter'; });
|
143 |
-
} else {
|
144 |
-
auth.createUserWithEmailAndPassword(email, password)
|
145 |
-
.catch(handleAuthError)
|
146 |
-
.finally(() => { authActionButton.disabled = false; switchToLoginMode(); /* Revenir en mode login après tentative */ });
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
function handleLogout() { /* ... Identique ... */ if(!auth) return; console.log("Déconnexion..."); auth.signOut().catch(handleAuthError); }
|
151 |
-
|
152 |
-
// Modifié pour gérer le mode reset
|
153 |
-
function authSwitchMode() {
|
154 |
-
isLoginMode = !isLoginMode;
|
155 |
-
isResetMode = false; // Quitter le mode reset si on switch
|
156 |
-
updateAuthUI();
|
157 |
-
}
|
158 |
-
|
159 |
-
// Nouvelle fonction pour entrer/sortir du mode reset
|
160 |
-
function toggleResetMode(enterReset) {
|
161 |
-
isResetMode = enterReset;
|
162 |
-
isLoginMode = !enterReset; // Si on est en reset, on n'est plus en login standard
|
163 |
-
updateAuthUI();
|
164 |
-
}
|
165 |
-
|
166 |
-
// Nouvelle fonction pour mettre à jour l'UI d'authentification
|
167 |
-
function updateAuthUI() {
|
168 |
-
loginError.textContent = ''; // Clear errors
|
169 |
-
if (isResetMode) {
|
170 |
-
authTitle.textContent = 'Mot de Passe Oublié';
|
171 |
-
passwordGroup.classList.add('hidden'); // Cacher mot de passe
|
172 |
-
authPasswordInput.required = false; // Ne pas exiger le mdp caché
|
173 |
-
authSwitchContainer.classList.add('hidden'); // Cacher "Pas de compte?"
|
174 |
-
forgotPasswordLink.classList.add('hidden'); // Cacher "mdp oublié?"
|
175 |
-
backToLoginLink.classList.remove('hidden'); // Montrer "Retour"
|
176 |
-
authActionButton.textContent = 'Envoyer Email Reset';
|
177 |
-
} else {
|
178 |
-
passwordGroup.classList.remove('hidden'); // Montrer mot de passe
|
179 |
-
authPasswordInput.required = true; // Exiger le mdp
|
180 |
-
authSwitchContainer.classList.remove('hidden'); // Montrer switch
|
181 |
-
backToLoginLink.classList.add('hidden'); // Cacher "Retour"
|
182 |
-
|
183 |
-
if (isLoginMode) {
|
184 |
-
authTitle.textContent = 'Connexion';
|
185 |
-
authActionButton.textContent = 'Se Connecter';
|
186 |
-
authSwitchText.textContent = 'Pas encore de compte ?';
|
187 |
-
authSwitchLink.textContent = 'Inscrivez-vous ici';
|
188 |
-
forgotPasswordLink.classList.remove('hidden'); // Montrer "mdp oublié?"
|
189 |
-
} else {
|
190 |
-
authTitle.textContent = 'Inscription';
|
191 |
-
authActionButton.textContent = 'S\'inscrire';
|
192 |
-
authSwitchText.textContent = 'Déjà un compte ?';
|
193 |
-
authSwitchLink.textContent = 'Connectez-vous ici';
|
194 |
-
forgotPasswordLink.classList.add('hidden'); // Cacher "mdp oublié?" en mode inscription
|
195 |
-
}
|
196 |
-
}
|
197 |
-
authActionButton.disabled = false; // Réactiver au cas où
|
198 |
-
}
|
199 |
-
|
200 |
-
// Passer en mode connexion et mettre à jour l'UI
|
201 |
-
function switchToLoginMode() {
|
202 |
-
isLoginMode = true;
|
203 |
-
isResetMode = false;
|
204 |
-
updateAuthUI();
|
205 |
-
}
|
206 |
-
|
207 |
-
|
208 |
-
function handleAuthError(error) { /* ... Identique ... */ console.error("Erreur Auth:", error); loginError.textContent = getAuthErrorMessage(error); }
|
209 |
-
function getAuthErrorMessage(error) { /* ... Identique ... */ switch (error.code) { case 'auth/invalid-email': return 'Email invalide.'; case 'auth/user-disabled': return 'Compte désactivé.'; case 'auth/user-not-found': return 'Utilisateur inconnu.'; case 'auth/wrong-password': return 'Mot de passe incorrect.'; case 'auth/email-already-in-use': return 'Email déjà utilisé.'; case 'auth/weak-password': return 'Mot de passe trop faible.'; default: return 'Erreur authentification.'; } }
|
210 |
-
function loadWorkoutTypes() { /* ... Identique ... */ if (!currentFirebaseUser || !db) return; const userId = currentFirebaseUser.uid; console.log("Chargement types..."); userWorkoutTypes = []; if (typesSpinner) typesSpinner.classList.remove('hidden'); db.collection('workoutTypes').where('userId', '==', userId).orderBy('name').get().then(snapshot => { snapshot.forEach(doc => userWorkoutTypes.push({ id: doc.id, ...doc.data() })); console.log("Types chargés:", userWorkoutTypes); renderWorkoutTypesList(); populateWorkoutTypeSelector(); }).catch(handleFirestoreError).finally(() => { if (typesSpinner) typesSpinner.classList.add('hidden'); }); }
|
211 |
-
function renderWorkoutTypesList() { /* ... Identique ... */ if (!workoutTypesList) return; workoutTypesList.innerHTML = ''; if (userWorkoutTypes.length === 0) { if(emptyTypesMessage) emptyTypesMessage.classList.remove('hidden'); } else { if(emptyTypesMessage) emptyTypesMessage.classList.add('hidden'); userWorkoutTypes.forEach(type => { const li = document.createElement('li'); li.textContent = type.name; workoutTypesList.appendChild(li); }); } }
|
212 |
-
function handleAddWorkoutType(event) { /* ... Identique ... */ event.preventDefault(); if (!currentFirebaseUser || !newTypeNameInput || !db) return; const typeName = newTypeNameInput.value.trim(); addTypeError.textContent = ''; if (!typeName) { addTypeError.textContent = "Nom vide."; return; } if (userWorkoutTypes.some(t => t.name.toLowerCase() === typeName.toLowerCase())) { addTypeError.textContent = "Type existe déjà."; return; } console.log("Ajout type:", typeName); const typeData = { userId: currentFirebaseUser.uid, name: typeName }; db.collection('workoutTypes').add(typeData).then(() => { console.log("Type ajouté"); newTypeNameInput.value = ''; loadWorkoutTypes(); }).catch(handleFirestoreError); }
|
213 |
-
function populateWorkoutTypeSelector() { /* ... Identique ... */ if (!selectWorkoutTypeDropdown) return; selectWorkoutTypeDropdown.innerHTML = '<option value="">-- Sélectionner --</option>'; userWorkoutTypes.forEach(type => { const option = document.createElement('option'); option.value = type.name; option.textContent = type.name; selectWorkoutTypeDropdown.appendChild(option); }); updateStartStructuredBtnState(); }
|
214 |
-
function updateStartStructuredBtnState() { /* ... Identique ... */ if (!selectWorkoutTypeDropdown || !startStructuredWorkoutBtn) return; startStructuredWorkoutBtn.disabled = !selectWorkoutTypeDropdown.value; }
|
215 |
-
function loadWorkouts() { /* ... Identique ... */ if (!currentFirebaseUser || !db) { console.log("Chargement séances annulé."); workouts = []; renderWorkoutsList(); showPage('home-page'); return; } const userId = currentFirebaseUser.uid; console.log(`Chargement séances ${userId}...`); if (spinner) spinner.classList.remove('hidden'); if(emptyWorkoutMessage) emptyWorkoutMessage.classList.add('hidden'); if(workoutsList) workoutsList.innerHTML = ''; workouts = []; db.collection('workouts').where('userId', '==', userId).orderBy('date', 'desc').get().then((querySnapshot) => { console.log(`${querySnapshot.size} séances trouvées.`); querySnapshot.forEach((doc) => { const workoutData = doc.data(); workoutData.firestoreId = doc.id; workouts.push(workoutData); }); renderWorkoutsList(); updateStats(); showPage('home-page'); }).catch(handleFirestoreError).finally(() => { if (spinner) spinner.classList.add('hidden'); }); }
|
216 |
-
function saveWorkout() { /* ... Identique ... */ if (!currentFirebaseUser || !db) { alert("Non connecté."); 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.value; const workoutDuration = parseInt(document.getElementById('workout-duration').value) || 0; const satisfaction = parseInt(satisfactionRange.value); if (!selectedWorkoutTypeName) { alert("Type séance non défini."); return; } if (!workoutDate || workoutDuration <= 0) { alert("Données invalides."); return; } const exerciseElements = workoutExercisesForm; const exercises = []; if (exerciseElements.length === 0) { alert("Ajoutez exercices."); return; } let validationError = null; exerciseElements.forEach((exerciseEl, index) => { if (validationError) return; const nameInput = exerciseEl.querySelector('.exercise-name'); const exerciseName = nameInput ? nameInput.value.trim() : ''; const isUnilateral = exerciseEl.querySelector('.unilateral-checkbox').checked; if (!exerciseName) { validationError = `Nommez exo #${index + 1}.`; if(nameInput) nameInput.focus(); return; } const series = []; const seriesElements = exerciseEl.querySelectorAll('.series'); if (seriesElements.length === 0) { validationError = `"${exerciseName}" sans série.`; return; } seriesElements.forEach(seriesEl => { if (validationError) return; const repsInput = seriesEl.querySelector('.reps'); const weightInput = seriesEl.querySelector('.weight'); const reps = parseInt(repsInput.value) || 0; const weight = parseFloat(weightInput.value) || 0; const isDegressive = seriesEl.querySelector('.degressive-checkbox').checked; if (reps <= 0) { validationError = `Reps invalides: "${exerciseName}".`; if(repsInput) repsInput.focus(); return; } if (weight < 0) { validationError = `Charge invalide: "${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 * s.weight * (ex.isUnilateral ? 2 : 1))); const finalWorkoutName = workoutName || selectedWorkoutTypeName; const workout = { id: currentWorkoutId || `workout-${Date.now()}`, userId: userId, workoutTypeName: selectedWorkoutTypeName, name: finalWorkoutName, date: workoutDate, duration: workoutDuration, exercises: exercises, totalTonnage: totalTonnage, satisfaction: satisfaction }; console.log("Sauvegarde:", workout); saveWorkoutBtn.disabled = true; saveWorkoutBtn.textContent = 'Sauvegarde...'; db.collection('workouts').doc(workout.id).set(workout).then(() => { console.log("Sauvegardé:", workout.id); const existingIndex = workouts.findIndex(w => w.id === workout.id); if (existingIndex > -1) workouts[existingIndex] = workout; else workouts.push(workout); confetti({ particleCount: 150, spread: 90, origin: { y: 0.6 } }); showPage('home-page'); renderWorkoutsList(); }).catch(handleFirestoreError).finally(() => { saveWorkoutBtn.disabled = false; saveWorkoutBtn.textContent = 'Enregistrer Séance'; }); }
|
217 |
-
function deleteWorkout() { /* ... Identique ... */ if (!currentFirebaseUser || !currentWorkoutId || !db) return; const workoutToDelete = workouts.find(w => w.id === currentWorkoutId); if (!workoutToDelete) return; const confirmDelete = confirm(`Supprimer "${workoutToDelete.name}"?`); if (!confirmDelete) return; console.log("Suppression:", currentWorkoutId); deleteWorkoutBtn.disabled = true; deleteWorkoutBtn.textContent = 'Suppression...'; db.collection('workouts').doc(currentWorkoutId).delete().then(() => { console.log("Supprimé:", currentWorkoutId); workouts = workouts.filter(w => w.id !== currentWorkoutId); currentWorkoutId = null; showPage('home-page'); renderWorkoutsList(); }).catch(handleFirestoreError).finally(() => { deleteWorkoutBtn.disabled = false; deleteWorkoutBtn.textContent = 'Supprimer'; }); }
|
218 |
-
function setTodayDate() { /* ... Identique ... */ if(workoutDateInput) try { workoutDateInput.value = new Date().toISOString().split('T')[0]; } catch(e){ console.error("Erreur date:", e); }}
|
219 |
-
function showPage(pageId) { /* ... Identique ... */ console.log(`Affichage page: ${pageId}`); if (!currentFirebaseUser && pageId !== 'login-page') { showLoginPage(); return; } document.querySelectorAll('#app-container > div').forEach(page => page.classList.remove('active')); const pageToShow = document.getElementById(pageId); if (pageToShow) { pageToShow.classList.add('active'); if (pageId === 'new-workout-page') { triggerFlameAnimation(); renderActiveExerciseForm(); updateWorkoutTypeIndicator(); } if (pageId === 'manage-types-page') { loadWorkoutTypes(); } if (pageId === 'select-workout-type-page') { populateWorkoutTypeSelector(); } if (pageId === 'stats-page') { updateStats(); } } else { console.error(`Page ID "${pageId}" non trouvée.`); document.getElementById('home-page').classList.add('active'); pageId = 'home-page'; } navItems.forEach(item => { item.classList.remove('active'); }); const activeNavItem = document.querySelector(`.nav-item[data-page="${pageId === 'stats-page' ? 'stats-page' : 'home-page'}"]`); if(activeNavItem) activeNavItem.classList.add('active'); }
|
220 |
-
function triggerFlameAnimation() { /* ... Identique ... */ const duration = 1 * 1000; const animationEnd = Date.now() + duration; const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 }; function randomInRange(min, max) { return Math.random() * (max - min) + min; } const interval = setInterval(function() { const timeLeft = animationEnd - Date.now(); if (timeLeft <= 0) return clearInterval(interval); const particleCount = 50 * (timeLeft / duration); confetti(Object.assign({}, defaults, { particleCount, origin: { x: randomInRange(0.3, 0.7), y: Math.random() - 0.2 }, angle: randomInRange(240, 300), spread: randomInRange(50, 90), gravity: 0.5, drift: randomInRange(-1, 1), colors: ['#ff6f00', '#ff8f00', '#ffa000', '#ffcc00'] })); }, 250); }
|
221 |
-
function handleAddNewExercise() { /* ... Identique ... */ addExercise(true); }
|
222 |
-
function addExercise(navigateToNew = false) { /* ... Identique ... */ if (!currentFirebaseUser) return; const exerciseId = `exercise-${Date.now()}`; const exerciseDiv = document.createElement('div'); exerciseDiv.className = 'card exercise'; exerciseDiv.setAttribute('data-exercise-id', exerciseId); exerciseDiv.innerHTML = `<div class="exercise-header"> <input type="text" placeholder="Nom Exercice" class="exercise-name"> <button class="btn btn-danger remove-exercise" style="padding: 0.3rem 0.6rem; flex-shrink: 0;">×</button> </div> <div class="form-group" style="margin-top: 0.5rem; margin-bottom: 0.5rem;"> <label style="display: inline-flex; align-items: center; color: #bbb; font-size: 0.9rem;"> <input type="checkbox" class="unilateral-checkbox"> Unilatéral </label> </div> <div class="series-container"></div> <button class="btn btn-outline add-series" style="width: 100%; margin-top: 0.5rem; padding: 0.4rem;">+ Ajouter Série</button>`; exercisesContainer.appendChild(exerciseDiv); workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); const removeBtn = exerciseDiv.querySelector('.remove-exercise'); removeBtn.addEventListener('click', () => { const indexToRemove = workoutExercisesForm.indexOf(exerciseDiv); if (indexToRemove > -1) { exerciseDiv.remove(); workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); if (currentExerciseIndex >= indexToRemove) currentExerciseIndex = Math.max(0, currentExerciseIndex - 1); if (currentExerciseIndex >= workoutExercisesForm.length) currentExerciseIndex = Math.max(0, workoutExercisesForm.length - 1); renderActiveExerciseForm(); } }); const addSeriesBtn = exerciseDiv.querySelector('.add-series'); const seriesContainer = exerciseDiv.querySelector('.series-container'); addSeriesBtn.addEventListener('click', () => addSeries(seriesContainer)); addSeries(seriesContainer); if (navigateToNew) { currentExerciseIndex = workoutExercisesForm.length - 1; renderActiveExerciseForm(); } else updateExerciseNavButtons(); }
|
223 |
-
function addSeries(container) { /* ... Identique ... */ if (!currentFirebaseUser || !container) return; 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" style="align-items: flex-end; gap: 0.8rem;"> <div class="form-group" style="flex: 1.2;"> <label>Reps</label> <input type="number" class="reps" min="1" placeholder="10" style="padding: 0.4rem;"> </div> <div class="form-group" style="flex: 1.2;"> <label>Charge (kg)</label> <input type="number" class="weight" min="0" step="0.1" placeholder="20" style="padding: 0.4rem;"> </div> <div class="form-group" style="flex: 1; display: flex; align-items: center; padding-bottom: 0.6rem; min-width: 100px;"> <label style="display: inline-flex; align-items: center; color: #bbb; font-size: 0.8rem; margin-bottom: 0; white-space: nowrap;"> <input type="checkbox" class="degressive-checkbox" style="margin-right: 0.3rem;"> Dégressive </label> </div> <button class="btn btn-danger remove-series" style="padding: 0.3rem 0.6rem; margin-bottom: 0.6rem; flex-basis: 30px; flex-grow: 0; align-self: center;">×</button> </div>`; container.appendChild(seriesDiv); const removeBtn = seriesDiv.querySelector('.remove-series'); removeBtn.addEventListener('click', () => seriesDiv.remove()); }
|
224 |
-
function navigateExerciseForm(direction) { /* ... Identique ... */ workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); const newIndex = currentExerciseIndex + direction; if (newIndex >= 0 && newIndex < workoutExercisesForm.length) { currentExerciseIndex = newIndex; renderActiveExerciseForm(); } }
|
225 |
-
function renderActiveExerciseForm() { /* ... Identique ... */ workoutExercisesForm = Array.from(exercisesContainer.querySelectorAll('.exercise')); workoutExercisesForm.forEach(ex => ex.classList.remove('active-exercise')); if (currentExerciseIndex >= 0 && currentExerciseIndex < workoutExercisesForm.length) workoutExercisesForm[currentExerciseIndex].classList.add('active-exercise'); updateExerciseNavButtons(); }
|
226 |
-
function updateExerciseNavButtons() { /* ... Identique ... */ const totalExercises = workoutExercisesForm.length; if (totalExercises === 0) { currentExerciseIndicator.textContent = "(Aucun exercice)"; prevExerciseBtn.disabled = true; nextExerciseBtn.disabled = true; } else { currentExerciseIndicator.textContent = `(${currentExerciseIndex + 1}/${totalExercises})`; prevExerciseBtn.disabled = currentExerciseIndex === 0; nextExerciseBtn.disabled = currentExerciseIndex === totalExercises - 1; } }
|
227 |
-
function clearNewWorkoutForm(typeName = "Libre") { /* ... Identique ... */ console.log("Nettoyage form pour type:", typeName); if (!currentFirebaseUser) return; selectedWorkoutTypeName = typeName; const workoutNameInput = document.getElementById('workout-name'); if(workoutNameInput) workoutNameInput.value = (typeName === "Libre" ? "" : typeName); if(workoutDateInput) setTodayDate(); if(document.getElementById('workout-duration')) document.getElementById('workout-duration').value = ''; if(exercisesContainer) exercisesContainer.innerHTML = ''; workoutExercisesForm = []; if(satisfactionRange) satisfactionRange.value = 75; if(satisfactionValue) satisfactionValue.textContent = '75%'; currentWorkoutId = null; currentExerciseIndex = 0; addExercise(false); updateWorkoutTypeIndicator(); renderActiveExerciseForm(); }
|
228 |
-
function updateWorkoutTypeIndicator() { /* ... Identique ... */ if (!workoutTypeIndicator) return; if (selectedWorkoutTypeName && selectedWorkoutTypeName !== "Libre") { workoutTypeIndicator.textContent = selectedWorkoutTypeName; workoutTypeIndicator.classList.remove('hidden'); } else { workoutTypeIndicator.classList.add('hidden'); } }
|
229 |
-
function renderWorkoutsList() { /* ... Identique ... */ if (!currentFirebaseUser) { workoutsList.innerHTML = ''; emptyWorkoutMessage.classList.remove('hidden'); updateStats(); return; } workoutsList.innerHTML = ''; if (workouts.length === 0) { emptyWorkoutMessage.classList.remove('hidden'); } else { emptyWorkoutMessage.classList.add('hidden'); const sortedWorkouts = [...workouts].sort((a, b) => new Date(b.date) - new Date(a.date)); sortedWorkouts.forEach(workout => { const workoutDate = new Date(workout.date).toLocaleDateString('fr-FR', { year: 'numeric', month: 'short', day: 'numeric' }); const workoutDiv = document.createElement('div'); workoutDiv.className = 'card workout-card'; workoutDiv.setAttribute('data-workout-id', workout.id); const typeBadge = workout.workoutTypeName && workout.workoutTypeName !== "Libre" ? `<span class="badge type-badge">${workout.workoutTypeName}</span>` : ''; workoutDiv.innerHTML = `<div class="workout-header"><h3 style="margin-bottom: 0.5rem;">${workout.name} ${typeBadge}</h3><div class="badge">${workoutDate}</div></div><div class="workout-details" style="font-size: 0.9rem; color: #ccc; margin-top: 0.5rem;"><span>${workout.duration} min</span> | <span>${workout.exercises.length} exo${workout.exercises.length > 1 ? 's' : ''}</span> | <span>${workout.totalTonnage.toFixed(1)} kg</span> | <span>${workout.satisfaction}%</span></div>`; workoutDiv.addEventListener('click', () => displayWorkoutDetails(workout.id)); workoutsList.appendChild(workoutDiv); }); } /* updateStats est appelé par loadWorkouts */ }
|
230 |
-
function displayWorkoutDetails(workoutId) { /* ... Identique ... */ if (!currentFirebaseUser) return; const workout = workouts.find(w => w.id === workoutId); if (!workout) { showPage('home-page'); return; } if(detailWorkoutType) { if (workout.workoutTypeName && workout.workoutTypeName !== "Libre") { detailWorkoutType.textContent = workout.workoutTypeName; detailWorkoutType.classList.remove('hidden'); } else detailWorkoutType.classList.add('hidden'); } if(document.getElementById('detail-workout-name')) document.getElementById('detail-workout-name').textContent = workout.name; if(document.getElementById('detail-date')) document.getElementById('detail-date').textContent = new Date(workout.date).toLocaleDateString('fr-FR'); if(document.getElementById('detail-duration')) document.getElementById('detail-duration').textContent = workout.duration; if(document.getElementById('detail-tonnage')) document.getElementById('detail-tonnage').textContent = workout.totalTonnage.toFixed(1); if(document.getElementById('detail-satisfaction')) document.getElementById('detail-satisfaction').textContent = `${workout.satisfaction}%`; if(document.getElementById('detail-exercises-count')) document.getElementById('detail-exercises-count').textContent = workout.exercises.length; const detailExercisesContainer = document.getElementById('detail-exercises-container'); if(detailExercisesContainer) { detailExercisesContainer.innerHTML = ''; workout.exercises.forEach((exercise) => { const exerciseDiv = document.createElement('div'); exerciseDiv.className = 'card detail-exercise-card'; let seriesHtml = ''; exercise.series.forEach((serie, sIndex) => { const degressiveLabel = serie.isDegressive ? ' <span class="badge" style="font-size: 0.7rem; background-color: var(--accent-dark);">Dégr.</span>' : ''; const weightFactor = exercise.isUnilateral ? 2 : 1; const seriesTonnage = serie.reps * serie.weight * weightFactor; seriesHtml += `<div class="exercise-summary"><div class="flex-between"><span>Série ${sIndex + 1}: ${serie.reps} reps × ${serie.weight} kg${degressiveLabel}</span><span style="color: #aaa;">(${seriesTonnage.toFixed(1)} kg)</span></div></div>`; }); const unilateralLabel = exercise.isUnilateral ? ' <span class="badge" style="font-size: 0.7rem;">Unilat.</span>' : ''; exerciseDiv.innerHTML = `<h3 style="font-size: 1.1rem; margin-bottom: 0.5rem;">${exercise.name}${unilateralLabel}</h3> <div class="series-summary-container"> ${seriesHtml} </div>`; detailExercisesContainer.appendChild(exerciseDiv); }); } currentWorkoutId = workoutId; showPage('workout-details-page'); }
|
231 |
-
function updateStats() { /* ... (Version v5 avec tendances) ... */ console.log("Mise à jour des statistiques..."); if (!currentFirebaseUser) { console.log("Stats: non connecté."); return; } const workoutCount = workouts.length; if (!statsWorkoutCountEl || !statsAvgTonnageEl || !statsAvgSatisfactionEl) { console.error("Éléments DOM pour stats globales manquants."); return; } statsWorkoutCountEl.textContent = workoutCount; if (workoutCount === 0) { statsAvgTonnageEl.textContent = '0'; statsAvgSatisfactionEl.textContent = '0%'; renderTypeTrends({}); return; } const totalTonnageAll = workouts.reduce((sum, w) => sum + (w.totalTonnage || 0), 0); statsAvgTonnageEl.textContent = (totalTonnageAll / workoutCount).toFixed(1); const totalSatisfaction = workouts.reduce((sum, w) => sum + (w.satisfaction || 0), 0); statsAvgSatisfactionEl.textContent = `${Math.round(totalSatisfaction / workoutCount)}%`; console.log("Calcul tendances..."); const trendsData = {}; const structuredWorkouts = workouts.filter(w => w.workoutTypeName && w.workoutTypeName !== "Libre"); const groupedByType = structuredWorkouts.reduce((acc, workout) => { const type = workout.workoutTypeName; if (!acc[type]) acc[type] = []; acc[type].push(workout); return acc; }, {}); console.log("Groupées:", groupedByType); for (const typeName in groupedByType) { const sessionsOfType = groupedByType[typeName].sort((a, b) => new Date(b.date) - new Date(a.date)); trendsData[typeName] = sessionsOfType.slice(0, 3).map(s => ({ date: s.date, tonnage: s.totalTonnage })).reverse(); } console.log("Données tendances:", trendsData); renderTypeTrends(trendsData); }
|
232 |
-
function renderTypeTrends(trends) { /* ... (Identique à la v5) ... */ if (!typeTrendsContainer || !noTrendsMessage) { console.error("Éléments DOM pour tendances manquants."); return;} 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 = 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} (Dernières Séances)</h4><ul>${listItems}</ul>`; typeTrendsContainer.appendChild(card); }); } }
|
233 |
-
function handleFirestoreError(error) { console.error("Erreur Firestore:", error); alert("Erreur base de données."); }
|
234 |
-
|
235 |
-
// --- ÉCOUTEURS D'ÉVÉNEMENTS ---
|
236 |
-
function initEventListeners() {
|
237 |
-
console.log("initEventListeners: Attachement...");
|
238 |
-
// Authentification
|
239 |
-
if (loginForm) loginForm.addEventListener('submit', handleAuthAction); else console.error("!loginForm");
|
240 |
-
if (authSwitchLink) authSwitchLink.addEventListener('click', authSwitchMode); else console.error("!authSwitchLink");
|
241 |
-
if (logoutBtn) logoutBtn.addEventListener('click', handleLogout); else console.error("!logoutBtn");
|
242 |
-
// **NOUVEAU:** Liens pour mot de passe oublié
|
243 |
-
if (forgotPasswordLink) forgotPasswordLink.addEventListener('click', (e) => { e.preventDefault(); toggleResetMode(true); }); else console.error("!forgotPasswordLink");
|
244 |
-
if (backToLoginLink) backToLoginLink.addEventListener('click', (e) => { e.preventDefault(); toggleResetMode(false); }); else console.error("!backToLoginLink");
|
245 |
-
|
246 |
-
// Navigation & Actions App
|
247 |
-
navItems.forEach((item, index) => { if(item) item.addEventListener('click', (e) => { e.preventDefault(); if (!currentFirebaseUser) return; const targetPageId = item.getAttribute('data-page'); showPage(targetPageId); }); else console.error(`!navItem #${index}`); });
|
248 |
-
if (newWorkoutBtn) newWorkoutBtn.addEventListener('click', () => { if (!currentFirebaseUser) return; showPage('select-workout-type-page'); }); else console.error("!newWorkoutBtn");
|
249 |
-
if (manageTypesBtn) manageTypesBtn.addEventListener('click', () => showPage('manage-types-page')); else console.error("!manageTypesBtn");
|
250 |
-
if (addTypeForm) addTypeForm.addEventListener('submit', handleAddWorkoutType); else console.error("!addTypeForm");
|
251 |
-
if (selectWorkoutTypeDropdown) selectWorkoutTypeDropdown.addEventListener('change', updateStartStructuredBtnState); else console.error("!selectWorkoutTypeDropdown");
|
252 |
-
if (startStructuredWorkoutBtn) startStructuredWorkoutBtn.addEventListener('click', () => { if(selectWorkoutTypeDropdown) { const type = selectWorkoutTypeDropdown.value; if(type) { clearNewWorkoutForm(type); showPage('new-workout-page'); } } }); else console.error("!startStructuredWorkoutBtn");
|
253 |
-
if (startFreeWorkoutBtn) startFreeWorkoutBtn.addEventListener('click', () => { clearNewWorkoutForm("Libre"); showPage('new-workout-page'); }); else console.error("!startFreeWorkoutBtn");
|
254 |
-
backToHomeBtns.forEach(btn => { if(btn) btn.addEventListener('click', () => showPage('home-page')); else console.error("!backToHomeBtn"); });
|
255 |
-
if (cancelNewWorkoutBtn) cancelNewWorkoutBtn.addEventListener('click', () => showPage('home-page')); else console.error("!cancelNewWorkoutBtn");
|
256 |
-
if (saveWorkoutBtn) saveWorkoutBtn.addEventListener('click', saveWorkout); else console.error("!saveWorkoutBtn");
|
257 |
-
if (addExerciseBtn) addExerciseBtn.addEventListener('click', handleAddNewExercise); else console.error("!addExerciseBtn");
|
258 |
-
if (prevExerciseBtn) prevExerciseBtn.addEventListener('click', navigateExerciseForm.bind(null, -1)); else console.error("!prevExerciseBtn");
|
259 |
-
if (nextExerciseBtn) nextExerciseBtn.addEventListener('click', navigateExerciseForm.bind(null, 1)); else console.error("!nextExerciseBtn");
|
260 |
-
if (deleteWorkoutBtn) deleteWorkoutBtn.addEventListener('click', deleteWorkout); else console.error("!deleteWorkoutBtn");
|
261 |
-
if (satisfactionRange) satisfactionRange.addEventListener('input', () => { if(satisfactionValue) satisfactionValue.textContent = `${satisfactionRange.value}%`; }); else console.error("!satisfactionRange");
|
262 |
-
console.log("initEventListeners: Fin attachement.");
|
263 |
-
}
|
264 |
-
|
265 |
-
// ===========================================
|
266 |
-
// --- INITIALISATION ---
|
267 |
-
// ===========================================
|
268 |
-
if (auth) { initAuthListener(); } else { console.error("Firebase Auth non prêt!"); }
|
269 |
-
initEventListeners();
|
270 |
-
|
271 |
</script>
|
272 |
</body>
|
273 |
-
</html>
|
|
|
1 |
+
|
2 |
<!DOCTYPE html>
|
3 |
<html lang="fr">
|
4 |
<head>
|
5 |
<meta charset="UTF-8">
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<title>Cocktail Fitness - Connexion</title>
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Oswald:wght@700&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
<style>
|
10 |
+
body {
|
11 |
+
background-color: #101010;
|
12 |
+
color: #f0f0f0;
|
13 |
+
font-family: 'Roboto', sans-serif;
|
14 |
+
display: flex;
|
15 |
+
align-items: center;
|
16 |
+
justify-content: center;
|
17 |
+
height: 100vh;
|
18 |
+
margin: 0;
|
19 |
+
}
|
20 |
+
.card {
|
21 |
+
background-color: #1e1e1e;
|
22 |
+
padding: 2rem;
|
23 |
+
border-radius: 8px;
|
24 |
+
width: 100%;
|
25 |
+
max-width: 400px;
|
26 |
+
box-shadow: 0 0 20px rgba(0,0,0,0.5);
|
27 |
+
}
|
28 |
+
h2 {
|
29 |
+
font-family: 'Oswald', sans-serif;
|
30 |
+
color: #FFC107;
|
31 |
text-align: center;
|
32 |
+
margin-bottom: 1rem;
|
33 |
+
}
|
34 |
+
input {
|
35 |
+
width: 100%;
|
36 |
+
padding: 0.8rem;
|
37 |
+
margin-bottom: 1rem;
|
38 |
+
border: 1px solid #444;
|
39 |
+
border-radius: 4px;
|
40 |
+
background-color: #2a2a2a;
|
41 |
+
color: white;
|
42 |
+
}
|
43 |
+
button {
|
44 |
+
width: 100%;
|
45 |
+
padding: 0.8rem;
|
46 |
+
background-color: #FFC107;
|
47 |
+
border: none;
|
48 |
+
border-radius: 4px;
|
49 |
+
color: #101010;
|
50 |
+
font-weight: bold;
|
51 |
cursor: pointer;
|
52 |
}
|
53 |
+
#login-error {
|
54 |
+
color: #f44336;
|
55 |
+
text-align: center;
|
56 |
+
display: none;
|
57 |
+
margin-top: 0.5rem;
|
58 |
+
}
|
59 |
</style>
|
60 |
</head>
|
61 |
<body>
|
62 |
+
<div class="card">
|
63 |
+
<h2>Connexion</h2>
|
64 |
+
<form id="login-form">
|
65 |
+
<input type="email" id="auth-email" placeholder="Votre email" required>
|
66 |
+
<input type="password" id="auth-password" placeholder="Mot de passe" required>
|
67 |
+
<p id="login-error"></p>
|
68 |
+
<button type="submit">Se connecter</button>
|
69 |
+
</form>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<!-- Firebase SDK -->
|
73 |
+
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
|
74 |
+
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
<script>
|
76 |
+
const firebaseConfig = {
|
77 |
+
apiKey: "AIzaSyAkWvrRyXgrC7zbTtoh_GppsHMrz2rF7WM",
|
78 |
+
authDomain: "lifttrackapp.firebaseapp.com",
|
79 |
+
projectId: "lifttrackapp",
|
80 |
+
storageBucket: "lifttrackapp.appspot.com",
|
81 |
+
messagingSenderId: "594426771796",
|
82 |
+
appId: "1:594426771796:web:789bef037ca0016c54b0c1",
|
83 |
+
measurementId: "G-MXLFK0H160"
|
84 |
+
};
|
85 |
+
|
86 |
+
firebase.initializeApp(firebaseConfig);
|
87 |
+
const auth = firebase.auth();
|
88 |
+
|
89 |
+
const form = document.getElementById('login-form');
|
90 |
+
const errorMsg = document.getElementById('login-error');
|
91 |
+
|
92 |
+
form.addEventListener('submit', (e) => {
|
93 |
+
e.preventDefault();
|
94 |
+
const email = document.getElementById('auth-email').value;
|
95 |
+
const password = document.getElementById('auth-password').value;
|
96 |
+
|
97 |
+
auth.signInWithEmailAndPassword(email, password)
|
98 |
+
.then(userCredential => {
|
99 |
+
alert('Connexion réussie pour ' + userCredential.user.email);
|
100 |
+
})
|
101 |
+
.catch(error => {
|
102 |
+
errorMsg.style.display = 'block';
|
103 |
+
errorMsg.textContent = 'Erreur : ' + error.message;
|
104 |
+
});
|
105 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
</script>
|
107 |
</body>
|
108 |
+
</html>
|