diff --git a/app.js b/app.js index 3fa1f88..6715e16 100644 --- a/app.js +++ b/app.js @@ -1322,6 +1322,163 @@ class VitruvianApp { } } } +// --- BEGIN Exercise Library with Demos --- + +const EXERCISES = { + chest: ["Bench Press","Incline Press","Chest Fly","Push-Ups","Cable Crossover","Dips","Decline Press"], + back: ["Pull-Ups","Lat Pulldown","Bent Row","Seated Row","Deadlift","Face Pulls","T-Bar Row"], + legs: ["Squats","Lunges","Leg Press","Leg Curl","Leg Extension","Calf Raises","Bulgarian Split Squat"], + shoulders: ["Overhead Press","Lateral Raise","Front Raise","Rear Delt Fly","Arnold Press","Upright Row"], + arms: ["Bicep Curl","Tricep Extension","Hammer Curl","Skull Crushers","Preacher Curl","Tricep Pushdown"], + core: ["Plank","Crunches","Russian Twist","Leg Raises","Cable Woodchop","Bicycle Crunches","Mountain Climbers"] +}; + +const EXERCISE_EMOJIS = { + 'Bench Press': '🏋️', + 'Incline Press': '🏋️', + 'Chest Fly': '💪', + 'Push-Ups': '💪', + 'Pull-Ups': '🤸', + 'Lat Pulldown': '💪', + 'Squats': '🦵', + 'Lunges': '🏃', + 'Bicep Curl': '💪', + 'Tricep Extension': '💪', + 'Overhead Press': '🏋️', + 'Plank': '🧘' +}; + +let selectedExercise = null; +let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}'); +let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]'); + +function initSidebarFeatures() { + if (!document.getElementById('exerciseList')) return; // Skip if sidebar not in HTML + renderExercises(); + renderPersonalBests(); + renderLeaderboard(); + + document.getElementById('exerciseSearch').oninput = renderExercises; + document.getElementById('muscleFilter').onchange = renderExercises; + if (document.getElementById('startBtn')) { + document.getElementById('startBtn').onclick = startWorkoutFromSidebar; + } +} + +function renderExercises() { + const search = document.getElementById('exerciseSearch').value.toLowerCase(); + const muscle = document.getElementById('muscleFilter').value; + const listEl = document.getElementById('exerciseList'); + let exercises = []; + + if (muscle === 'all') { + Object.values(EXERCISES).forEach(list => exercises.push(...list)); + } else { + exercises = EXERCISES[muscle] || []; + } + exercises = exercises.filter(ex => ex.toLowerCase().includes(search)); + + listEl.innerHTML = exercises.map(ex => { + const emoji = EXERCISE_EMOJIS[ex] || '🏃'; + return `
+ ${emoji} + ${ex} +
`; + }).join(''); +} + +window.selectExercise = function(name) { + selectedExercise = name; + if (document.getElementById('selectedExercise')) { + document.getElementById('selectedExercise').textContent = `Selected: ${name}`; + } + document.querySelectorAll('.exercise-item').forEach(item => { + const exerciseName = item.querySelector('span:last-child').textContent; + if (exerciseName === name) { + item.style.background = '#667eea'; + item.style.color = 'white'; + } else { + item.style.background = '#f5f5f5'; + item.style.color = 'black'; + } + }); + updateMuscleHeatmap(name); +}; + +function startWorkoutFromSidebar() { + if (!document.getElementById('mode')) return; + let mode = document.getElementById('mode').value; + let weight = parseFloat(document.getElementById('weight').value); + let reps = parseInt(document.getElementById('reps').value, 10); + + localStorage.setItem('vitruvian_lastworkout', + JSON.stringify({ exercise: selectedExercise, mode, weight, reps }) + ); + + console.log('Workout started:', { exercise: selectedExercise, mode, weight, reps }); +} + +function renderPersonalBests() { + const pbList = document.getElementById('pbList'); + if (!pbList) return; + const pbs = Object.entries(personalBests).slice(0, 5); + if (pbs.length === 0) { + pbList.innerHTML = '

Complete workouts to track PRs

'; + return; + } + pbList.innerHTML = pbs.map(([exercise, weight]) => + `
+ ${exercise} + ${weight}kg +
` + ).join(''); +} + +function renderLeaderboard() { + const lbList = document.getElementById('leaderboardList'); + if (!lbList) return; + const sorted = leaderboard.sort((a,b) => b.score - a.score).slice(0,5); + if (sorted.length === 0) { + lbList.innerHTML = '

No entries yet

'; + return; + } + lbList.innerHTML = sorted.map((entry, i) => + `
+ ${i+1} + ${entry.name} + ${entry.score} +
` + ).join(''); +} + +function updateMuscleHeatmap(selected) { + ['chest','shoulders-l','shoulders-r','arms-l','arms-r','core','legs-l','legs-r'].forEach(id => { + let el = document.getElementById('m-'+id); + if (el) el.setAttribute('fill', '#ddd'); + }); + if (!selected) return; + + const ex = selected.toLowerCase(); + if (ex.match(/chest|press|fly|push/)) highlight(['chest']); + else if (ex.match(/shoulder|overhead|lateral|arnold/)) highlight(['shoulders-l','shoulders-r']); + else if (ex.match(/bicep|tricep|curl|skull|hammer/)) highlight(['arms-l','arms-r']); + else if (ex.match(/core|plank|crunch|twist|woodchop/)) highlight(['core']); + else if (ex.match(/squat|lunge|leg|calf/)) highlight(['legs-l','legs-r']); + else if (ex.match(/pull|row|deadlift/)) highlight(['shoulders-l','shoulders-r','arms-l','arms-r']); + + function highlight(ids) { + ids.forEach(id => { + let el = document.getElementById('m-'+id); + if (el) el.setAttribute('fill', '#f88'); + }); + } +} + +window.addEventListener('DOMContentLoaded', () => { + initSidebarFeatures(); +}); + +// --- END Exercise Library with Demos --- // Create global app instance const app = new VitruvianApp(); @@ -1334,3 +1491,160 @@ app.addLogEntry("Requirements:", "info"); app.addLogEntry("- Chrome, Edge, or Opera browser", "info"); app.addLogEntry("- HTTPS connection (or localhost)", "info"); app.addLogEntry("- Bluetooth enabled on your device", "info"); +// --- BEGIN Exercise Library with Demos --- + +const EXERCISES = { + chest: ["Bench Press","Incline Press","Chest Fly","Push-Ups","Cable Crossover","Dips","Decline Press"], + back: ["Pull-Ups","Lat Pulldown","Bent Row","Seated Row","Deadlift","Face Pulls","T-Bar Row"], + legs: ["Squats","Lunges","Leg Press","Leg Curl","Leg Extension","Calf Raises","Bulgarian Split Squat"], + shoulders: ["Overhead Press","Lateral Raise","Front Raise","Rear Delt Fly","Arnold Press","Upright Row"], + arms: ["Bicep Curl","Tricep Extension","Hammer Curl","Skull Crushers","Preacher Curl","Tricep Pushdown"], + core: ["Plank","Crunches","Russian Twist","Leg Raises","Cable Woodchop","Bicycle Crunches","Mountain Climbers"] +}; + +const EXERCISE_EMOJIS = { + 'Bench Press': '🏋️', + 'Incline Press': '🏋️', + 'Chest Fly': '💪', + 'Push-Ups': '💪', + 'Pull-Ups': '🤸', + 'Lat Pulldown': '💪', + 'Squats': '🦵', + 'Lunges': '🏃', + 'Bicep Curl': '💪', + 'Tricep Extension': '💪', + 'Overhead Press': '🏋️', + 'Plank': '🧘' +}; + +let selectedExercise = null; +let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}'); +let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]'); + +function initSidebarFeatures() { + if (!document.getElementById('exerciseList')) return; // Skip if sidebar not in HTML + renderExercises(); + renderPersonalBests(); + renderLeaderboard(); + + document.getElementById('exerciseSearch').oninput = renderExercises; + document.getElementById('muscleFilter').onchange = renderExercises; + if (document.getElementById('startBtn')) { + document.getElementById('startBtn').onclick = startWorkoutFromSidebar; + } +} + +function renderExercises() { + const search = document.getElementById('exerciseSearch').value.toLowerCase(); + const muscle = document.getElementById('muscleFilter').value; + const listEl = document.getElementById('exerciseList'); + let exercises = []; + + if (muscle === 'all') { + Object.values(EXERCISES).forEach(list => exercises.push(...list)); + } else { + exercises = EXERCISES[muscle] || []; + } + exercises = exercises.filter(ex => ex.toLowerCase().includes(search)); + + listEl.innerHTML = exercises.map(ex => { + const emoji = EXERCISE_EMOJIS[ex] || '🏃'; + return `
+ ${emoji} + ${ex} +
`; + }).join(''); +} + +window.selectExercise = function(name) { + selectedExercise = name; + if (document.getElementById('selectedExercise')) { + document.getElementById('selectedExercise').textContent = `Selected: ${name}`; + } + document.querySelectorAll('.exercise-item').forEach(item => { + const exerciseName = item.querySelector('span:last-child').textContent; + if (exerciseName === name) { + item.style.background = '#667eea'; + item.style.color = 'white'; + } else { + item.style.background = '#f5f5f5'; + item.style.color = 'black'; + } + }); + updateMuscleHeatmap(name); +}; + +function startWorkoutFromSidebar() { + if (!document.getElementById('mode')) return; + let mode = document.getElementById('mode').value; + let weight = parseFloat(document.getElementById('weight').value); + let reps = parseInt(document.getElementById('reps').value, 10); + + localStorage.setItem('vitruvian_lastworkout', + JSON.stringify({ exercise: selectedExercise, mode, weight, reps }) + ); + + console.log('Workout started:', { exercise: selectedExercise, mode, weight, reps }); +} + +function renderPersonalBests() { + const pbList = document.getElementById('pbList'); + if (!pbList) return; + const pbs = Object.entries(personalBests).slice(0, 5); + if (pbs.length === 0) { + pbList.innerHTML = '

Complete workouts to track PRs

'; + return; + } + pbList.innerHTML = pbs.map(([exercise, weight]) => + `
+ ${exercise} + ${weight}kg +
` + ).join(''); +} + +function renderLeaderboard() { + const lbList = document.getElementById('leaderboardList'); + if (!lbList) return; + const sorted = leaderboard.sort((a,b) => b.score - a.score).slice(0,5); + if (sorted.length === 0) { + lbList.innerHTML = '

No entries yet

'; + return; + } + lbList.innerHTML = sorted.map((entry, i) => + `
+ ${i+1} + ${entry.name} + ${entry.score} +
` + ).join(''); +} + +function updateMuscleHeatmap(selected) { + ['chest','shoulders-l','shoulders-r','arms-l','arms-r','core','legs-l','legs-r'].forEach(id => { + let el = document.getElementById('m-'+id); + if (el) el.setAttribute('fill', '#ddd'); + }); + if (!selected) return; + + const ex = selected.toLowerCase(); + if (ex.match(/chest|press|fly|push/)) highlight(['chest']); + else if (ex.match(/shoulder|overhead|lateral|arnold/)) highlight(['shoulders-l','shoulders-r']); + else if (ex.match(/bicep|tricep|curl|skull|hammer/)) highlight(['arms-l','arms-r']); + else if (ex.match(/core|plank|crunch|twist|woodchop/)) highlight(['core']); + else if (ex.match(/squat|lunge|leg|calf/)) highlight(['legs-l','legs-r']); + else if (ex.match(/pull|row|deadlift/)) highlight(['shoulders-l','shoulders-r','arms-l','arms-r']); + + function highlight(ids) { + ids.forEach(id => { + let el = document.getElementById('m-'+id); + if (el) el.setAttribute('fill', '#f88'); + }); + } +} + +window.addEventListener('DOMContentLoaded', () => { + initSidebarFeatures(); +}); + +// --- END Exercise Library with Demos --- diff --git a/images/images_bench-press_Version3.svg b/images/images_bench-press_Version3.svg new file mode 100644 index 0000000..95572b1 --- /dev/null +++ b/images/images_bench-press_Version3.svg @@ -0,0 +1,11 @@ + + + + + Bench Press + placeholder demo + + + + + \ No newline at end of file diff --git a/images/images_bicep-curl_Version2.svg b/images/images_bicep-curl_Version2.svg new file mode 100644 index 0000000..b49b68f --- /dev/null +++ b/images/images_bicep-curl_Version2.svg @@ -0,0 +1,11 @@ + + + + + Bicep Curl + placeholder demo + + + + + \ No newline at end of file diff --git a/images/images_chest-fly_Version2.svg b/images/images_chest-fly_Version2.svg new file mode 100644 index 0000000..e142815 --- /dev/null +++ b/images/images_chest-fly_Version2.svg @@ -0,0 +1,9 @@ + + + + + Chest Fly + placeholder demo + + + \ No newline at end of file diff --git a/images/images_incline-press_Version2.svg b/images/images_incline-press_Version2.svg new file mode 100644 index 0000000..9c4f45d --- /dev/null +++ b/images/images_incline-press_Version2.svg @@ -0,0 +1,9 @@ + + + + + Incline Press + placeholder demo + + + \ No newline at end of file diff --git a/images/images_lat-pulldown_Version1.svg b/images/images_lat-pulldown_Version1.svg new file mode 100644 index 0000000..bf15fe8 --- /dev/null +++ b/images/images_lat-pulldown_Version1.svg @@ -0,0 +1,9 @@ + + + + + Lat Pulldown + placeholder demo + + + \ No newline at end of file diff --git a/images/images_lateral-raise_Version1.svg b/images/images_lateral-raise_Version1.svg new file mode 100644 index 0000000..8ff8c36 --- /dev/null +++ b/images/images_lateral-raise_Version1.svg @@ -0,0 +1,9 @@ + + + + + Lateral Raise + placeholder demo + + + \ No newline at end of file diff --git a/images/images_leg-press_Version1.svg b/images/images_leg-press_Version1.svg new file mode 100644 index 0000000..b54b739 --- /dev/null +++ b/images/images_leg-press_Version1.svg @@ -0,0 +1,9 @@ + + + + + Leg Press + placeholder demo + + + \ No newline at end of file diff --git a/images/images_lunge_Version1.svg b/images/images_lunge_Version1.svg new file mode 100644 index 0000000..2e91cd3 --- /dev/null +++ b/images/images_lunge_Version1.svg @@ -0,0 +1,9 @@ + + + + + Lunges + placeholder demo + + + \ No newline at end of file diff --git a/images/images_overhead-press_Version1.svg b/images/images_overhead-press_Version1.svg new file mode 100644 index 0000000..06f41a2 --- /dev/null +++ b/images/images_overhead-press_Version1.svg @@ -0,0 +1,9 @@ + + + + + Overhead Press + placeholder demo + + + \ No newline at end of file diff --git a/images/images_plank_Version2.svg b/images/images_plank_Version2.svg new file mode 100644 index 0000000..37d18dd --- /dev/null +++ b/images/images_plank_Version2.svg @@ -0,0 +1,9 @@ + + + + + Plank + placeholder demo + + + \ No newline at end of file diff --git a/images/images_pull-ups_Version2.svg b/images/images_pull-ups_Version2.svg new file mode 100644 index 0000000..b9ee338 --- /dev/null +++ b/images/images_pull-ups_Version2.svg @@ -0,0 +1,10 @@ + + + + + Pull-Ups + placeholder demo + + + + \ No newline at end of file diff --git a/images/images_russian-twist_Version1.svg b/images/images_russian-twist_Version1.svg new file mode 100644 index 0000000..c067753 --- /dev/null +++ b/images/images_russian-twist_Version1.svg @@ -0,0 +1,10 @@ + + + + + Russian Twist + placeholder demo + + + + \ No newline at end of file diff --git a/images/images_seated-row_Version1.svg b/images/images_seated-row_Version1.svg new file mode 100644 index 0000000..98c4190 --- /dev/null +++ b/images/images_seated-row_Version1.svg @@ -0,0 +1,9 @@ + + + + + Seated Row + placeholder demo + + + \ No newline at end of file diff --git a/images/images_squat_Version2.svg b/images/images_squat_Version2.svg new file mode 100644 index 0000000..eef5867 --- /dev/null +++ b/images/images_squat_Version2.svg @@ -0,0 +1,10 @@ + + + + + Squats + placeholder demo + + + + \ No newline at end of file diff --git a/images/images_tricep-pushdown_Version1.svg b/images/images_tricep-pushdown_Version1.svg new file mode 100644 index 0000000..4160da6 --- /dev/null +++ b/images/images_tricep-pushdown_Version1.svg @@ -0,0 +1,9 @@ + + + + + Tricep Pushdown + placeholder demo + + + \ No newline at end of file diff --git a/images/placeholder.txt b/images/placeholder.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/images/placeholder.txt @@ -0,0 +1 @@ + diff --git a/index.html b/index.html index 623a67d..cfcaca9 100644 --- a/index.html +++ b/index.html @@ -67,6 +67,56 @@ padding-bottom: 25px; border-bottom: 1px solid #e0e0e0; } + +
+

Exercise Library 💪

+ + +
+
+ + +
+

Workout Setup

+
Select an exercise above
+ +
+ + +
+

Personal Bests 🏆

+
+
+ + +
+

Leaderboard 🎯

+ +
+
+ + +
+

Muscle Activity Map 🔥

+ + + + + + + + + + +
.section:last-child { border-bottom: none; diff --git a/workoutmachineappfree.github.io/app.js b/workoutmachineappfree.github.io/app.js new file mode 100644 index 0000000..f870353 --- /dev/null +++ b/workoutmachineappfree.github.io/app.js @@ -0,0 +1,51 @@ +// --- BEGIN Sidebar Features and Logic --- + +const EXERCISES = { + chest: [ + { name: "Bench Press", image: "images/bench-press.gif" }, + { name: "Incline Press", image: "images/incline-press.gif" }, + { name: "Chest Fly", image: "images/chest-fly.gif" } + ], + back: [ + { name: "Pull-Ups", image: "images/pull-ups.gif" }, + { name: "Lat Pulldown", image: "images/lat-pulldown.gif" }, + { name: "Seated Row", image: "images/seated-row.gif" } + ], + legs: [ + { name: "Squats", image: "images/squat.gif" }, + { name: "Lunges", image: "images/lunge.gif" }, + { name: "Leg Press", image: "images/leg-press.gif" } + ], + shoulders: [ + { name: "Overhead Press", image: "images/overhead-press.gif" }, + { name: "Lateral Raise", image: "images/lateral-raise.gif" } + ], + arms: [ + { name: "Bicep Curl", image: "images/bicep-curl.gif" }, + { name: "Tricep Pushdown", image: "images/tricep-pushdown.gif" } + ], + core: [ + { name: "Plank", image: "images/plank.gif" }, + { name: "Russian Twist", image: "images/russian-twist.gif" } + ] +}; + +let selectedExercise = null; +let personalBests = JSON.parse(localStorage.getItem('vitruvian_pbs') || '{}'); +let leaderboard = JSON.parse(localStorage.getItem('vitruvian_leaderboard') || '[]'); + +function initSidebarFeatures() { + renderExercises(); + renderPersonalBests(); + renderLeaderboard(); + + const searchEl = document.getElementById('exerciseSearch'); + const filterEl = document.getElementById('muscleFilter'); + const startBtn = document.getElementById('startBtn'); + + if (searchEl) searchEl.oninput = renderExercises; + if (filterEl) filterEl.onchange = renderExercises; + if (startBtn) startBtn.onclick = startWorkoutFromSidebar; +} + +function escapeHtml(s){ return (s||'').toString().replace(/[&<>\ \ No newline at end of file