3.1 KiB
3.1 KiB
Architecture: Custom Workouts & Flexible Sets
Project: Gravl — PPL Workout Tracker Researched: 2026-02-15
Current State
Fixed program structure:
Users → Programs (hardcoded id=1) → Program Days (6) → Program Exercises (fixed sets) → Workout Logs
Proposed: Dual Data Paths
Two parallel workout sources:
- Program Workouts (existing): Fixed PPL structure, unchanged
- Custom Workouts (new): User-built workouts with flexible sets
Schema Additions
-- User-created workout templates
CREATE TABLE custom_workouts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- Exercises in custom workouts
CREATE TABLE custom_workout_exercises (
id SERIAL PRIMARY KEY,
custom_workout_id INTEGER REFERENCES custom_workouts(id) ON DELETE CASCADE,
exercise_id INTEGER REFERENCES exercises(id),
sets INTEGER DEFAULT 3,
sort_order INTEGER DEFAULT 0
);
Enhanced workout_logs:
- Add
source_typecolumn ('program' | 'custom') — defaults to 'program' for backward compat - Add
custom_workout_exercise_idcolumn (nullable FK)
Frontend Components
New pages:
CustomWorkoutBuilder.jsx— search exercises, build workout, save templateModifyWorkoutPage.jsx— fork a program workout into custom
New components:
ExerciseSearchInput.jsx— searchable exercise listSetCountEditor.jsx— +/- controls for set countStepperInput.jsx— number input with +/- buttons and unit label
Enhanced:
WorkoutSelectPage.jsx— show both program and custom workoutsWorkoutPage.jsx— flexible set count, stepper inputs
Backend Endpoints
New:
POST /api/custom-workouts— create custom workoutGET /api/custom-workouts— list user's custom workoutsGET /api/custom-workouts/:id— get custom workout with exercisesPUT /api/custom-workouts/:id— update custom workoutDELETE /api/custom-workouts/:id— delete custom workoutGET /api/exercises— list all exercises (for search/selection)
Enhanced:
POST /api/logs— accept both program_exercise_id and custom_workout_exercise_id
Data Flow
- Program Workout (unchanged): Dashboard → WorkoutSelectPage → WorkoutPage → logs
- Custom Workout Build: Dashboard → CustomWorkoutBuilder → search exercises → save → POST /api/custom-workouts
- Modify Program Workout: WorkoutPage → "Modify" → fork to custom workout → edit exercises/sets
- Flexible Sets: User clicks "+Set" → local state adds entry → logs all sets on save
Build Order
- Input UX fixes — stepper inputs, validation, units (no backend changes)
- Flexible sets — local state for set count, backend accepts variable sets
- Exercise list endpoint — GET /api/exercises for search
- Custom workout CRUD — new tables + endpoints
- Custom workout builder UI — frontend page + components
- Modify program workout — fork program workout to custom
Each phase builds on the previous. Phase 1 can ship independently.