| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NutriCalc - Calculateur de Calories Intelligent</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| .gradient-bg { |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); |
| } |
| .food-card:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); |
| } |
| .progress-ring__circle { |
| transition: stroke-dashoffset 0.5s; |
| transform: rotate(-90deg); |
| transform-origin: 50% 50%; |
| } |
| .animate-bounce-slow { |
| animation: bounce 3s infinite; |
| } |
| @keyframes bounce { |
| 0%, 100% { transform: translateY(0); } |
| 50% { transform: translateY(-10px); } |
| } |
| </style> |
| </head> |
| <body class="gradient-bg min-h-screen font-sans"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <header class="text-center mb-12"> |
| <h1 class="text-4xl font-bold text-indigo-800 mb-2">NutriCalc</h1> |
| <p class="text-lg text-gray-600">Votre calculateur de calories intelligent</p> |
| <div class="w-24 h-1 bg-indigo-500 mx-auto mt-4 rounded-full"></div> |
| </header> |
|
|
| |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-12"> |
| |
| <div class="bg-white rounded-xl shadow-lg p-6 lg:col-span-1"> |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-user-circle text-indigo-500 mr-3"></i> Vos Informations |
| </h2> |
| |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-gray-700 mb-2">Sexe</label> |
| <div class="flex space-x-4"> |
| <button id="male" class="gender-btn px-4 py-2 rounded-lg border border-gray-300 hover:bg-indigo-50 transition">Homme</button> |
| <button id="female" class="gender-btn px-4 py-2 rounded-lg border border-gray-300 hover:bg-indigo-50 transition">Femme</button> |
| </div> |
| </div> |
| |
| <div> |
| <label for="age" class="block text-gray-700 mb-2">Âge (ans)</label> |
| <input type="number" id="age" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| </div> |
| |
| <div> |
| <label for="height" class="block text-gray-700 mb-2">Taille (cm)</label> |
| <input type="number" id="height" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| </div> |
| |
| <div> |
| <label for="weight" class="block text-gray-700 mb-2">Poids (kg)</label> |
| <input type="number" id="weight" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| </div> |
| |
| <div> |
| <label for="activity" class="block text-gray-700 mb-2">Niveau d'activité</label> |
| <select id="activity" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <option value="1.2">Sédentaire (peu ou pas d'exercice)</option> |
| <option value="1.375">Légèrement actif (1-3 jours/semaine)</option> |
| <option value="1.55">Modérément actif (3-5 jours/semaine)</option> |
| <option value="1.725">Très actif (6-7 jours/semaine)</option> |
| <option value="1.9">Extrêmement actif (sport intense + travail physique)</option> |
| </select> |
| </div> |
| |
| <div> |
| <label for="goal" class="block text-gray-700 mb-2">Objectif</label> |
| <select id="goal" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"> |
| <option value="maintain">Maintenir mon poids</option> |
| <option value="lose">Perdre du poids</option> |
| <option value="gain">Prendre du poids</option> |
| </select> |
| </div> |
| |
| <button id="calculate" class="w-full bg-indigo-600 text-white py-3 rounded-lg font-medium hover:bg-indigo-700 transition mt-6 flex items-center justify-center"> |
| <i class="fas fa-calculator mr-2"></i> Calculer mes besoins |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-lg p-6 lg:col-span-2"> |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-chart-pie text-indigo-500 mr-3"></i> Résultats |
| </h2> |
| |
| <div id="results" class="hidden"> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> |
| |
| <div class="bg-indigo-50 rounded-lg p-4 text-center"> |
| <div class="text-indigo-800 font-medium mb-2">Métabolisme de base</div> |
| <div id="bmr" class="text-3xl font-bold text-indigo-600">0</div> |
| <div class="text-sm text-gray-600 mt-1">kcal/jour</div> |
| </div> |
| |
| |
| <div class="bg-indigo-50 rounded-lg p-4 text-center"> |
| <div class="text-indigo-800 font-medium mb-2">Dépense énergétique</div> |
| <div id="tdee" class="text-3xl font-bold text-indigo-600">0</div> |
| <div class="text-sm text-gray-600 mt-1">kcal/jour</div> |
| </div> |
| |
| |
| <div class="bg-indigo-50 rounded-lg p-4 text-center"> |
| <div class="text-indigo-800 font-medium mb-2">Objectif calorique</div> |
| <div id="goal-calories" class="text-3xl font-bold text-indigo-600">0</div> |
| <div class="text-sm text-gray-600 mt-1">kcal/jour</div> |
| </div> |
| </div> |
| |
| |
| <div class="mb-8"> |
| <h3 class="text-lg font-semibold text-gray-800 mb-4">Répartition des macronutriments</h3> |
| |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> |
| |
| <div class="bg-white border border-gray-200 rounded-lg p-4"> |
| <div class="flex items-center mb-2"> |
| <div class="w-3 h-3 bg-red-500 rounded-full mr-2"></div> |
| <span class="font-medium">Protéines</span> |
| </div> |
| <div class="flex justify-between items-end"> |
| <div> |
| <div id="protein-grams" class="text-xl font-bold">0g</div> |
| <div id="protein-percent" class="text-sm text-gray-600">0%</div> |
| </div> |
| <div class="text-sm text-gray-500">4 kcal/g</div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white border border-gray-200 rounded-lg p-4"> |
| <div class="flex items-center mb-2"> |
| <div class="w-3 h-3 bg-blue-500 rounded-full mr-2"></div> |
| <span class="font-medium">Glucides</span> |
| </div> |
| <div class="flex justify-between items-end"> |
| <div> |
| <div id="carbs-grams" class="text-xl font-bold">0g</div> |
| <div id="carbs-percent" class="text-sm text-gray-600">0%</div> |
| </div> |
| <div class="text-sm text-gray-500">4 kcal/g</div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white border border-gray-200 rounded-lg p-4"> |
| <div class="flex items-center mb-2"> |
| <div class="w-3 h-3 bg-yellow-500 rounded-full mr-2"></div> |
| <span class="font-medium">Lipides</span> |
| </div> |
| <div class="flex justify-between items-end"> |
| <div> |
| <div id="fats-grams" class="text-xl font-bold">0g</div> |
| <div id="fats-percent" class="text-sm text-gray-600">0%</div> |
| </div> |
| <div class="text-sm text-gray-500">9 kcal/g</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> |
| <div class="flex flex-col items-center"> |
| <svg class="w-32 h-32"> |
| <circle class="text-gray-200" stroke-width="8" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| <circle id="protein-ring" class="progress-ring__circle text-red-500" stroke-width="8" stroke-dasharray="326.56" stroke-dashoffset="326.56" stroke-linecap="round" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| </svg> |
| <div class="mt-2 text-center"> |
| <div class="font-medium">Protéines</div> |
| <div id="protein-target" class="text-sm text-gray-600">0g cible</div> |
| </div> |
| </div> |
| |
| <div class="flex flex-col items-center"> |
| <svg class="w-32 h-32"> |
| <circle class="text-gray-200" stroke-width="8" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| <circle id="carbs-ring" class="progress-ring__circle text-blue-500" stroke-width="8" stroke-dasharray="326.56" stroke-dashoffset="326.56" stroke-linecap="round" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| </svg> |
| <div class="mt-2 text-center"> |
| <div class="font-medium">Glucides</div> |
| <div id="carbs-target" class="text-sm text-gray-600">0g cible</div> |
| </div> |
| </div> |
| |
| <div class="flex flex-col items-center"> |
| <svg class="w-32 h-32"> |
| <circle class="text-gray-200" stroke-width="8" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| <circle id="fats-ring" class="progress-ring__circle text-yellow-500" stroke-width="8" stroke-dasharray="326.56" stroke-dashoffset="326.56" stroke-linecap="round" stroke="currentColor" fill="transparent" r="52" cx="64" cy="64" /> |
| </svg> |
| <div class="mt-2 text-center"> |
| <div class="font-medium">Lipides</div> |
| <div id="fats-target" class="text-sm text-gray-600">0g cible</div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-indigo-50 rounded-lg p-4"> |
| <h3 class="text-lg font-semibold text-indigo-800 mb-3 flex items-center"> |
| <i class="fas fa-utensils text-indigo-500 mr-2"></i> Suggestions de repas |
| </h3> |
| <div id="meal-suggestion" class="text-gray-700"> |
| <p>Veuillez calculer vos besoins pour obtenir des suggestions personnalisées.</p> |
| </div> |
| </div> |
| </div> |
| |
| <div id="no-results" class="text-center py-12"> |
| <div class="animate-bounce-slow inline-block mb-6"> |
| <i class="fas fa-calculator text-6xl text-indigo-300"></i> |
| </div> |
| <h3 class="text-xl font-medium text-gray-700 mb-2">Commençons le calcul !</h3> |
| <p class="text-gray-500">Remplissez vos informations et cliquez sur "Calculer mes besoins" pour obtenir vos résultats personnalisés.</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-lg p-6 mb-12"> |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-archive text-indigo-500 mr-3"></i> Base de données alimentaire |
| </h2> |
| |
| <div class="mb-6"> |
| <div class="relative"> |
| <input type="text" id="food-search" placeholder="Rechercher un aliment..." class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 pl-10"> |
| <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4" id="food-container"> |
| |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-lg p-6"> |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-clipboard-list text-indigo-500 mr-3"></i> Journal alimentaire |
| </h2> |
| |
| <div class="mb-6"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-lg font-medium text-gray-800">Aujourd'hui</h3> |
| <div class="text-gray-600"> |
| <span id="consumed-calories">0</span> / <span id="target-calories">0</span> kcal |
| </div> |
| </div> |
| |
| <div class="h-4 bg-gray-200 rounded-full mb-2"> |
| <div id="calorie-progress" class="h-full bg-indigo-500 rounded-full" style="width: 0%"></div> |
| </div> |
| |
| <div class="grid grid-cols-4 text-center text-sm text-gray-600"> |
| <div>Protéines: <span id="consumed-protein">0</span>g</div> |
| <div>Glucides: <span id="consumed-carbs">0</span>g</div> |
| <div>Lipides: <span id="consumed-fats">0</span>g</div> |
| <div>Fibres: <span id="consumed-fiber">0</span>g</div> |
| </div> |
| </div> |
| |
| <div class="space-y-4 mb-6" id="meal-log"> |
| |
| <div class="text-center py-8 text-gray-500"> |
| <i class="fas fa-utensils text-4xl mb-3 opacity-30"></i> |
| <p>Votre journal alimentaire est vide.</p> |
| <p class="text-sm">Ajoutez des aliments pour commencer à suivre votre consommation.</p> |
| </div> |
| </div> |
| |
| <div class="flex justify-between items-center"> |
| <button id="clear-log" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition"> |
| <i class="fas fa-trash-alt mr-2"></i> Effacer le journal |
| </button> |
| <button id="save-log" class="px-6 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition"> |
| <i class="fas fa-save mr-2"></i> Sauvegarder |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const foodDatabase = [ |
| { name: "Poulet (100g)", calories: 165, protein: 31, carbs: 0, fats: 3.6, fiber: 0 }, |
| { name: "Riz brun (100g)", calories: 111, protein: 2.6, carbs: 23, fats: 0.9, fiber: 1.8 }, |
| { name: "Brocoli (100g)", calories: 34, protein: 2.8, carbs: 6.6, fats: 0.4, fiber: 2.6 }, |
| { name: "Saumon (100g)", calories: 208, protein: 20, carbs: 0, fats: 13, fiber: 0 }, |
| { name: "Oeuf (1 gros)", calories: 70, protein: 6, carbs: 0.6, fats: 5, fiber: 0 }, |
| { name: "Avocat (100g)", calories: 160, protein: 2, carbs: 8.5, fats: 14.7, fiber: 6.7 }, |
| { name: "Pomme (1 moyenne)", calories: 95, protein: 0.5, carbs: 25, fats: 0.3, fiber: 4 }, |
| { name: "Pain complet (1 tranche)", calories: 69, protein: 3.6, carbs: 12, fats: 0.9, fiber: 1.9 }, |
| { name: "Lait écrémé (250ml)", calories: 83, protein: 8, carbs: 12, fats: 0.2, fiber: 0 }, |
| { name: "Amandes (30g)", calories: 170, protein: 6, carbs: 6, fats: 15, fiber: 3.5 }, |
| { name: "Banane (1 moyenne)", calories: 105, protein: 1.3, carbs: 27, fats: 0.4, fiber: 3.1 }, |
| { name: "Fromage cottage (100g)", calories: 98, protein: 11, carbs: 3.4, fats: 4.3, fiber: 0 }, |
| ]; |
| |
| |
| const calculateBtn = document.getElementById('calculate'); |
| const resultsSection = document.getElementById('results'); |
| const noResultsSection = document.getElementById('no-results'); |
| const foodContainer = document.getElementById('food-container'); |
| const foodSearch = document.getElementById('food-search'); |
| const mealLog = document.getElementById('meal-log'); |
| const clearLogBtn = document.getElementById('clear-log'); |
| const saveLogBtn = document.getElementById('save-log'); |
| const genderBtns = document.querySelectorAll('.gender-btn'); |
| |
| |
| let userData = { |
| gender: null, |
| age: null, |
| height: null, |
| weight: null, |
| activity: 1.2, |
| goal: 'maintain' |
| }; |
| |
| |
| let dailyLog = { |
| calories: 0, |
| protein: 0, |
| carbs: 0, |
| fats: 0, |
| fiber: 0, |
| items: [] |
| }; |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const savedLog = localStorage.getItem('dailyLog'); |
| if (savedLog) { |
| dailyLog = JSON.parse(savedLog); |
| updateDailyLogDisplay(); |
| } |
| |
| |
| renderFoodItems(foodDatabase); |
| |
| |
| setupEventListeners(); |
| }); |
| |
| function setupEventListeners() { |
| |
| genderBtns.forEach(btn => { |
| btn.addEventListener('click', function() { |
| genderBtns.forEach(b => b.classList.remove('bg-indigo-500', 'text-white')); |
| this.classList.add('bg-indigo-500', 'text-white'); |
| userData.gender = this.id; |
| }); |
| }); |
| |
| |
| document.getElementById('age').addEventListener('change', function() { |
| userData.age = parseInt(this.value); |
| }); |
| |
| document.getElementById('height').addEventListener('change', function() { |
| userData.height = parseInt(this.value); |
| }); |
| |
| document.getElementById('weight').addEventListener('change', function() { |
| userData.weight = parseInt(this.value); |
| }); |
| |
| document.getElementById('activity').addEventListener('change', function() { |
| userData.activity = parseFloat(this.value); |
| }); |
| |
| document.getElementById('goal').addEventListener('change', function() { |
| userData.goal = this.value; |
| }); |
| |
| |
| calculateBtn.addEventListener('click', calculateCalories); |
| |
| |
| foodSearch.addEventListener('input', function() { |
| const searchTerm = this.value.toLowerCase(); |
| const filteredFoods = foodDatabase.filter(food => |
| food.name.toLowerCase().includes(searchTerm) |
| ); |
| renderFoodItems(filteredFoods); |
| }); |
| |
| |
| clearLogBtn.addEventListener('click', function() { |
| dailyLog = { |
| calories: 0, |
| protein: 0, |
| carbs: 0, |
| fats: 0, |
| fiber: 0, |
| items: [] |
| }; |
| updateDailyLogDisplay(); |
| localStorage.removeItem('dailyLog'); |
| }); |
| |
| |
| saveLogBtn.addEventListener('click', function() { |
| localStorage.setItem('dailyLog', JSON.stringify(dailyLog)); |
| alert('Journal sauvegardé avec succès !'); |
| }); |
| } |
| |
| function renderFoodItems(foods) { |
| foodContainer.innerHTML = ''; |
| |
| if (foods.length === 0) { |
| foodContainer.innerHTML = '<div class="col-span-3 text-center py-8 text-gray-500">Aucun aliment trouvé.</div>'; |
| return; |
| } |
| |
| foods.forEach(food => { |
| const foodCard = document.createElement('div'); |
| foodCard.className = 'food-card bg-white border border-gray-200 rounded-lg p-4 transition cursor-pointer hover:shadow-md'; |
| foodCard.innerHTML = ` |
| <div class="flex justify-between items-start mb-2"> |
| <h3 class="font-medium text-gray-800">${food.name}</h3> |
| <span class="text-sm font-semibold text-indigo-600">${food.calories} kcal</span> |
| </div> |
| <div class="grid grid-cols-4 gap-2 text-xs text-center"> |
| <div class="bg-red-50 text-red-600 px-2 py-1 rounded">P: ${food.protein}g</div> |
| <div class="bg-blue-50 text-blue-600 px-2 py-1 rounded">G: ${food.carbs}g</div> |
| <div class="bg-yellow-50 text-yellow-600 px-2 py-1 rounded">L: ${food.fats}g</div> |
| <div class="bg-green-50 text-green-600 px-2 py-1 rounded">F: ${food.fiber}g</div> |
| </div> |
| <button class="add-food-btn mt-3 w-full py-1 bg-indigo-50 text-indigo-600 text-sm rounded hover:bg-indigo-100 transition" data-food='${JSON.stringify(food)}'> |
| <i class="fas fa-plus mr-1"></i> Ajouter |
| </button> |
| `; |
| foodContainer.appendChild(foodCard); |
| |
| |
| foodCard.querySelector('.add-food-btn').addEventListener('click', function(e) { |
| e.stopPropagation(); |
| const foodData = JSON.parse(this.getAttribute('data-food')); |
| addFoodToLog(foodData); |
| }); |
| }); |
| } |
| |
| function addFoodToLog(food) { |
| dailyLog.calories += food.calories; |
| dailyLog.protein += food.protein; |
| dailyLog.carbs += food.carbs; |
| dailyLog.fats += food.fats; |
| dailyLog.fiber += food.fiber; |
| dailyLog.items.push(food); |
| |
| updateDailyLogDisplay(); |
| } |
| |
| function updateDailyLogDisplay() { |
| |
| document.getElementById('consumed-calories').textContent = dailyLog.calories; |
| document.getElementById('consumed-protein').textContent = dailyLog.protein.toFixed(1); |
| document.getElementById('consumed-carbs').textContent = dailyLog.carbs.toFixed(1); |
| document.getElementById('consumed-fats').textContent = dailyLog.fats.toFixed(1); |
| document.getElementById('consumed-fiber').textContent = dailyLog.fiber.toFixed(1); |
| |
| |
| const targetCalories = document.getElementById('goal-calories').textContent || 2000; |
| const progressPercent = Math.min((dailyLog.calories / targetCalories) * 100, 100); |
| document.getElementById('calorie-progress').style.width = `${progressPercent}%`; |
| |
| |
| if (dailyLog.items.length === 0) { |
| mealLog.innerHTML = ` |
| <div class="text-center py-8 text-gray-500"> |
| <i class="fas fa-utensils text-4xl mb-3 opacity-30"></i> |
| <p>Votre journal alimentaire est vide.</p> |
| <p class="text-sm">Ajoutez des aliments pour commencer à suivre votre consommation.</p> |
| </div> |
| `; |
| } else { |
| mealLog.innerHTML = ''; |
| dailyLog.items.forEach((item, index) => { |
| const mealItem = document.createElement('div'); |
| mealItem.className = 'flex justify-between items-center py-3 border-b border-gray-100'; |
| mealItem.innerHTML = ` |
| <div> |
| <div class="font-medium text-gray-800">${item.name}</div> |
| <div class="flex space-x-3 text-xs text-gray-500 mt-1"> |
| <span>${item.calories} kcal</span> |
| <span>P: ${item.protein}g</span> |
| <span>G: ${item.carbs}g</span> |
| <span>L: ${item.fats}g</span> |
| </div> |
| </div> |
| <button class="remove-food-btn px-2 py-1 text-red-500 hover:text-red-700 transition" data-index="${index}"> |
| <i class="fas fa-times"></i> |
| </button> |
| `; |
| mealLog.appendChild(mealItem); |
| |
| |
| mealItem.querySelector('.remove-food-btn').addEventListener('click', function() { |
| const index = parseInt(this.getAttribute('data-index')); |
| removeFoodFromLog(index); |
| }); |
| }); |
| } |
| } |
| |
| function removeFoodFromLog(index) { |
| const removedItem = dailyLog.items[index]; |
| |
| dailyLog.calories -= removedItem.calories; |
| dailyLog.protein -= removedItem.protein; |
| dailyLog.carbs -= removedItem.carbs; |
| dailyLog.fats -= removedItem.fats; |
| dailyLog.fiber -= removedItem.fiber; |
| dailyLog.items.splice(index, 1); |
| |
| updateDailyLogDisplay(); |
| } |
| |
| function calculateCalories() { |
| |
| if (!userData.gender || !userData.age || !userData.height || !userData.weight) { |
| alert('Veuillez remplir tous les champs requis.'); |
| return; |
| } |
| |
| |
| let bmr; |
| if (userData.gender === 'male') { |
| bmr = 88.362 + (13.397 * userData.weight) + (4.799 * userData.height) - (5.677 * userData.age); |
| } else { |
| bmr = 447.593 + (9.247 * userData.weight) + (3.098 * userData.height) - (4.330 * userData.age); |
| } |
| |
| |
| const tdee = bmr * userData.activity; |
| |
| |
| let goalCalories; |
| switch(userData.goal) { |
| case 'lose': |
| goalCalories = tdee - 500; |
| break; |
| case 'gain': |
| goalCalories = tdee + 500; |
| break; |
| default: |
| goalCalories = tdee; |
| } |
| |
| |
| const proteinGrams = Math.round((goalCalories * 0.3) / 4); |
| const carbsGrams = Math.round((goalCalories * 0.4) / 4); |
| const fatsGrams = Math.round((goalCalories * 0.3) / 9); |
| |
| |
| document.getElementById('bmr').textContent = Math.round(bmr); |
| document.getElementById('tdee').textContent = Math.round(tdee); |
| document.getElementById('goal-calories').textContent = Math.round(goalCalories); |
| |
| |
| document.getElementById('protein-grams').textContent = `${proteinGrams}g`; |
| document.getElementById('protein-percent').textContent = '30%'; |
| document.getElementById('carbs-grams').textContent = `${carbsGrams}g`; |
| document.getElementById('carbs-percent').textContent = '40%'; |
| document.getElementById('fats-grams').textContent = `${fatsGrams}g`; |
| document.getElementById('fats-percent').textContent = '30%'; |
| |
| |
| document.getElementById('protein-target').textContent = `${proteinGrams}g cible`; |
| document.getElementById('carbs-target').textContent = `${carbsGrams}g cible`; |
| document.getElementById('fats-target').textContent = `${fatsGrams}g cible`; |
| |
| |
| updateProgressRing('protein-ring', 30); |
| updateProgressRing('carbs-ring', 40); |
| updateProgressRing('fats-ring', 30); |
| |
| |
| let mealSuggestion = ''; |
| if (userData.goal === 'lose') { |
| mealSuggestion = ` |
| <p class="mb-2"><strong>Petit-déjeuner :</strong> Œufs brouillés avec épinards et avocat (environ 300 kcal)</p> |
| <p class="mb-2"><strong>Déjeuner :</strong> Poulet grillé avec quinoa et légumes (environ 450 kcal)</p> |
| <p class="mb-2"><strong>Dîner :</strong> Saumon avec patate douce et asperges (environ 400 kcal)</p> |
| <p class="mb-2"><strong>Collations :</strong> Yaourt grec avec baies ou amandes (environ 150-200 kcal)</p> |
| `; |
| } else if (userData.goal === 'gain') { |
| mealSuggestion = ` |
| <p class="mb-2"><strong>Petit-déjeuner :</strong> Omelette avec fromage, avocat et pain complet (environ 500 kcal)</p> |
| <p class="mb-2"><strong>Déjeuner :</strong> Steak avec riz brun et légumes sautés à l'huile d'olive (environ 600 kcal)</p> |
| <p class="mb-2"><strong>Dîner :</strong> Pâtes complètes avec sauce à la viande et fromage (environ 550 kcal)</p> |
| <p class="mb-2"><strong>Collations :</strong> Smoothie protéiné avec banane et beurre de cacahuète (environ 300 kcal)</p> |
| `; |
| } else { |
| mealSuggestion = ` |
| <p class="mb-2"><strong>Petit-déjeuner :</strong> Porridge avec fruits et noix (environ 350 kcal)</p> |
| <p class="mb-2"><strong>Déjeuner :</strong> Salade de quinoa avec poulet et vinaigrette légère (environ 450 kcal)</p> |
| <p class="mb-2"><strong>Dîner :</strong> Poisson blanc avec riz et légumes (environ 400 kcal)</p> |
| <p class="mb-2"><strong>Collations :</strong> Fruits frais ou poignée de noix (environ 100-150 kcal)</p> |
| `; |
| } |
| document.getElementById('meal-suggestion').innerHTML = mealSuggestion; |
| |
| |
| document.getElementById('target-calories').textContent = Math.round(goalCalories); |
| |
| |
| resultsSection.classList.remove('hidden'); |
| noResultsSection.classList.add('hidden'); |
| |
| |
| updateDailyLogDisplay(); |
| } |
| |
| function updateProgressRing(ringId, percent) { |
| const circle = document.getElementById(ringId); |
| const radius = circle.r.baseVal.value; |
| const circumference = radius * 2 * Math.PI; |
| const offset = circumference - (percent / 100) * circumference; |
| |
| circle.style.strokeDashoffset = offset; |
| } |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Adama99/ajd" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |