WorkOutPro / index.html
Shreyas1441AI's picture
Update index.html
cffe3e2 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SweatSculpt Supreme - Your Digital Fitness Coach</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.waves.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
}
.glow-text {
text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
}
.exercise-card {
transition: all 0.3s ease;
}
.exercise-card:hover {
transform: translateY(-2px);
}
.current-exercise {
box-shadow: 0 0 15px rgba(255, 215, 0, 0.7);
transform: scale(1.02);
}
.completed-exercise {
opacity: 0.6;
background-color: #f3f4f6;
}
.neon-timer {
text-shadow: 0 0 10px #00ff9d, 0 0 20px #00ff9d;
}
.scroll-container {
scroll-behavior: smooth;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen">
<div id="vanta-bg" class="fixed inset-0 -z-10"></div>
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-10">
<h1 class="text-4xl md:text-5xl font-bold mb-2 glow-text">SweatSculpt Supreme</h1>
<p class="text-xl text-gray-300">Your digital yoga and fitness companion</p>
<p id="routine-indicator" class="text-lg text-cyan-300 mt-2"></p> <div class="flex justify-center mt-4">
<div class="w-24 h-1 bg-gradient-to-r from-blue-400 to-green-400 rounded-full"></div>
</div>
</header>
<div class="flex flex-col lg:flex-row gap-8">
<div class="w-full lg:w-1/3 bg-gray-800 bg-opacity-70 rounded-xl p-6 shadow-lg">
<h2 class="text-2xl font-semibold mb-4 flex items-center">
<i data-feather="list" class="mr-2"></i> Workout Plan
</h2>
<div class="scroll-container max-h-[500px] overflow-y-auto pr-2">
<div id="exercise-list" class="space-y-3">
</div>
</div>
</div>
<div class="w-full lg:w-2/3 bg-gray-800 bg-opacity-70 rounded-xl p-6 shadow-lg">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold flex items-center">
<i data-feather="info" class="mr-2"></i> Instructions
</h2>
<div class="flex items-center space-x-4">
<button id="music-toggle" class="p-2 rounded-full bg-gray-700 hover:bg-gray-600 transition">
<i data-feather="music"></i>
</button>
<button id="tts-toggle" class="p-2 rounded-full bg-gray-700 hover:bg-gray-600 transition">
<i data-feather="volume-2"></i>
</button>
</div>
</div>
<div id="exercise-instructions" class="bg-gray-700 bg-opacity-50 rounded-lg p-4 mb-6 h-64 overflow-y-auto">
<p class="text-gray-300 italic">Select an exercise to begin or click Start Workout</p>
</div>
<div class="bg-gray-700 bg-opacity-50 rounded-lg p-6 mb-6">
<div class="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
<div class="text-center">
<div class="text-sm text-gray-400 mb-1">Current Exercise</div>
<div id="current-exercise-name" class="text-xl font-semibold">-</div>
</div>
<div class="text-center">
<div class="text-sm text-gray-400 mb-1">Time Remaining</div>
<div id="timer" class="text-4xl font-bold neon-timer">00:00</div>
</div>
<div class="text-center">
<div class="text-sm text-gray-400 mb-1">Progress</div>
<div id="progress-text" class="text-xl font-semibold">0/0</div>
</div>
</div>
</div>
<div class="mb-6">
<div class="flex justify-between text-sm text-gray-400 mb-1">
<span>Workout Progress</span>
<span id="progress-percent">0%</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-3">
<div id="progress-bar" class="bg-gradient-to-r from-blue-500 to-green-500 h-3 rounded-full" style="width: 0%"></div>
</div>
</div>
<div class="flex flex-col sm:flex-row justify-center space-y-3 sm:space-y-0 sm:space-x-4">
<button id="start-btn" class="px-8 py-3 bg-gradient-to-r from-blue-500 to-green-500 rounded-full font-bold hover:from-blue-600 hover:to-green-600 transition transform hover:scale-105 shadow-lg">
<i data-feather="play" class="mr-2"></i> Start Workout
</button>
<button id="pause-btn" class="px-8 py-3 bg-yellow-500 rounded-full font-bold hover:bg-yellow-600 transition transform hover:scale-105 shadow-lg hidden">
<i data-feather="pause" class="mr-2"></i> Pause
</button>
<button id="skip-btn" class="px-8 py-3 bg-red-500 rounded-full font-bold hover:bg-red-600 transition transform hover:scale-105 shadow-lg hidden">
<i data-feather="skip-forward" class="mr-2"></i> Skip
</button>
</div>
</div>
</div>
<audio id="background-music" loop>
<source src="background.mp3" type="audio/mpeg">
</audio>
</div>
<script>
// Initialize
feather.replace();
// Vanta.js background
VANTA.WAVES({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x0a0a0a,
shininess: 35.00,
waveHeight: 15.00,
waveSpeed: 0.75,
zoom: 0.65
});
// --- MODIFICATION START ---
// Auto-detect morning/evening for Suryanamaskar rounds
const currentHour = new Date().getHours();
const isEvening = currentHour >= 16; // Evening is defined as 4 PM (16:00) or later
const suryanamaskarRounds = isEvening ? 6 : 12;
// Update UI indicator
const routineIndicator = document.getElementById('routine-indicator');
if (routineIndicator) {
routineIndicator.textContent = `✨ ${isEvening ? 'Evening Routine' : 'Morning Routine'} Activated (${suryanamaskarRounds} Suryanamaskars)`;
}
// --- MODIFICATION END ---
// Exercise Data
const exercises = [
// Warm-up
{ name: "Light jogging/brisk walk", type: "warmup", duration: 300, tips: "Keep posture upright, Breathe deeply" },
{ name: "Neck rotations", type: "warmup", duration: 60, tips: "Move slowly, Don't strain neck" },
{ name: "Shoulder rotations", type: "warmup", duration: 60, tips: "Keep shoulders relaxed" },
{ name: "Wrist rotations", type: "warmup", duration: 30, tips: "Move gently" },
{ name: "Ankle rotations", type: "warmup", duration: 30, tips: "Support yourself if needed" },
{ name: "Gentle stretching", type: "warmup", duration: 120, tips: "Do not bounce, Feel the stretch" },
{ name: "Short break", type: "warmup", duration: 30, tips: "Relax shoulders, Sip water" },
// Suryanamaskar (Dynamic rounds based on time of day)
...Array.from({ length: suryanamaskarRounds }, (_, round) => [
{ name: `Round ${round+1}: Pranamasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Hasta Uttanasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Padahastasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Ashwa Sanchalanasana (Right Leg)`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Dandasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Ashtanga Namaskara`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Bhujangasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Adho Mukha Svanasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Ashwa Sanchalanasana (Left Leg)`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Padahastasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Hasta Uttanasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" },
{ name: `Round ${round+1}: Pranamasana`, type: "suryanamaskar", duration: 5, tips: "Focus on breathing, Keep core engaged" }
]).flat(),
{ name: "Short break", type: "warmup", duration: 30, tips: "Relax shoulders, Sip water" },
{ name: "Kapalabhati", type: "postworkout", duration: 60, tips: "Focus on breath, Relax shoulders" },
{ name: "Anulom Vilom", type: "postworkout", duration: 180, tips: "Inhale left, Exhale right calmly" },
{ name: "Bhramari Pranayama", type: "postworkout", duration: 90, tips: "Use gentle humming sound" },
{ name: "Meditation / Deep Breathing", type: "postworkout", duration: 300, tips: "Sit comfortably, Focus on stillness" },
{ name: "Shavasana (Final Relaxation)", type: "postworkout", duration: 300, tips: "Completely relax body and mind" }
];
// App State
let currentExerciseIndex = 0;
let timerInterval;
let secondsRemaining = 0;
let isWorkoutRunning = false;
let isPaused = false;
let isTTSEnabled = true;
let isMusicEnabled = false;
const audioElement = document.getElementById('background-music');
const synth = window.speechSynthesis;
// DOM Elements
const exerciseListElement = document.getElementById('exercise-list');
const instructionsElement = document.getElementById('exercise-instructions');
const timerElement = document.getElementById('timer');
const currentExerciseNameElement = document.getElementById('current-exercise-name');
const progressTextElement = document.getElementById('progress-text');
const progressPercentElement = document.getElementById('progress-percent');
const progressBarElement = document.getElementById('progress-bar');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');
const skipBtn = document.getElementById('skip-btn');
const musicToggleBtn = document.getElementById('music-toggle');
const ttsToggleBtn = document.getElementById('tts-toggle');
// Initialize Exercise List
function renderExerciseList() {
exerciseListElement.innerHTML = '';
exercises.forEach((exercise, index) => {
const card = document.createElement('div');
card.className = `exercise-card p-4 rounded-lg cursor-pointer transition-all ${
index < currentExerciseIndex ? 'completed-exercise' :
index === currentExerciseIndex ? 'current-exercise' : 'bg-gray-700 hover:bg-gray-600'
} ${
exercise.type === 'warmup' ? 'border-l-4 border-blue-500' :
exercise.type === 'suryanamaskar' ? 'border-l-4 border-orange-500' :
'border-l-4 border-green-500'
}`;
card.innerHTML = `
<div class="flex justify-between items-center">
<div>
<h3 class="font-semibold">${exercise.name}</h3>
<p class="text-sm text-gray-400">${formatTime(exercise.duration)}</p>
</div>
${index < currentExerciseIndex ? '<i data-feather="check" class="text-green-400"></i>' : ''}
</div>
`;
card.addEventListener('click', () => skipToExercise(index));
exerciseListElement.appendChild(card);
});
feather.replace();
}
// Format time (seconds to MM:SS)
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Start Workout
function startWorkout() {
if (isWorkoutRunning) return;
isWorkoutRunning = true;
startBtn.classList.add('hidden');
pauseBtn.classList.remove('hidden');
skipBtn.classList.remove('hidden');
if (isMusicEnabled) {
audioElement.play().catch(e => console.log("Audio play failed:", e));
}
startExercise(currentExerciseIndex);
}
// Start Exercise
function startExercise(index) {
if (index >= exercises.length) {
endWorkout();
return;
}
currentExerciseIndex = index;
const exercise = exercises[index];
// Update UI
currentExerciseNameElement.textContent = exercise.name;
instructionsElement.innerHTML = `
<h3 class="text-xl font-semibold mb-2">${exercise.name}</h3>
<p class="text-gray-300 mb-4">${formatTime(exercise.duration)}</p>
<div class="bg-gray-600 rounded-lg p-3">
<h4 class="font-semibold mb-1">Tips:</h4>
<p>${exercise.tips}</p>
</div>
`;
// Speak instructions if TTS is enabled
if (isTTSEnabled) {
speakInstructions(exercise);
}
// Start timer
secondsRemaining = exercise.duration;
updateTimerDisplay();
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(updateTimer, 1000);
// Update progress
updateProgress();
// Scroll to current exercise
scrollToCurrentExercise();
// Re-render exercise list to update highlights
renderExerciseList();
}
// Update Timer
function updateTimer() {
if (isPaused) return;
secondsRemaining--;
updateTimerDisplay();
if (secondsRemaining <= 0) {
clearInterval(timerInterval);
setTimeout(() => startExercise(currentExerciseIndex + 1), 1000);
}
}
// Update Timer Display
function updateTimerDisplay() {
timerElement.textContent = formatTime(secondsRemaining);
}
// Skip to Exercise
function skipToExercise(index) {
if (!isWorkoutRunning) {
currentExerciseIndex = index;
const exercise = exercises[index];
currentExerciseNameElement.textContent = exercise.name;
instructionsElement.innerHTML = `
<h3 class="text-xl font-semibold mb-2">${exercise.name}</h3>
<p class="text-gray-300 mb-4">${formatTime(exercise.duration)}</p>
<div class="bg-gray-600 rounded-lg p-3">
<h4 class="font-semibold mb-1">Tips:</h4>
<p>${exercise.tips}</p>
</div>
`;
updateProgress();
renderExerciseList();
scrollToCurrentExercise();
return;
}
if (index <= currentExerciseIndex) return;
clearInterval(timerInterval);
startExercise(index);
}
// Pause/Resume Workout
function togglePause() {
isPaused = !isPaused;
if (isPaused) {
pauseBtn.innerHTML = '<i data-feather="play" class="mr-2"></i> Resume';
if (isMusicEnabled) {
audioElement.pause();
}
} else {
pauseBtn.innerHTML = '<i data-feather="pause" class="mr-2"></i> Pause';
if (isMusicEnabled) {
audioElement.play().catch(e => console.log("Audio play failed:", e));
}
}
feather.replace();
}
// Skip Current Exercise
function skipCurrentExercise() {
clearInterval(timerInterval);
startExercise(currentExerciseIndex + 1);
}
// End Workout
function endWorkout() {
clearInterval(timerInterval);
isWorkoutRunning = false;
startBtn.classList.remove('hidden');
pauseBtn.classList.add('hidden');
skipBtn.classList.add('hidden');
if (isMusicEnabled) {
audioElement.pause();
audioElement.currentTime = 0;
}
// Show completion message
instructionsElement.innerHTML = `
<div class="text-center py-8">
<i data-feather="award" class="w-16 h-16 text-yellow-400 mx-auto mb-4"></i>
<h3 class="text-2xl font-bold mb-2">Workout Complete!</h3>
<p class="text-gray-300">Great job! You've finished your workout.</p>
</div>
`;
feather.replace();
// Speak completion message if TTS is enabled
if (isTTSEnabled) {
const utterance = new SpeechSynthesisUtterance("Workout complete! Great job!");
synth.speak(utterance);
}
}
// Update Progress
function updateProgress() {
const percent = Math.round((currentExerciseIndex / exercises.length) * 100);
progressTextElement.textContent = `${currentExerciseIndex}/${exercises.length}`;
progressPercentElement.textContent = `${percent}%`;
progressBarElement.style.width = `${percent}%`;
}
// Scroll to Current Exercise
function scrollToCurrentExercise() {
const cards = document.querySelectorAll('.exercise-card');
if (cards[currentExerciseIndex]) {
cards[currentExerciseIndex].scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
}
// TTS Speak Instructions
function speakInstructions(exercise) {
if (synth.speaking) synth.cancel();
const exerciseMsg = new SpeechSynthesisUtterance(
`Now performing ${exercise.name}. ${exercise.tips}`
);
synth.speak(exerciseMsg);
}
// Toggle Music
function toggleMusic() {
isMusicEnabled = !isMusicEnabled;
if (isMusicEnabled) {
musicToggleBtn.innerHTML = '<i data-feather="music"></i>';
if (isWorkoutRunning && !isPaused) {
audioElement.play().catch(e => console.log("Audio play failed:", e));
}
} else {
musicToggleBtn.innerHTML = '<i data-feather="music" class="text-gray-400"></i>';
audioElement.pause();
}
feather.replace();
}
// Toggle TTS
function toggleTTS() {
isTTSEnabled = !isTTSEnabled;
if (isTTSEnabled) {
ttsToggleBtn.innerHTML = '<i data-feather="volume-2"></i>';
} else {
ttsToggleBtn.innerHTML = '<i data-feather="volume-2" class="text-gray-400"></i>';
if (synth.speaking) synth.cancel();
}
feather.replace();
}
// Event Listeners
startBtn.addEventListener('click', startWorkout);
pauseBtn.addEventListener('click', togglePause);
skipBtn.addEventListener('click', skipCurrentExercise);
musicToggleBtn.addEventListener('click', toggleMusic);
ttsToggleBtn.addEventListener('click', toggleTTS);
// Initialize
renderExerciseList();
updateProgress();
</script>
</body>
</html>