89 lines
3.1 KiB
Markdown
89 lines
3.1 KiB
Markdown
# 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:
|
|
1. **Program Workouts** (existing): Fixed PPL structure, unchanged
|
|
2. **Custom Workouts** (new): User-built workouts with flexible sets
|
|
|
|
### Schema Additions
|
|
|
|
```sql
|
|
-- 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_type` column ('program' | 'custom') — defaults to 'program' for backward compat
|
|
- Add `custom_workout_exercise_id` column (nullable FK)
|
|
|
|
### Frontend Components
|
|
|
|
**New pages:**
|
|
- `CustomWorkoutBuilder.jsx` — search exercises, build workout, save template
|
|
- `ModifyWorkoutPage.jsx` — fork a program workout into custom
|
|
|
|
**New components:**
|
|
- `ExerciseSearchInput.jsx` — searchable exercise list
|
|
- `SetCountEditor.jsx` — +/- controls for set count
|
|
- `StepperInput.jsx` — number input with +/- buttons and unit label
|
|
|
|
**Enhanced:**
|
|
- `WorkoutSelectPage.jsx` — show both program and custom workouts
|
|
- `WorkoutPage.jsx` — flexible set count, stepper inputs
|
|
|
|
### Backend Endpoints
|
|
|
|
New:
|
|
- `POST /api/custom-workouts` — create custom workout
|
|
- `GET /api/custom-workouts` — list user's custom workouts
|
|
- `GET /api/custom-workouts/:id` — get custom workout with exercises
|
|
- `PUT /api/custom-workouts/:id` — update custom workout
|
|
- `DELETE /api/custom-workouts/:id` — delete custom workout
|
|
- `GET /api/exercises` — list all exercises (for search/selection)
|
|
|
|
Enhanced:
|
|
- `POST /api/logs` — accept both program_exercise_id and custom_workout_exercise_id
|
|
|
|
### Data Flow
|
|
|
|
1. **Program Workout** (unchanged): Dashboard → WorkoutSelectPage → WorkoutPage → logs
|
|
2. **Custom Workout Build**: Dashboard → CustomWorkoutBuilder → search exercises → save → POST /api/custom-workouts
|
|
3. **Modify Program Workout**: WorkoutPage → "Modify" → fork to custom workout → edit exercises/sets
|
|
4. **Flexible Sets**: User clicks "+Set" → local state adds entry → logs all sets on save
|
|
|
|
## Build Order
|
|
|
|
1. **Input UX fixes** — stepper inputs, validation, units (no backend changes)
|
|
2. **Flexible sets** — local state for set count, backend accepts variable sets
|
|
3. **Exercise list endpoint** — GET /api/exercises for search
|
|
4. **Custom workout CRUD** — new tables + endpoints
|
|
5. **Custom workout builder UI** — frontend page + components
|
|
6. **Modify program workout** — fork program workout to custom
|
|
|
|
Each phase builds on the previous. Phase 1 can ship independently.
|