diff --git a/csv files/back_202603181941.csv b/csv files/back_202603181941.csv new file mode 100644 index 0000000..b85cc4b --- /dev/null +++ b/csv files/back_202603181941.csv @@ -0,0 +1,37 @@ +date,group,type,exercise,set,weight,reps,notes +2024-11-21,Primary,Back,One-arm row,1,40,8, +2024-11-21,Secondary,Arms,Hammer curl,1,20,8, +2024-11-21,Core,Core,Swiss-ball crunch,1,0,25, +2024-11-21,Primary,Back,One-arm row,2,40,8, +2024-11-21,Secondary,Arms,Hammer curl,2,20,8, +2024-11-21,Core,Core,Swiss-ball crunch,2,0,25, +2024-11-21,Primary,Back,One-arm row,3,40,8, +2024-11-21,Secondary,Arms,Hammer curl,3,20,8, +2024-11-21,Core,Core,Swiss-ball crunch,3,0,25, +2024-11-21,Primary,Back,One-arm row,4,40,8,SS 35 30 +2024-11-21,Secondary,Arms,Hammer curl,4,20,8,SS 15 10 +2024-11-21,Core,Core,Swiss-ball crunch,4,0,25, +2024-11-21,Primary,Back,Lat pulldown,1,90,8, +2024-11-21,Secondary,Arms,Concentration dumbbell curl,1,15,8, +2024-11-21,Core,Core,Decline twisting ab crunch,1,0,10, +2024-11-21,Primary,Back,Lat pulldown,2,90,8, +2024-11-21,Secondary,Arms,Concentration dumbbell curl,2,15,8, +2024-11-21,Core,Core,Decline twisting ab crunch,2,0,10, +2024-11-21,Primary,Back,Lat pulldown,3,90,8, +2024-11-21,Secondary,Arms,Concentration dumbbell curl,3,15,8, +2024-11-21,Core,Core,Decline twisting ab crunch,3,0,10, +2024-11-21,Primary,Back,Lat pulldown,4,90,8,SS 80 70 +2024-11-21,Secondary,Arms,Concentration dumbbell curl,4,15,8,SS 12.5 10 +2024-11-21,Core,Core,Decline twisting ab crunch,4,0,10, +2024-11-21,Primary,Back,Cable seated close row,1,70,8, +2024-11-21,Secondary,Arms,Cable Underhand Close Grip Pulldown,1,70,8, +2024-11-21,Core,Core,Abdominal reverse curl,1,0,10, +2024-11-21,Primary,Back,Cable seated close row,2,70,8, +2024-11-21,Secondary,Arms,Cable Underhand Close Grip Pulldown,2,70,8, +2024-11-21,Core,Core,Abdominal reverse curl,2,0,10, +2024-11-21,Primary,Back,Cable seated close row,3,70,8, +2024-11-21,Secondary,Arms,Cable Underhand Close Grip Pulldown,3,70,8, +2024-11-21,Core,Core,Abdominal reverse curl,3,0,10, +2024-11-21,Primary,Back,Cable seated close row,4,70,8,SS 60 50 +2024-11-21,Secondary,Arms,Cable Underhand Close Grip Pulldown,4,70,8,SS 60 50 +2024-11-21,Core,Core,Abdominal reverse curl,4,0,10, diff --git a/csv files/chest_202603181941.csv b/csv files/chest_202603181941.csv new file mode 100644 index 0000000..5a48082 --- /dev/null +++ b/csv files/chest_202603181941.csv @@ -0,0 +1,37 @@ +date,group,type,exercise,set,weight,reps,notes +2024-11-21,Primary,Chest,Barbell bench press,1,40,8, +2024-11-21,Secondary,Arms,Triceps kickback,1,15,8, +2024-11-21,Core,Core,Swiss-ball crunch,1,0,25, +2024-11-21,Primary,Chest,Barbell bench press,2,40,8, +2024-11-21,Secondary,Arms,Triceps kickback,2,15,8, +2024-11-21,Core,Core,Swiss-ball crunch,2,0,25, +2024-11-21,Primary,Chest,Barbell bench press,3,40,8, +2024-11-21,Secondary,Arms,Triceps kickback,3,15,8, +2024-11-21,Core,Core,Swiss-ball crunch,3,0,25, +2024-11-21,Primary,Chest,Barbell bench press,4,40,8,SS 35 30 +2024-11-21,Secondary,Arms,Triceps kickback,4,15,8,SS 12.5 10 +2024-11-21,Core,Core,Swiss-ball crunch,4,0,25, +2024-11-21,Primary,Chest,Decline dumbbell bench press,1,35,8, +2024-11-21,Secondary,Core,Decline twisting ab crunch,1,0,10, +2024-11-21,Core,Arms,Cable triceps pushdown,1,35,8, +2024-11-21,Primary,Chest,Decline dumbbell bench press,2,35,8, +2024-11-21,Secondary,Core,Decline twisting ab crunch,2,0,10, +2024-11-21,Core,Arms,Cable triceps pushdown,2,35,8, +2024-11-21,Primary,Chest,Decline dumbbell bench press,3,35,8, +2024-11-21,Secondary,Core,Decline twisting ab crunch,3,0,10, +2024-11-21,Core,Arms,Cable triceps pushdown,3,35,8, +2024-11-21,Primary,Chest,Decline dumbbell bench press,4,35,8,SS 30 25 +2024-11-21,Secondary,Core,Decline twisting ab crunch,4,0,10, +2024-11-21,Core,Arms,Cable triceps pushdown,4,35,8,SS 30 25 +2024-11-21,Primary,Chest,Incline dumbbell fly,1,15,8, +2024-11-21,Secondary,Arms,Standing single-arm triceps extension,1,15,8, +2024-11-21,Core,Core,Abdominal reverse curl,1,0,10, +2024-11-21,Primary,Chest,Incline dumbbell fly,2,15,8, +2024-11-21,Secondary,Arms,Standing single-arm triceps extension,2,15,8, +2024-11-21,Core,Core,Abdominal reverse curl,2,0,10, +2024-11-21,Primary,Chest,Incline dumbbell fly,3,15,8, +2024-11-21,Secondary,Arms,Standing single-arm triceps extension,3,15,8, +2024-11-21,Core,Core,Abdominal reverse curl,3,0,10, +2024-11-21,Primary,Chest,Incline dumbbell fly,4,15,8,SS 12.5 10 +2024-11-21,Secondary,Arms,Standing single-arm triceps extension,4,15,8,SS 12.5 10 +2024-11-21,Core,Core,Abdominal reverse curl,4,0,10, diff --git a/csv files/exercises_202603181942.csv b/csv files/exercises_202603181942.csv new file mode 100644 index 0000000..24e2faf --- /dev/null +++ b/csv files/exercises_202603181942.csv @@ -0,0 +1,67 @@ +exercise,type,group +Cable biceps curl,Arms,Secondary +Cable triceps pushdown,Arms,Secondary +Cable Underhand Close Grip Pulldown,Arms,Secondary +Chair dip (no weights),Arms,Secondary +Concentration dumbbell curl,Arms,Secondary +Drag curl,Arms,Secondary +Dumbbell biceps curl,Arms,Secondary +Dumbbell row kickback,Arms,Secondary +Hammer curl,Arms,Secondary +Kettlebell pullover,Arms,Secondary +Lying triceps extension,Arms,Secondary +Machine biceps curl,Arms,Secondary +Overhead bar press,Arms,Secondary +Prone curl,Arms,Secondary +Seated preacher curl,Arms,Secondary +Standing biceps curl,Arms,Secondary +Standing single-arm triceps extension,Arms,Secondary +Triceps kickback,Arms,Secondary +Assisted pull-up,Back,Primary +Barbell bent-over row,Back,Primary +Cable seated close row,Back,Primary +Cable seated low row,Back,Primary +Dumbbell upright row,Back,Primary +Incline y raise,Back,Primary +Lat pulldown,Back,Primary +One-arm row,Back,Primary +Seated reverse fly,Back,Primary +Barbell bench press,Chest,Primary +Cable diagonal raise,Chest,Primary +Decline dumbbell bench press,Chest,Primary +Decline dumbbell fly,Chest,Primary +Dumbbell bench press,Chest,Primary +Dumbbell incline bench press,Chest,Primary +Incline dumbbell fly,Chest,Primary +Machine chest flye,Chest,Primary +Ab crunch on a ball,Core,Core +Abdominal reverse curl,Core,Core +Bench leg raise,Core,Core +Bicycle kick,Core,Core +Decline twisting ab crunch,Core,Core +Elevated-feet plank,Core,Core +Jackknife,Core,Core +Kettlebell russian twist,Core,Core +Plank,Core,Core +Russian twist,Core,Core +Side plank,Core,Core +Superman,Core,Core +Swiss-ball crunch,Core,Core +Swiss-ball glute bridge,Core,Core +Twisting windmill,Core,Core +Two-point bridge,Core,Core +Burpees,HIIT,Core +Mountain climbers,HIIT,Core +Squat Jump,HIIT,Core +Assisted dumbbell lunge,Legs,Primary +Back squat,Legs,Primary +Beginner squat,Legs,Primary +Bulgarian split squat (no weights),Legs,Primary +Dumbbell lunge,Legs,Primary +Machine leg curl,Legs,Primary +Machine leg extension,Legs,Primary +Machine leg press,Legs,Primary +Dumbbell front raise,Shoulders,Secondary +Dumbbell lateral raise,Shoulders,Secondary +Seated dumbbell shoulder press,Shoulders,Secondary +Shrug,Shoulders,Secondary diff --git a/csv files/legs_202603181942.csv b/csv files/legs_202603181942.csv new file mode 100644 index 0000000..107138a --- /dev/null +++ b/csv files/legs_202603181942.csv @@ -0,0 +1,49 @@ +date,group,type,exercise,set,weight,reps,notes +2024-11-21,Primary,Shoulders,Dumbbell front raise,1,15,10, +2024-11-21,Secondary,Legs,Dumbbell Lunge,1,5,8, +2024-11-21,Core,Core,Decline twisting ab crunch,1,0,10, +2024-11-21,Primary,Shoulders,Dumbbell front raise,2,15,10, +2024-11-21,Secondary,Legs,Dumbbell lunge,2,5,8, +2024-11-21,Core,Core,Decline twisting ab crunch,2,0,10, +2024-11-21,Primary,Shoulders,Dumbbell front raise,3,15,10, +2024-11-21,Secondary,Legs,Dumbbell lunge,3,5,8, +2024-11-21,Core,Core,Decline twisting ab crunch,3,0,10, +2024-11-21,Primary,Shoulders,Dumbbell front raise,4,15,10, +2024-11-21,Secondary,Legs,Dumbbell lunge,4,5,8, +2024-11-21,Core,Core,Decline twisting ab crunch,4,0,10, +2024-11-21,Primary,Legs,Back squat,1,50,8, +2024-11-21,Secondary,Shoulders,Seated dumbbell shoulder press,1,20,8, +2024-11-21,Core,Core,Swiss-ball glute bridge,1,0,10, +2024-11-21,Primary,Legs,Back squat,2,50,8, +2024-11-21,Secondary,Shoulders,Seated dumbbell shoulder press,2,20,8, +2024-11-21,Core,Core,Swiss-ball glute bridge,2,0,10, +2024-11-21,Primary,Legs,Back squat,3,50,8, +2024-11-21,Secondary,Shoulders,Seated dumbbell shoulder press,3,20,8, +2024-11-21,Core,Core,Swiss-ball glute bridge,3,0,10, +2024-11-21,Primary,Legs,Back squat,4,50,8, +2024-11-21,Secondary,Shoulders,Seated dumbbell shoulder press,4,20,8, +2024-11-21,Core,Core,Swiss-ball glute bridge,4,0,10, +2024-11-21,Primary,Legs,Machine leg extension,1,75,8, +2024-11-21,Secondary,Shoulders,Dumbbell lateral raise,1,10,8, +2024-11-21,Core,Core,Abdominal reverse curl,1,0,10, +2024-11-21,Primary,Legs,Machine leg extension,2,75,8, +2024-11-21,Secondary,Shoulders,Dumbbell lateral raise,2,10,8, +2024-11-21,Core,Core,Abdominal reverse curl,2,0,10, +2024-11-21,Primary,Legs,Machine leg extension,3,75,8, +2024-11-21,Secondary,Shoulders,Dumbbell lateral raise,3,10,8, +2024-11-21,Core,Core,Abdominal reverse curl,3,0,10, +2024-11-21,Primary,Legs,Machine leg extension,4,75,8, +2024-11-21,Secondary,Shoulders,Dumbbell lateral raise,4,10,8, +2024-11-21,Core,Core,Abdominal reverse curl,4,0,10, +2024-11-21,Primary,Legs,Machine leg curl,1,35,8, +2024-11-21,Secondary,Shoulders,Shrug,1,40,8, +2024-11-21,Core,Core,Swiss-ball crunch,1,0,20, +2024-11-21,Primary,Legs,Machine leg curl,2,35,8, +2024-11-21,Secondary,Shoulders,Shrug,2,40,8, +2024-11-21,Core,Core,Swiss-ball crunch,2,0,20, +2024-11-21,Primary,Legs,Machine leg curl,3,35,8, +2024-11-21,Secondary,Shoulders,Shrug,3,40,8, +2024-11-21,Core,Core,Swiss-ball crunch,3,0,20, +2024-11-21,Primary,Legs,Machine leg curl,4,35,8, +2024-11-21,Secondary,Shoulders,Shrug,4,40,8, +2024-11-21,Core,Core,Swiss-ball crunch,4,0,20, diff --git a/zed_workouts/tracker/templates/tracker/index.html b/zed_workouts/tracker/templates/tracker/index.html index 2664094..8a1c693 100644 --- a/zed_workouts/tracker/templates/tracker/index.html +++ b/zed_workouts/tracker/templates/tracker/index.html @@ -160,8 +160,8 @@ Exercise - Group - Set + Group + Set Reps Weight Note @@ -212,7 +212,7 @@ Exercise - Set + Set Reps Weight @@ -231,6 +231,26 @@ const exercises = {{ exercises_json|safe }}; const templates = {{ templates_json|safe }}; + // Object to track if a user has explicitly made a selection for a dropdown + const userMadeSelection = { + primarySelect: false, + secondarySelect: false, + coreSelect: false + }; + + // Add event listeners to track user selections when the DOM is fully loaded + document.addEventListener('DOMContentLoaded', function() { + document.getElementById('primarySelect').addEventListener('change', () => { + userMadeSelection.primarySelect = true; + }); + document.getElementById('secondarySelect').addEventListener('change', () => { + userMadeSelection.secondarySelect = true; + }); + document.getElementById('coreSelect').addEventListener('change', () => { + userMadeSelection.coreSelect = true; + }); + }); + function filterExercises() { const template = document.getElementById('templateSelect').value; document.getElementById('formTemplateName').value = template; @@ -248,7 +268,7 @@ function populateDropdown(id, group, types) { const select = document.getElementById(id); - select.innerHTML = ''; + select.innerHTML = ''; // Changed default option to "None" exercises.forEach(ex => { if (ex.group === group && (types.length === 0 || types.includes(ex.type))) { const opt = document.createElement('option'); @@ -277,10 +297,10 @@ return ` ${exName} - ${group} - ${set} + ${group} + ${set} - + `; } @@ -301,7 +321,12 @@ function setDropdownIfEmpty(id, value) { const select = document.getElementById(id); - if (select && select.value === "") select.value = value; + // Only set the value if the dropdown is currently "None" (empty value) + // AND the user has not explicitly made a selection for this dropdown before. + // This prevents overwriting a user's explicit "None" choice or another selection. + if (select && select.value === "" && !userMadeSelection[id]) { + select.value = value; + } } function generateTable() { @@ -315,13 +340,17 @@ { el: document.getElementById('coreSelect'), group: 'Core' } ]; - if (selects.some(s => !s.el.value)) { alert("Select 3 exercises"); return; } + // Removed the check that required 3 exercises to be selected, allowing "None" + // if (selects.some(s => !s.el.value)) { alert("Select 3 exercises"); return; } for (let set = 1; set <= 4; set++) { selects.forEach(s => { - const opt = s.el.options[s.el.selectedIndex]; - const match = templateData.find(row => row.exercise === s.el.value && row.set === set); - tbody.insertAdjacentHTML('beforeend', getRowHtml(s.el.value, s.group, opt.dataset.type, set, match?.reps || 0, match?.weight || 0, match?.notes || '')); + // Only generate rows for exercises that are actually selected (not "None") + if (s.el.value) { + const opt = s.el.options[s.el.selectedIndex]; + const match = templateData.find(row => row.exercise === s.el.value && row.set === set); + tbody.insertAdjacentHTML('beforeend', getRowHtml(s.el.value, s.group, opt.dataset.type, set, match?.reps || 0, match?.weight || 0, match?.notes || '')); + } }); } } @@ -362,7 +391,7 @@ nt: row.querySelector('.d-nt').value }; - logBody.insertAdjacentHTML('beforeend', `${data.ex}${data.st}${data.rp}${data.wt}`); + logBody.insertAdjacentHTML('beforeend', `${data.ex}${data.st}${data.rp}${data.wt}`); hiddenDiv.insertAdjacentHTML('beforeend', ` diff --git a/zed_workouts/tracker/views.py b/zed_workouts/tracker/views.py index b9664b7..298cf50 100644 --- a/zed_workouts/tracker/views.py +++ b/zed_workouts/tracker/views.py @@ -1,64 +1,65 @@ -from django.shortcuts import render, redirect -from django.db import transaction -from .models import Exercise, Workout, ChestTemplate, BackTemplate, LegsTemplate import json from datetime import date + from django.core.serializers.json import DjangoJSONEncoder +from django.db import transaction +from django.shortcuts import redirect, render + +from .models import BackTemplate, ChestTemplate, Exercise, LegsTemplate, Workout + def workout_tracker(request): template_models = { - 'Chest': ChestTemplate, - 'Back': BackTemplate, - 'Legs': LegsTemplate, + "Chest": ChestTemplate, + "Back": BackTemplate, + "Legs": LegsTemplate, } - if request.method == 'POST': + if request.method == "POST": # Data comes in as lists from the form - selected_template = request.POST.get('template_name') - exercises = request.POST.getlist('exercise[]') - groups = request.POST.getlist('group[]') - types = request.POST.getlist('type[]') - sets = request.POST.getlist('set[]') - weights = request.POST.getlist('weight[]') - reps = request.POST.getlist('reps[]') - notes = request.POST.getlist('notes[]') + selected_template = request.POST.get("template_name") + exercises = request.POST.getlist("exercise[]") + groups = request.POST.getlist("group[]") + types = request.POST.getlist("type[]") + sets = request.POST.getlist("set[]") + weights = request.POST.getlist("weight[]") + reps = request.POST.getlist("reps[]") + notes = request.POST.getlist("notes[]") TemplateModel = template_models.get(selected_template) if TemplateModel and exercises: with transaction.atomic(): - # 1. Clear the specific Template table to replace with new data - TemplateModel.objects.all().delete() - - # 2. Iterate and save to both Workouts (History) and Template (Current) + # Iterate and save to Workouts (History) only for i in range(len(exercises)): row_data = { - 'group': groups[i], - 'type': types[i], - 'exercise': exercises[i], - 'set': int(sets[i]), - 'weight': float(weights[i] or 0), - 'reps': int(reps[i] or 0), - 'notes': notes[i] + "group": groups[i], + "type": types[i], + "exercise": exercises[i], + "set": int(sets[i]), + "weight": float(weights[i] or 0), + "reps": int(reps[i] or 0), + "notes": notes[i], } - + # Save to history Workout.objects.create(**row_data) - # Save to template (date will auto-set to today) - TemplateModel.objects.create(**row_data) - return redirect('workout_tracker') + return redirect("workout_tracker") # GET: Fetch exercises for dropdowns - exercises = list(Exercise.objects.values('exercise', 'type', 'group')) + exercises = list(Exercise.objects.values("exercise", "type", "group")) # Fetch current template data to seed the view templates_data = { - name: list(model.objects.values()) - for name, model in template_models.items() + name: list(model.objects.values()) for name, model in template_models.items() } - return render(request, 'tracker/index.html', { - 'exercises_json': json.dumps(exercises), - 'templates_json': json.dumps(templates_data, cls=DjangoJSONEncoder) - }) + return render( + request, + "tracker/index.html", + { + "exercises_json": json.dumps(exercises), + "templates_json": json.dumps(templates_data, cls=DjangoJSONEncoder), + }, + )