added exercise table and local mysql connector. working version

This commit is contained in:
Cutty 2026-03-19 14:20:52 -06:00
parent 964c10f417
commit 014ccacb46
4 changed files with 148 additions and 0 deletions

View file

@ -0,0 +1,94 @@
# Generated by Django 6.0.3 on 2026-03-19 14:53
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='BackTemplate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(auto_now_add=True)),
('group', models.CharField(max_length=20)),
('type', models.CharField(max_length=100)),
('exercise', models.CharField(max_length=255)),
('set', models.IntegerField()),
('weight', models.DecimalField(decimal_places=2, default=0.0, max_digits=6)),
('reps', models.IntegerField(default=0)),
('notes', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'back',
},
),
migrations.CreateModel(
name='ChestTemplate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(auto_now_add=True)),
('group', models.CharField(max_length=20)),
('type', models.CharField(max_length=100)),
('exercise', models.CharField(max_length=255)),
('set', models.IntegerField()),
('weight', models.DecimalField(decimal_places=2, default=0.0, max_digits=6)),
('reps', models.IntegerField(default=0)),
('notes', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'chest',
},
),
migrations.CreateModel(
name='Exercise',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('exercise', models.CharField(max_length=255, unique=True)),
('type', models.CharField(max_length=100)),
('group', models.CharField(choices=[('Primary', 'Primary'), ('Secondary', 'Secondary'), ('Core', 'Core')], max_length=20)),
],
options={
'db_table': 'exercises',
},
),
migrations.CreateModel(
name='LegsTemplate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(auto_now_add=True)),
('group', models.CharField(max_length=20)),
('type', models.CharField(max_length=100)),
('exercise', models.CharField(max_length=255)),
('set', models.IntegerField()),
('weight', models.DecimalField(decimal_places=2, default=0.0, max_digits=6)),
('reps', models.IntegerField(default=0)),
('notes', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'legs',
},
),
migrations.CreateModel(
name='Workout',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(auto_now_add=True)),
('group', models.CharField(max_length=20)),
('type', models.CharField(max_length=100)),
('exercise', models.CharField(max_length=255)),
('set', models.IntegerField()),
('weight', models.DecimalField(decimal_places=2, default=0.0, max_digits=6)),
('reps', models.IntegerField(default=0)),
('notes', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'workouts',
},
),
]

View file

@ -11,6 +11,9 @@ class Exercise(models.Model):
type = models.CharField(max_length=100) # e.g., Chest, Back, Arms type = models.CharField(max_length=100) # e.g., Chest, Back, Arms
group = models.CharField(max_length=20, choices=GROUP_CHOICES) group = models.CharField(max_length=20, choices=GROUP_CHOICES)
class Meta:
db_table = 'exercises'
def __str__(self): def __str__(self):
return f"{self.exercise} ({self.group})" return f"{self.exercise} ({self.group})"

View file

@ -85,6 +85,7 @@
<script> <script>
const exercises = {{ exercises_json|safe }}; const exercises = {{ exercises_json|safe }};
const templates = {{ templates_json|safe }};
function filterExercises() { function filterExercises() {
const template = document.getElementById('templateSelect').value; const template = document.getElementById('templateSelect').value;
@ -101,6 +102,7 @@
populateDropdown('primarySelect', 'Primary', primaryType); populateDropdown('primarySelect', 'Primary', primaryType);
populateDropdown('secondarySelect', 'Secondary', secondaryType); populateDropdown('secondarySelect', 'Secondary', secondaryType);
populateDropdown('coreSelect', 'Core', ['Abs', 'Core']); populateDropdown('coreSelect', 'Core', ['Abs', 'Core']);
loadTemplateData(template);
} }
function populateDropdown(id, group, types) { function populateDropdown(id, group, types) {
@ -117,6 +119,38 @@
}); });
} }
function loadTemplateData(templateName) {
const tbody = document.getElementById('activeTableBody');
tbody.innerHTML = '';
const data = templates[templateName];
if (data && data.length > 0) {
data.forEach(row => {
// Try to sync dropdowns based on first occurrence
if (row.group === 'Primary') setDropdownIfEmpty('primarySelect', row.exercise);
if (row.group === 'Secondary') setDropdownIfEmpty('secondarySelect', row.exercise);
if (row.group === 'Core') setDropdownIfEmpty('coreSelect', row.exercise);
const html = `
<tr>
<td>${row.exercise}<input type="hidden" class="d-ex" value="${row.exercise}"></td>
<td>${row.group}<input type="hidden" class="d-gr" value="${row.group}">
<input type="hidden" class="d-ty" value="${row.type}"></td>
<td>${row.set}<input type="hidden" class="d-st" value="${row.set}"></td>
<td><input type="number" class="table-input d-rp" value="${row.reps}"></td>
<td><input type="number" class="table-input d-wt" step="0.5" value="${row.weight}"></td>
<td><input type="text" class="table-input d-nt" value="${row.notes || ''}" placeholder="Notes"></td>
</tr>`;
tbody.insertAdjacentHTML('beforeend', html);
});
}
}
function setDropdownIfEmpty(id, value) {
const select = document.getElementById(id);
if (select && select.value === "") select.value = value;
}
function generateTable() { function generateTable() {
const tbody = document.getElementById('activeTableBody'); const tbody = document.getElementById('activeTableBody');
tbody.innerHTML = ''; tbody.innerHTML = '';

View file

@ -80,6 +80,8 @@ WSGI_APPLICATION = 'zed_workouts.wsgi.application'
# 'NAME': BASE_DIR / 'db.sqlite3', # 'NAME': BASE_DIR / 'db.sqlite3',
# } # }
#} #}
# Database connector for docker container
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
@ -91,6 +93,21 @@ DATABASES = {
} }
} }
# Database connector for local mysql instance
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'workouts',
'USER': 'root',
'PASSWORD': 'Throwaway',
'HOST': 'localhost', # Or your DB server IP
'PORT': '3306', # Default MySQL port
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
# Password validation # Password validation
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators