Skip to main content

MoSession

"The Workout Manager" — "I orchestrate your training"

Status: ✅ Built

MoSession manages workout session state — starting workouts, tracking progress, and completing sessions.


Purpose

  • Determine today's workout from PPL rotation
  • Create and manage workout sessions
  • Track session state (planned → in_progress → completed)
  • Calculate session metrics on completion
  • Trigger post-workout hooks (streaks, etc.)

Implementation

Code Location

/app/api/ppl/today/route.ts      → Get today's workout
/app/api/ppl/session/route.ts → Start/complete sessions

Key Operations

// Get today's workout
GET /api/ppl/today

// Start a session
POST /api/ppl/session { templateDayId }

// Complete a session
PATCH /api/ppl/session { sessionId, notes? }

Data Model

interface WorkoutSession {
id: string;
userId: string;
templateDayId: string;
sessionNumber: number; // Sequential session count

// State
status: SessionStatus;
startedAt: Date | null;
completedAt: Date | null;

// Metrics (calculated on completion)
totalDuration: number | null; // minutes
totalVolume: number | null; // total weight lifted
totalSets: number | null;
avgRpe: number | null;

notes: string | null;
}

type SessionStatus =
| 'planned' // Created but not started
| 'warmup' // Warmup in progress
| 'in_progress' // Main workout active
| 'completed' // Finished
| 'skipped'; // User skipped

Database Tables

CREATE TABLE workout_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
template_day_id UUID REFERENCES template_days(id),
session_number INTEGER NOT NULL,
status session_status DEFAULT 'planned',
started_at TIMESTAMP,
completed_at TIMESTAMP,
total_duration INTEGER,
total_volume DECIMAL(10,2),
total_sets INTEGER,
avg_rpe DECIMAL(3,1),
notes TEXT,
created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE session_exercises (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID REFERENCES workout_sessions(id),
exercise_id UUID REFERENCES exercises(id),
slot_id UUID REFERENCES template_slots(id),
exercise_order INTEGER NOT NULL,
target_sets INTEGER,
target_reps VARCHAR(20),
notes TEXT
);

PPL Rotation

The 6-day PPL rotation determines today's workout:

const PPL_ROTATION = [
'Push A', // Day 1
'Pull A', // Day 2
'Legs A', // Day 3
'Push B', // Day 4
'Pull B', // Day 5
'Legs B', // Day 6
];

function getTodayWorkout(lastSessionNumber: number): string {
const dayIndex = lastSessionNumber % 6;
return PPL_ROTATION[dayIndex];
}

API Endpoints

GET /api/ppl/today

Returns today's workout with slots and exercise suggestions.

{
"templateDay": {
"id": "uuid",
"name": "Push A",
"dayType": "push",
"targetMuscles": ["chest", "shoulders", "triceps"],
"estimatedDuration": 60
},
"slots": [
{
"id": "uuid",
"slotOrder": 1,
"slotType": "primary",
"movementPattern": "horizontal_push",
"sets": 4,
"repRangeMin": 6,
"repRangeMax": 8,
"rpeTarget": 8,
"suggestedExercise": {
"id": "uuid",
"name": "Barbell Bench Press"
}
}
],
"warmup": { ... },
"dayNumber": 1,
"trainingStatus": {
"fatigueScore": 4,
"fatigueLevel": "normal",
"isDeloadActive": false
}
}

POST /api/ppl/session

Starts a new workout session.

Request:

{
"templateDayId": "uuid"
}

Response:

{
"session": {
"id": "uuid",
"sessionNumber": 15,
"status": "in_progress",
"startedAt": "2024-12-22T10:00:00Z"
},
"exercises": [
{
"id": "uuid",
"exerciseId": "uuid",
"exerciseName": "Barbell Bench Press",
"targetSets": 4,
"targetReps": "6-8"
}
]
}

PATCH /api/ppl/session

Completes a session and calculates metrics.

Request:

{
"sessionId": "uuid",
"notes": "Felt strong today"
}

Response:

{
"session": {
"status": "completed",
"completedAt": "2024-12-22T11:15:00Z",
"totalDuration": 75,
"totalVolume": 15240,
"totalSets": 18,
"avgRpe": 7.5
},
"streak": {
"currentStreak": 5,
"longestStreak": 12
}
}

Session Flow

1. User opens workout page
→ GET /api/ppl/today
→ Shows day overview

2. User taps "Start Workout"
→ POST /api/ppl/session
→ Creates session, enters focused mode

3. User logs sets
→ POST /api/ppl/session/sets (for each set)
→ Updates UI with completion

4. User taps "Complete Workout"
→ PATCH /api/ppl/session
→ Calculates metrics, updates streak
→ Shows summary

Integration Points

Provides to:

  • Workout UI (session state)
  • MoStreaks (workout completion trigger)
  • Dashboard (recent sessions)
  • MoFatigue (session data for fatigue calc)

Receives from:

  • MoStrength (set data)
  • MoWarmup (warmup state)
  • Template system (workout structure)