Files
gravl/.planning/research/ARCHITECTURE.md
T
2026-02-15 22:48:57 +01:00

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.