Add library exercises mid-workout with plan defaults
Pick any exercise from the full library while a workout is running, not just the ones in its split. The new exercise's plan is seeded from the most recent log of that exercise, else the library's authored Defaults line, else a plain 3x10. Adds a searchable two-section picker sheet and a **Defaults:** bullet to all 47 library reference pages. Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
@@ -7,6 +7,7 @@ supported.
|
|||||||
- **Type:** Machine-based trunk flexion
|
- **Type:** Machine-based trunk flexion
|
||||||
- **Targets:** Rectus abdominis, deep core
|
- **Targets:** Rectus abdominis, deep core
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ hips and glutes.
|
|||||||
- **Type:** Machine-based hip abduction
|
- **Type:** Machine-based hip abduction
|
||||||
- **Targets:** Gluteus medius, gluteus minimus, outer thighs
|
- **Targets:** Gluteus medius, gluteus minimus, outer thighs
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ inner thighs.
|
|||||||
- **Type:** Machine-based hip adduction
|
- **Type:** Machine-based hip adduction
|
||||||
- **Targets:** Adductors, inner thighs
|
- **Targets:** Adductors, inner thighs
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the pad so only the forearms move.
|
|||||||
- **Type:** Machine-based elbow flexion (isolation)
|
- **Type:** Machine-based elbow flexion (isolation)
|
||||||
- **Targets:** Biceps brachii, brachialis
|
- **Targets:** Biceps brachii, brachialis
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the trunk back in line with the legs.
|
|||||||
- **Type:** Machine-based back extension (hip hinge)
|
- **Type:** Machine-based back extension (hip hinge)
|
||||||
- **Targets:** Spinal erectors, glutes, hamstrings
|
- **Targets:** Spinal erectors, glutes, hamstrings
|
||||||
- **Prescription:** 3 × 10–15
|
- **Prescription:** 3 × 10–15
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ heels, stand back up.
|
|||||||
- **Type:** Free-weight compound squat
|
- **Type:** Free-weight compound squat
|
||||||
- **Targets:** Quadriceps, glutes, adductors, trunk
|
- **Targets:** Quadriceps, glutes, adductors, trunk
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ and press it back to straight arms.
|
|||||||
- **Type:** Free-weight horizontal press
|
- **Type:** Free-weight horizontal press
|
||||||
- **Targets:** Chest, front delts, triceps
|
- **Targets:** Chest, front delts, triceps
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ twist.
|
|||||||
- **Type:** Anti-rotation
|
- **Type:** Anti-rotation
|
||||||
- **Targets:** Spinal erectors, glutes, deep core, shoulder stability
|
- **Targets:** Spinal erectors, glutes, deep core, shoulder stability
|
||||||
- **Prescription:** Warm-up 8 per side; main circuit 3 × 8–10 per side, slow
|
- **Prescription:** Warm-up 8 per side; main circuit 3 × 8–10 per side, slow
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ sit down between the heels. The pattern every loaded squat is built on.
|
|||||||
- **Type:** Bodyweight squat
|
- **Type:** Bodyweight squat
|
||||||
- **Targets:** Quadriceps, glutes, mobility
|
- **Targets:** Quadriceps, glutes, mobility
|
||||||
- **Prescription:** 3 × 15–20, or 10 slow reps as a warm-up
|
- **Prescription:** 3 × 15–20, or 10 slow reps as a warm-up
|
||||||
|
- **Defaults:** 3 × 15 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ a hard squeeze at the top.
|
|||||||
- **Type:** Machine-based calf raise
|
- **Type:** Machine-based calf raise
|
||||||
- **Targets:** Soleus, gastrocnemius
|
- **Targets:** Soleus, gastrocnemius
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Gentle spinal mobility drill that wakes up the whole trunk before core work.
|
|||||||
- **Type:** Spinal mobility
|
- **Type:** Spinal mobility
|
||||||
- **Targets:** Thoracic and lumbar spine, deep core awareness
|
- **Targets:** Thoracic and lumbar spine, deep core awareness
|
||||||
- **Prescription:** 10 slow reps (one rep = cat + cow)
|
- **Prescription:** 10 slow reps (one rep = cat + cow)
|
||||||
|
- **Defaults:** 3 × 10 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ forward from the chest.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based horizontal press
|
- **Type:** Machine-based horizontal press
|
||||||
- **Targets:** Pectorals, anterior deltoids, triceps
|
- **Targets:** Pectorals, anterior deltoids, triceps
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ lower. Short range, all abs.
|
|||||||
- **Type:** Spinal flexion (upper)
|
- **Type:** Spinal flexion (upper)
|
||||||
- **Targets:** Rectus abdominis
|
- **Targets:** Rectus abdominis
|
||||||
- **Prescription:** 3 × 15–20, slow
|
- **Prescription:** 3 × 15–20, slow
|
||||||
|
- **Defaults:** 3 × 15 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Anti-extension drill — the limbs move while the trunk stays perfectly still.
|
|||||||
- **Type:** Anti-extension
|
- **Type:** Anti-extension
|
||||||
- **Targets:** Deep core (transverse abdominis), hip flexor control
|
- **Targets:** Deep core (transverse abdominis), hip flexor control
|
||||||
- **Prescription:** 8 per side, slow and controlled
|
- **Prescription:** 8 per side, slow and controlled
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the hips through.
|
|||||||
- **Type:** Free-weight compound hinge
|
- **Type:** Free-weight compound hinge
|
||||||
- **Targets:** Glutes, hamstrings, spinal erectors, grip
|
- **Targets:** Glutes, hamstrings, spinal erectors, grip
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ elbow depth, then press back to straight arms.
|
|||||||
- **Type:** Bodyweight elbow extension (chest/triceps press)
|
- **Type:** Bodyweight elbow extension (chest/triceps press)
|
||||||
- **Targets:** Triceps, chest, front delts
|
- **Targets:** Triceps, chest, front delts
|
||||||
- **Prescription:** 3 × 6–12
|
- **Prescription:** 3 × 6–12
|
||||||
|
- **Defaults:** 3 × 6 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the bar, one weight in each hand.
|
|||||||
- **Type:** Free-weight horizontal press (dumbbells)
|
- **Type:** Free-weight horizontal press (dumbbells)
|
||||||
- **Targets:** Chest, front delts, triceps
|
- **Targets:** Chest, front delts, triceps
|
||||||
- **Prescription:** 3 × 8–12
|
- **Prescription:** 3 × 8–12
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ dumbbells from a full hang to the shoulders.
|
|||||||
- **Type:** Free-weight elbow flexion (dumbbells)
|
- **Type:** Free-weight elbow flexion (dumbbells)
|
||||||
- **Targets:** Biceps, forearms
|
- **Targets:** Biceps, forearms
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ hugging arc, elbows softly fixed.
|
|||||||
- **Type:** Free-weight chest fly (dumbbells)
|
- **Type:** Free-weight chest fly (dumbbells)
|
||||||
- **Targets:** Chest, front delts
|
- **Targets:** Chest, front delts
|
||||||
- **Prescription:** 3 × 10–15, light and controlled
|
- **Prescription:** 3 × 10–15, light and controlled
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from a dead hang to the ribs.
|
|||||||
- **Type:** Free-weight horizontal pull (dumbbell)
|
- **Type:** Free-weight horizontal pull (dumbbell)
|
||||||
- **Targets:** Lats, mid-back, biceps
|
- **Targets:** Lats, mid-back, biceps
|
||||||
- **Prescription:** 3 × 8–12 per side
|
- **Prescription:** 3 × 8–12 per side
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ press from the shoulders to lockout overhead.
|
|||||||
- **Type:** Free-weight vertical press (dumbbells)
|
- **Type:** Free-weight vertical press (dumbbells)
|
||||||
- **Targets:** Shoulders, triceps, upper chest
|
- **Targets:** Shoulders, triceps, upper chest
|
||||||
- **Prescription:** 3 × 8–12
|
- **Prescription:** 3 × 8–12
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the nose. Small weight, big shoulders-health payoff.
|
|||||||
- **Type:** Machine-based cable pull (rear delts)
|
- **Type:** Machine-based cable pull (rear delts)
|
||||||
- **Targets:** Rear delts, mid-back, rotator cuff
|
- **Targets:** Rear delts, mid-back, rotator cuff
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ body is a straight line from shoulders to knees.
|
|||||||
- **Type:** Hip extension (floor)
|
- **Type:** Hip extension (floor)
|
||||||
- **Targets:** Glutes, hamstrings
|
- **Targets:** Glutes, hamstrings
|
||||||
- **Prescription:** 3 × 12–15, squeeze at the top
|
- **Prescription:** 3 × 12–15, squeeze at the top
|
||||||
|
- **Defaults:** 3 × 12 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ between the heels. The friendliest way to load a squat.
|
|||||||
- **Type:** Free-weight squat (dumbbell)
|
- **Type:** Free-weight squat (dumbbell)
|
||||||
- **Targets:** Quadriceps, glutes, trunk
|
- **Targets:** Quadriceps, glutes, trunk
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ drive the hips up to a straight line.
|
|||||||
- **Type:** Free-weight hip extension
|
- **Type:** Free-weight hip extension
|
||||||
- **Targets:** Glutes, hamstrings
|
- **Targets:** Glutes, hamstrings
|
||||||
- **Prescription:** 4 × 8–10
|
- **Prescription:** 4 × 8–10
|
||||||
|
- **Defaults:** 4 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ The gold standard for deep core tension — a shallow, rigid banana shape.
|
|||||||
- **Type:** Anti-extension (isometric hold)
|
- **Type:** Anti-extension (isometric hold)
|
||||||
- **Targets:** Rectus abdominis, deep core, hip flexors
|
- **Targets:** Rectus abdominis, deep core, hip flexors
|
||||||
- **Prescription:** 3 × 20–40 s holds
|
- **Prescription:** 3 × 20–40 s holds
|
||||||
|
- **Defaults:** 3 × 20 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ chest.
|
|||||||
- **Type:** Free-weight incline press
|
- **Type:** Free-weight incline press
|
||||||
- **Targets:** Upper chest, front delts, triceps
|
- **Targets:** Upper chest, front delts, triceps
|
||||||
- **Prescription:** 3 × 8–10
|
- **Prescription:** 3 × 8–10
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ down from overhead.
|
|||||||
- **Type:** Machine-based vertical pull
|
- **Type:** Machine-based vertical pull
|
||||||
- **Targets:** Latissimus dorsi, mid-back, rear delts, biceps
|
- **Targets:** Latissimus dorsi, mid-back, rear delts, biceps
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the arms are level with the shoulders.
|
|||||||
- **Type:** Free-weight lateral raise (dumbbells)
|
- **Type:** Free-weight lateral raise (dumbbells)
|
||||||
- **Targets:** Side delts
|
- **Targets:** Side delts
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the thighs in place.
|
|||||||
- **Type:** Machine-based isolation (knee flexion)
|
- **Type:** Machine-based isolation (knee flexion)
|
||||||
- **Targets:** Hamstrings (biceps femoris, semitendinosus, semimembranosus)
|
- **Targets:** Hamstrings (biceps femoris, semitendinosus, semimembranosus)
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ stay pinned to the seat.
|
|||||||
- **Type:** Machine-based isolation (knee extension)
|
- **Type:** Machine-based isolation (knee extension)
|
||||||
- **Targets:** Quadriceps (rectus femoris, vastus lateralis/medialis)
|
- **Targets:** Quadriceps (rectus femoris, vastus lateralis/medialis)
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ supported.
|
|||||||
- **Type:** Machine-based compound push
|
- **Type:** Machine-based compound push
|
||||||
- **Targets:** Quadriceps, glutes, hamstrings
|
- **Targets:** Quadriceps, glutes, hamstrings
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Lower-ab builder — the slow lowering is the exercise.
|
|||||||
- **Type:** Anti-extension (dynamic)
|
- **Type:** Anti-extension (dynamic)
|
||||||
- **Targets:** Lower rectus abdominis, hip flexors, deep core
|
- **Targets:** Lower rectus abdominis, hip flexors, deep core
|
||||||
- **Prescription:** 3 × 8–15 reps, slow negatives
|
- **Prescription:** 3 × 8–15 reps, slow negatives
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ back up through the front heel. Bodyweight first, dumbbells in hand later.
|
|||||||
- **Type:** Split-stance squat (bodyweight or dumbbells)
|
- **Type:** Split-stance squat (bodyweight or dumbbells)
|
||||||
- **Targets:** Quadriceps, glutes, balance
|
- **Targets:** Quadriceps, glutes, balance
|
||||||
- **Prescription:** 3 × 8–10 per side
|
- **Prescription:** 3 × 8–10 per side
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the machine's fixed arc.
|
|||||||
- **Type:** Machine-based chest fly
|
- **Type:** Machine-based chest fly
|
||||||
- **Targets:** Chest, front delts
|
- **Targets:** Chest, front delts
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ The baseline anti-extension hold — a rigid line from head to heels.
|
|||||||
- **Type:** Anti-extension (isometric hold)
|
- **Type:** Anti-extension (isometric hold)
|
||||||
- **Targets:** Rectus abdominis, deep core, glutes, shoulders
|
- **Targets:** Rectus abdominis, deep core, glutes, shoulders
|
||||||
- **Prescription:** 3 × 30–60 s holds
|
- **Prescription:** 3 × 30–60 s holds
|
||||||
|
- **Defaults:** 3 × 30 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ lower all the way back down.
|
|||||||
- **Type:** Bodyweight vertical pull
|
- **Type:** Bodyweight vertical pull
|
||||||
- **Targets:** Lats, biceps, mid-back, grip
|
- **Targets:** Lats, biceps, mid-back, grip
|
||||||
- **Prescription:** 3 × as many strict reps as possible
|
- **Prescription:** 3 × as many strict reps as possible
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ press back up without the hips sagging.
|
|||||||
- **Type:** Bodyweight horizontal press
|
- **Type:** Bodyweight horizontal press
|
||||||
- **Targets:** Chest, front delts, triceps, trunk
|
- **Targets:** Chest, front delts, triceps, trunk
|
||||||
- **Prescription:** 3 × 8–15
|
- **Prescription:** 3 × 8–15
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ wide and back, hitting what pressing never touches.
|
|||||||
- **Type:** Machine-based reverse fly
|
- **Type:** Machine-based reverse fly
|
||||||
- **Targets:** Rear delts, mid-back
|
- **Targets:** Rear delts, mid-back
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Curl the pelvis toward the ribs — lower-ab flexion without neck strain.
|
|||||||
- **Type:** Spinal flexion (lower)
|
- **Type:** Spinal flexion (lower)
|
||||||
- **Targets:** Lower rectus abdominis, deep core
|
- **Targets:** Lower rectus abdominis, deep core
|
||||||
- **Prescription:** 3 × 12–15 reps, controlled negative
|
- **Prescription:** 3 × 12–15 reps, controlled negative
|
||||||
|
- **Defaults:** 3 × 12 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the hamstrings stop you, then stand back up. Barbell or dumbbells.
|
|||||||
- **Type:** Free-weight hinge (barbell or dumbbells)
|
- **Type:** Free-weight hinge (barbell or dumbbells)
|
||||||
- **Targets:** Hamstrings, glutes, spinal erectors
|
- **Targets:** Hamstrings, glutes, spinal erectors
|
||||||
- **Prescription:** 3 × 8–10
|
- **Prescription:** 3 × 8–10
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ obliques.
|
|||||||
- **Type:** Machine-based trunk rotation
|
- **Type:** Machine-based trunk rotation
|
||||||
- **Targets:** Obliques, deep core
|
- **Targets:** Obliques, deep core
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ straight back against the chest pad.
|
|||||||
- **Type:** Machine-based horizontal pull
|
- **Type:** Machine-based horizontal pull
|
||||||
- **Targets:** Mid-back, latissimus dorsi, rear delts, biceps
|
- **Targets:** Mid-back, latissimus dorsi, rear delts, biceps
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ against the pad.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based vertical press
|
- **Type:** Machine-based vertical press
|
||||||
- **Targets:** Deltoids, triceps, upper trapezius
|
- **Targets:** Deltoids, triceps, upper trapezius
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Anti-lateral-flexion hold — resist the hips dropping toward the floor.
|
|||||||
- **Type:** Anti-lateral flexion (isometric hold)
|
- **Type:** Anti-lateral flexion (isometric hold)
|
||||||
- **Targets:** Obliques, quadratus lumborum, glute medius, shoulder stability
|
- **Targets:** Obliques, quadratus lumborum, glute medius, shoulder stability
|
||||||
- **Prescription:** 3 × 20–45 s per side
|
- **Prescription:** 3 × 20–45 s per side
|
||||||
|
- **Defaults:** 3 × 20 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ chest to full extension.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based elbow extension
|
- **Type:** Machine-based elbow extension
|
||||||
- **Targets:** Triceps brachii
|
- **Targets:** Triceps brachii
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ chest height down to straight arms.
|
|||||||
- **Type:** Machine-based cable elbow extension
|
- **Type:** Machine-based cable elbow extension
|
||||||
- **Targets:** Triceps
|
- **Targets:** Triceps
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ struct ExerciseInfo {
|
|||||||
/// The comma-separated `**Targets:**` values, split for chip rendering.
|
/// The comma-separated `**Targets:**` values, split for chip rendering.
|
||||||
var targets: [String]
|
var targets: [String]
|
||||||
var sections: [Section]
|
var sections: [Section]
|
||||||
|
/// Parsed `**Defaults:**` bullet — the library's suggested starting plan for an
|
||||||
|
/// exercise added outside a split (no prior log, no split entry to copy from).
|
||||||
|
/// `nil` when the bullet is absent (not yet authored) or unparseable.
|
||||||
|
var defaults: Defaults?
|
||||||
|
|
||||||
/// Whether the authored `Type:` identifies this as a machine exercise — the
|
/// Whether the authored `Type:` identifies this as a machine exercise — the
|
||||||
/// library convention is that every machine entry's type starts "Machine-based".
|
/// library convention is that every machine entry's type starts "Machine-based".
|
||||||
@@ -34,6 +38,14 @@ struct ExerciseInfo {
|
|||||||
var items: [Item]
|
var items: [Item]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The library's suggested starting plan, parsed from the `**Defaults:**` bullet.
|
||||||
|
struct Defaults {
|
||||||
|
var sets: Int
|
||||||
|
var reps: Int
|
||||||
|
var loadType: LoadType
|
||||||
|
var durationSeconds: Int
|
||||||
|
}
|
||||||
|
|
||||||
/// One block within a section, preserving the authored list flavor: numbered
|
/// One block within a section, preserving the authored list flavor: numbered
|
||||||
/// steps render with their ordinal, bullets with a dot, paragraphs plain.
|
/// steps render with their ordinal, bullets with a dot, paragraphs plain.
|
||||||
enum Item {
|
enum Item {
|
||||||
@@ -58,6 +70,7 @@ extension ExerciseInfo {
|
|||||||
var category: String?
|
var category: String?
|
||||||
var type: String?
|
var type: String?
|
||||||
var targets: [String] = []
|
var targets: [String] = []
|
||||||
|
var defaults: Defaults?
|
||||||
var sections: [Section] = []
|
var sections: [Section] = []
|
||||||
|
|
||||||
var currentSection: Section?
|
var currentSection: Section?
|
||||||
@@ -118,6 +131,10 @@ extension ExerciseInfo {
|
|||||||
targets = value.components(separatedBy: ",")
|
targets = value.components(separatedBy: ",")
|
||||||
.map { $0.trimmingCharacters(in: .whitespaces) }
|
.map { $0.trimmingCharacters(in: .whitespaces) }
|
||||||
.filter { !$0.isEmpty }
|
.filter { !$0.isEmpty }
|
||||||
|
} else if currentSection == nil,
|
||||||
|
let value = metadataValue(line, key: "Defaults") {
|
||||||
|
flushItem()
|
||||||
|
defaults = parseDefaults(value)
|
||||||
} else if let range = line.range(of: #"^\d+\.\s+"#, options: .regularExpression) {
|
} else if let range = line.range(of: #"^\d+\.\s+"#, options: .regularExpression) {
|
||||||
flushItem()
|
flushItem()
|
||||||
currentItem = .step(String(line[range.upperBound...]))
|
currentItem = .step(String(line[range.upperBound...]))
|
||||||
@@ -136,9 +153,31 @@ extension ExerciseInfo {
|
|||||||
category: category,
|
category: category,
|
||||||
type: type,
|
type: type,
|
||||||
targets: targets,
|
targets: targets,
|
||||||
sections: sections
|
sections: sections,
|
||||||
|
defaults: defaults
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a `**Defaults:**` value — "4 × 10 weighted", "3 × 12 bodyweight", or
|
||||||
|
/// "3 × 30 s" — into sets/reps/loadType. The trailing unit picks the `LoadType`
|
||||||
|
/// and which of reps/duration the middle number fills; anything else (missing
|
||||||
|
/// bullet, unrecognized unit) yields `nil` rather than guessing.
|
||||||
|
private static func parseDefaults(_ value: String) -> Defaults? {
|
||||||
|
let parts = value.components(separatedBy: " × ")
|
||||||
|
guard parts.count == 2, let sets = Int(parts[0]) else { return nil }
|
||||||
|
let rest = parts[1].components(separatedBy: " ")
|
||||||
|
guard rest.count == 2, let n = Int(rest[0]) else { return nil }
|
||||||
|
switch rest[1] {
|
||||||
|
case "weighted":
|
||||||
|
return Defaults(sets: sets, reps: n, loadType: .weight, durationSeconds: 0)
|
||||||
|
case "bodyweight":
|
||||||
|
return Defaults(sets: sets, reps: n, loadType: .none, durationSeconds: 0)
|
||||||
|
case "s":
|
||||||
|
return Defaults(sets: sets, reps: 0, loadType: .duration, durationSeconds: n)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds and parses the bundled `<Exercise Name>.info.md` exported next to the
|
/// Finds and parses the bundled `<Exercise Name>.info.md` exported next to the
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ supported.
|
|||||||
- **Type:** Machine-based trunk flexion
|
- **Type:** Machine-based trunk flexion
|
||||||
- **Targets:** Rectus abdominis, deep core
|
- **Targets:** Rectus abdominis, deep core
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ hips and glutes.
|
|||||||
- **Type:** Machine-based hip abduction
|
- **Type:** Machine-based hip abduction
|
||||||
- **Targets:** Gluteus medius, gluteus minimus, outer thighs
|
- **Targets:** Gluteus medius, gluteus minimus, outer thighs
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ inner thighs.
|
|||||||
- **Type:** Machine-based hip adduction
|
- **Type:** Machine-based hip adduction
|
||||||
- **Targets:** Adductors, inner thighs
|
- **Targets:** Adductors, inner thighs
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the pad so only the forearms move.
|
|||||||
- **Type:** Machine-based elbow flexion (isolation)
|
- **Type:** Machine-based elbow flexion (isolation)
|
||||||
- **Targets:** Biceps brachii, brachialis
|
- **Targets:** Biceps brachii, brachialis
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the trunk back in line with the legs.
|
|||||||
- **Type:** Machine-based back extension (hip hinge)
|
- **Type:** Machine-based back extension (hip hinge)
|
||||||
- **Targets:** Spinal erectors, glutes, hamstrings
|
- **Targets:** Spinal erectors, glutes, hamstrings
|
||||||
- **Prescription:** 3 × 10–15
|
- **Prescription:** 3 × 10–15
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ heels, stand back up.
|
|||||||
- **Type:** Free-weight compound squat
|
- **Type:** Free-weight compound squat
|
||||||
- **Targets:** Quadriceps, glutes, adductors, trunk
|
- **Targets:** Quadriceps, glutes, adductors, trunk
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ and press it back to straight arms.
|
|||||||
- **Type:** Free-weight horizontal press
|
- **Type:** Free-weight horizontal press
|
||||||
- **Targets:** Chest, front delts, triceps
|
- **Targets:** Chest, front delts, triceps
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ twist.
|
|||||||
- **Type:** Anti-rotation
|
- **Type:** Anti-rotation
|
||||||
- **Targets:** Spinal erectors, glutes, deep core, shoulder stability
|
- **Targets:** Spinal erectors, glutes, deep core, shoulder stability
|
||||||
- **Prescription:** Warm-up 8 per side; main circuit 3 × 8–10 per side, slow
|
- **Prescription:** Warm-up 8 per side; main circuit 3 × 8–10 per side, slow
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ sit down between the heels. The pattern every loaded squat is built on.
|
|||||||
- **Type:** Bodyweight squat
|
- **Type:** Bodyweight squat
|
||||||
- **Targets:** Quadriceps, glutes, mobility
|
- **Targets:** Quadriceps, glutes, mobility
|
||||||
- **Prescription:** 3 × 15–20, or 10 slow reps as a warm-up
|
- **Prescription:** 3 × 15–20, or 10 slow reps as a warm-up
|
||||||
|
- **Defaults:** 3 × 15 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ a hard squeeze at the top.
|
|||||||
- **Type:** Machine-based calf raise
|
- **Type:** Machine-based calf raise
|
||||||
- **Targets:** Soleus, gastrocnemius
|
- **Targets:** Soleus, gastrocnemius
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Gentle spinal mobility drill that wakes up the whole trunk before core work.
|
|||||||
- **Type:** Spinal mobility
|
- **Type:** Spinal mobility
|
||||||
- **Targets:** Thoracic and lumbar spine, deep core awareness
|
- **Targets:** Thoracic and lumbar spine, deep core awareness
|
||||||
- **Prescription:** 10 slow reps (one rep = cat + cow)
|
- **Prescription:** 10 slow reps (one rep = cat + cow)
|
||||||
|
- **Defaults:** 3 × 10 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ forward from the chest.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based horizontal press
|
- **Type:** Machine-based horizontal press
|
||||||
- **Targets:** Pectorals, anterior deltoids, triceps
|
- **Targets:** Pectorals, anterior deltoids, triceps
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ lower. Short range, all abs.
|
|||||||
- **Type:** Spinal flexion (upper)
|
- **Type:** Spinal flexion (upper)
|
||||||
- **Targets:** Rectus abdominis
|
- **Targets:** Rectus abdominis
|
||||||
- **Prescription:** 3 × 15–20, slow
|
- **Prescription:** 3 × 15–20, slow
|
||||||
|
- **Defaults:** 3 × 15 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Anti-extension drill — the limbs move while the trunk stays perfectly still.
|
|||||||
- **Type:** Anti-extension
|
- **Type:** Anti-extension
|
||||||
- **Targets:** Deep core (transverse abdominis), hip flexor control
|
- **Targets:** Deep core (transverse abdominis), hip flexor control
|
||||||
- **Prescription:** 8 per side, slow and controlled
|
- **Prescription:** 8 per side, slow and controlled
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the hips through.
|
|||||||
- **Type:** Free-weight compound hinge
|
- **Type:** Free-weight compound hinge
|
||||||
- **Targets:** Glutes, hamstrings, spinal erectors, grip
|
- **Targets:** Glutes, hamstrings, spinal erectors, grip
|
||||||
- **Prescription:** 4 × 6–8
|
- **Prescription:** 4 × 6–8
|
||||||
|
- **Defaults:** 4 × 6 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ elbow depth, then press back to straight arms.
|
|||||||
- **Type:** Bodyweight elbow extension (chest/triceps press)
|
- **Type:** Bodyweight elbow extension (chest/triceps press)
|
||||||
- **Targets:** Triceps, chest, front delts
|
- **Targets:** Triceps, chest, front delts
|
||||||
- **Prescription:** 3 × 6–12
|
- **Prescription:** 3 × 6–12
|
||||||
|
- **Defaults:** 3 × 6 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the bar, one weight in each hand.
|
|||||||
- **Type:** Free-weight horizontal press (dumbbells)
|
- **Type:** Free-weight horizontal press (dumbbells)
|
||||||
- **Targets:** Chest, front delts, triceps
|
- **Targets:** Chest, front delts, triceps
|
||||||
- **Prescription:** 3 × 8–12
|
- **Prescription:** 3 × 8–12
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ dumbbells from a full hang to the shoulders.
|
|||||||
- **Type:** Free-weight elbow flexion (dumbbells)
|
- **Type:** Free-weight elbow flexion (dumbbells)
|
||||||
- **Targets:** Biceps, forearms
|
- **Targets:** Biceps, forearms
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ hugging arc, elbows softly fixed.
|
|||||||
- **Type:** Free-weight chest fly (dumbbells)
|
- **Type:** Free-weight chest fly (dumbbells)
|
||||||
- **Targets:** Chest, front delts
|
- **Targets:** Chest, front delts
|
||||||
- **Prescription:** 3 × 10–15, light and controlled
|
- **Prescription:** 3 × 10–15, light and controlled
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from a dead hang to the ribs.
|
|||||||
- **Type:** Free-weight horizontal pull (dumbbell)
|
- **Type:** Free-weight horizontal pull (dumbbell)
|
||||||
- **Targets:** Lats, mid-back, biceps
|
- **Targets:** Lats, mid-back, biceps
|
||||||
- **Prescription:** 3 × 8–12 per side
|
- **Prescription:** 3 × 8–12 per side
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ press from the shoulders to lockout overhead.
|
|||||||
- **Type:** Free-weight vertical press (dumbbells)
|
- **Type:** Free-weight vertical press (dumbbells)
|
||||||
- **Targets:** Shoulders, triceps, upper chest
|
- **Targets:** Shoulders, triceps, upper chest
|
||||||
- **Prescription:** 3 × 8–12
|
- **Prescription:** 3 × 8–12
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the nose. Small weight, big shoulders-health payoff.
|
|||||||
- **Type:** Machine-based cable pull (rear delts)
|
- **Type:** Machine-based cable pull (rear delts)
|
||||||
- **Targets:** Rear delts, mid-back, rotator cuff
|
- **Targets:** Rear delts, mid-back, rotator cuff
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ body is a straight line from shoulders to knees.
|
|||||||
- **Type:** Hip extension (floor)
|
- **Type:** Hip extension (floor)
|
||||||
- **Targets:** Glutes, hamstrings
|
- **Targets:** Glutes, hamstrings
|
||||||
- **Prescription:** 3 × 12–15, squeeze at the top
|
- **Prescription:** 3 × 12–15, squeeze at the top
|
||||||
|
- **Defaults:** 3 × 12 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ between the heels. The friendliest way to load a squat.
|
|||||||
- **Type:** Free-weight squat (dumbbell)
|
- **Type:** Free-weight squat (dumbbell)
|
||||||
- **Targets:** Quadriceps, glutes, trunk
|
- **Targets:** Quadriceps, glutes, trunk
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ drive the hips up to a straight line.
|
|||||||
- **Type:** Free-weight hip extension
|
- **Type:** Free-weight hip extension
|
||||||
- **Targets:** Glutes, hamstrings
|
- **Targets:** Glutes, hamstrings
|
||||||
- **Prescription:** 4 × 8–10
|
- **Prescription:** 4 × 8–10
|
||||||
|
- **Defaults:** 4 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ The gold standard for deep core tension — a shallow, rigid banana shape.
|
|||||||
- **Type:** Anti-extension (isometric hold)
|
- **Type:** Anti-extension (isometric hold)
|
||||||
- **Targets:** Rectus abdominis, deep core, hip flexors
|
- **Targets:** Rectus abdominis, deep core, hip flexors
|
||||||
- **Prescription:** 3 × 20–40 s holds
|
- **Prescription:** 3 × 20–40 s holds
|
||||||
|
- **Defaults:** 3 × 20 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ chest.
|
|||||||
- **Type:** Free-weight incline press
|
- **Type:** Free-weight incline press
|
||||||
- **Targets:** Upper chest, front delts, triceps
|
- **Targets:** Upper chest, front delts, triceps
|
||||||
- **Prescription:** 3 × 8–10
|
- **Prescription:** 3 × 8–10
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ down from overhead.
|
|||||||
- **Type:** Machine-based vertical pull
|
- **Type:** Machine-based vertical pull
|
||||||
- **Targets:** Latissimus dorsi, mid-back, rear delts, biceps
|
- **Targets:** Latissimus dorsi, mid-back, rear delts, biceps
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the arms are level with the shoulders.
|
|||||||
- **Type:** Free-weight lateral raise (dumbbells)
|
- **Type:** Free-weight lateral raise (dumbbells)
|
||||||
- **Targets:** Side delts
|
- **Targets:** Side delts
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the thighs in place.
|
|||||||
- **Type:** Machine-based isolation (knee flexion)
|
- **Type:** Machine-based isolation (knee flexion)
|
||||||
- **Targets:** Hamstrings (biceps femoris, semitendinosus, semimembranosus)
|
- **Targets:** Hamstrings (biceps femoris, semitendinosus, semimembranosus)
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ stay pinned to the seat.
|
|||||||
- **Type:** Machine-based isolation (knee extension)
|
- **Type:** Machine-based isolation (knee extension)
|
||||||
- **Targets:** Quadriceps (rectus femoris, vastus lateralis/medialis)
|
- **Targets:** Quadriceps (rectus femoris, vastus lateralis/medialis)
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ supported.
|
|||||||
- **Type:** Machine-based compound push
|
- **Type:** Machine-based compound push
|
||||||
- **Targets:** Quadriceps, glutes, hamstrings
|
- **Targets:** Quadriceps, glutes, hamstrings
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Lower-ab builder — the slow lowering is the exercise.
|
|||||||
- **Type:** Anti-extension (dynamic)
|
- **Type:** Anti-extension (dynamic)
|
||||||
- **Targets:** Lower rectus abdominis, hip flexors, deep core
|
- **Targets:** Lower rectus abdominis, hip flexors, deep core
|
||||||
- **Prescription:** 3 × 8–15 reps, slow negatives
|
- **Prescription:** 3 × 8–15 reps, slow negatives
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ back up through the front heel. Bodyweight first, dumbbells in hand later.
|
|||||||
- **Type:** Split-stance squat (bodyweight or dumbbells)
|
- **Type:** Split-stance squat (bodyweight or dumbbells)
|
||||||
- **Targets:** Quadriceps, glutes, balance
|
- **Targets:** Quadriceps, glutes, balance
|
||||||
- **Prescription:** 3 × 8–10 per side
|
- **Prescription:** 3 × 8–10 per side
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the machine's fixed arc.
|
|||||||
- **Type:** Machine-based chest fly
|
- **Type:** Machine-based chest fly
|
||||||
- **Targets:** Chest, front delts
|
- **Targets:** Chest, front delts
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ The baseline anti-extension hold — a rigid line from head to heels.
|
|||||||
- **Type:** Anti-extension (isometric hold)
|
- **Type:** Anti-extension (isometric hold)
|
||||||
- **Targets:** Rectus abdominis, deep core, glutes, shoulders
|
- **Targets:** Rectus abdominis, deep core, glutes, shoulders
|
||||||
- **Prescription:** 3 × 30–60 s holds
|
- **Prescription:** 3 × 30–60 s holds
|
||||||
|
- **Defaults:** 3 × 30 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ lower all the way back down.
|
|||||||
- **Type:** Bodyweight vertical pull
|
- **Type:** Bodyweight vertical pull
|
||||||
- **Targets:** Lats, biceps, mid-back, grip
|
- **Targets:** Lats, biceps, mid-back, grip
|
||||||
- **Prescription:** 3 × as many strict reps as possible
|
- **Prescription:** 3 × as many strict reps as possible
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ press back up without the hips sagging.
|
|||||||
- **Type:** Bodyweight horizontal press
|
- **Type:** Bodyweight horizontal press
|
||||||
- **Targets:** Chest, front delts, triceps, trunk
|
- **Targets:** Chest, front delts, triceps, trunk
|
||||||
- **Prescription:** 3 × 8–15
|
- **Prescription:** 3 × 8–15
|
||||||
|
- **Defaults:** 3 × 8 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ wide and back, hitting what pressing never touches.
|
|||||||
- **Type:** Machine-based reverse fly
|
- **Type:** Machine-based reverse fly
|
||||||
- **Targets:** Rear delts, mid-back
|
- **Targets:** Rear delts, mid-back
|
||||||
- **Prescription:** 3 × 12–15, light
|
- **Prescription:** 3 × 12–15, light
|
||||||
|
- **Defaults:** 3 × 12 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Curl the pelvis toward the ribs — lower-ab flexion without neck strain.
|
|||||||
- **Type:** Spinal flexion (lower)
|
- **Type:** Spinal flexion (lower)
|
||||||
- **Targets:** Lower rectus abdominis, deep core
|
- **Targets:** Lower rectus abdominis, deep core
|
||||||
- **Prescription:** 3 × 12–15 reps, controlled negative
|
- **Prescription:** 3 × 12–15 reps, controlled negative
|
||||||
|
- **Defaults:** 3 × 12 bodyweight
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ the hamstrings stop you, then stand back up. Barbell or dumbbells.
|
|||||||
- **Type:** Free-weight hinge (barbell or dumbbells)
|
- **Type:** Free-weight hinge (barbell or dumbbells)
|
||||||
- **Targets:** Hamstrings, glutes, spinal erectors
|
- **Targets:** Hamstrings, glutes, spinal erectors
|
||||||
- **Prescription:** 3 × 8–10
|
- **Prescription:** 3 × 8–10
|
||||||
|
- **Defaults:** 3 × 8 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ obliques.
|
|||||||
- **Type:** Machine-based trunk rotation
|
- **Type:** Machine-based trunk rotation
|
||||||
- **Targets:** Obliques, deep core
|
- **Targets:** Obliques, deep core
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ straight back against the chest pad.
|
|||||||
- **Type:** Machine-based horizontal pull
|
- **Type:** Machine-based horizontal pull
|
||||||
- **Targets:** Mid-back, latissimus dorsi, rear delts, biceps
|
- **Targets:** Mid-back, latissimus dorsi, rear delts, biceps
|
||||||
- **Prescription:** 4 × 10
|
- **Prescription:** 4 × 10
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ against the pad.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based vertical press
|
- **Type:** Machine-based vertical press
|
||||||
- **Targets:** Deltoids, triceps, upper trapezius
|
- **Targets:** Deltoids, triceps, upper trapezius
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Anti-lateral-flexion hold — resist the hips dropping toward the floor.
|
|||||||
- **Type:** Anti-lateral flexion (isometric hold)
|
- **Type:** Anti-lateral flexion (isometric hold)
|
||||||
- **Targets:** Obliques, quadratus lumborum, glute medius, shoulder stability
|
- **Targets:** Obliques, quadratus lumborum, glute medius, shoulder stability
|
||||||
- **Prescription:** 3 × 20–45 s per side
|
- **Prescription:** 3 × 20–45 s per side
|
||||||
|
- **Defaults:** 3 × 20 s
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ chest to full extension.
|
|||||||
- **Category:** Main circuit
|
- **Category:** Main circuit
|
||||||
- **Type:** Machine-based elbow extension
|
- **Type:** Machine-based elbow extension
|
||||||
- **Targets:** Triceps brachii
|
- **Targets:** Triceps brachii
|
||||||
|
- **Defaults:** 4 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ chest height down to straight arms.
|
|||||||
- **Type:** Machine-based cable elbow extension
|
- **Type:** Machine-based cable elbow extension
|
||||||
- **Targets:** Triceps
|
- **Targets:** Triceps
|
||||||
- **Prescription:** 3 × 10–12
|
- **Prescription:** 3 × 10–12
|
||||||
|
- **Defaults:** 3 × 10 weighted
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -254,12 +254,16 @@ struct ExerciseListView: View {
|
|||||||
let newDocs = names
|
let newDocs = names
|
||||||
.filter { !existingNames.contains($0) }
|
.filter { !existingNames.contains($0) }
|
||||||
.enumerated()
|
.enumerated()
|
||||||
.map { i, exName in
|
.map { i, exName -> ExerciseDocument in
|
||||||
ExerciseDocument(
|
// Seed from the library's authored `**Defaults:**` when available,
|
||||||
|
// falling back to a plain 3×10 weighted guess; weight always starts
|
||||||
|
// at 0 (there's no prior lift to seed it from).
|
||||||
|
let defaults = ExerciseInfoLibrary.info(for: exName)?.defaults
|
||||||
|
return ExerciseDocument(
|
||||||
id: ULID.make(), name: exName, order: base + i,
|
id: ULID.make(), name: exName, order: base + i,
|
||||||
sets: 3, reps: 10, weight: 40,
|
sets: defaults?.sets ?? 3, reps: defaults?.reps ?? 10, weight: 0,
|
||||||
loadType: LoadType.weight.rawValue,
|
loadType: (defaults?.loadType ?? .weight).rawValue,
|
||||||
durationSeconds: 0
|
durationSeconds: defaults?.durationSeconds ?? 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
doc.exercises.append(contentsOf: newDocs)
|
doc.exercises.append(contentsOf: newDocs)
|
||||||
|
|||||||
@@ -175,12 +175,16 @@ struct SplitDetailView: View {
|
|||||||
let newDocs = names
|
let newDocs = names
|
||||||
.filter { !existingNames.contains($0) }
|
.filter { !existingNames.contains($0) }
|
||||||
.enumerated()
|
.enumerated()
|
||||||
.map { i, exName in
|
.map { i, exName -> ExerciseDocument in
|
||||||
ExerciseDocument(
|
// Seed from the library's authored `**Defaults:**` when available,
|
||||||
|
// falling back to a plain 3×10 weighted guess; weight always starts
|
||||||
|
// at 0 (there's no prior lift to seed it from).
|
||||||
|
let defaults = ExerciseInfoLibrary.info(for: exName)?.defaults
|
||||||
|
return ExerciseDocument(
|
||||||
id: ULID.make(), name: exName, order: base + i,
|
id: ULID.make(), name: exName, order: base + i,
|
||||||
sets: 3, reps: 10, weight: 40,
|
sets: defaults?.sets ?? 3, reps: defaults?.reps ?? 10, weight: 0,
|
||||||
loadType: LoadType.weight.rawValue,
|
loadType: (defaults?.loadType ?? .weight).rawValue,
|
||||||
durationSeconds: 0
|
durationSeconds: defaults?.durationSeconds ?? 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
doc.exercises.append(contentsOf: newDocs)
|
doc.exercises.append(contentsOf: newDocs)
|
||||||
|
|||||||
@@ -182,8 +182,11 @@ struct WorkoutLogListView: View {
|
|||||||
SplitExercisePickerSheet(
|
SplitExercisePickerSheet(
|
||||||
split: split,
|
split: split,
|
||||||
existingExerciseNames: Set(sortedLogs.map { $0.exerciseName })
|
existingExerciseNames: Set(sortedLogs.map { $0.exerciseName })
|
||||||
) { exercise in
|
) { selection in
|
||||||
addExerciseFromSplit(exercise)
|
switch selection {
|
||||||
|
case .fromSplit(let exercise): addExerciseFromSplit(exercise)
|
||||||
|
case .fromLibrary(let name): addExerciseFromLibrary(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.confirmationDialog(
|
.confirmationDialog(
|
||||||
@@ -305,6 +308,21 @@ struct WorkoutLogListView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addExerciseFromSplit(_ exercise: Exercise) {
|
private func addExerciseFromSplit(_ exercise: Exercise) {
|
||||||
|
appendExercise(ExerciseDocument(from: exercise))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an exercise that isn't part of this workout's split, picked from the full
|
||||||
|
/// exercise library. Seeds a plan from, in priority order: the most recent logged
|
||||||
|
/// set of this exercise (any workout), the library's authored `**Defaults:**`, or
|
||||||
|
/// a plain 3×10 fallback when neither exists.
|
||||||
|
private func addExerciseFromLibrary(_ name: String) {
|
||||||
|
appendExercise(libraryPlan(for: name))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Append a freshly-planned exercise to the working doc, persist, and push
|
||||||
|
/// straight into its progress flow. Shared tail of `addExerciseFromSplit` and
|
||||||
|
/// `addExerciseFromLibrary`.
|
||||||
|
private func appendExercise(_ plan: ExerciseDocument) {
|
||||||
let now = Date()
|
let now = Date()
|
||||||
|
|
||||||
// Reuse the workout's start time only when it's the very first exercise.
|
// Reuse the workout's start time only when it's the very first exercise.
|
||||||
@@ -313,7 +331,7 @@ struct WorkoutLogListView: View {
|
|||||||
}
|
}
|
||||||
doc.end = nil
|
doc.end = nil
|
||||||
|
|
||||||
let newLog = WorkoutLogDocument(planFrom: ExerciseDocument(from: exercise), order: doc.logs.count, date: now)
|
let newLog = WorkoutLogDocument(planFrom: plan, order: doc.logs.count, date: now)
|
||||||
doc.logs.append(newLog)
|
doc.logs.append(newLog)
|
||||||
save()
|
save()
|
||||||
|
|
||||||
@@ -321,6 +339,46 @@ struct WorkoutLogListView: View {
|
|||||||
addedLog = LogRoute(id: newLog.id)
|
addedLog = LogRoute(id: newLog.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Plan defaults for a library exercise with no split entry: copy the most recent
|
||||||
|
/// logged set of this exercise (sets/reps/weight/loadType/duration and machine
|
||||||
|
/// settings) if one exists anywhere; otherwise the library's authored defaults
|
||||||
|
/// (weight always starts at 0 — there's no prior lift to copy); otherwise a plain
|
||||||
|
/// 3×10 bodyweight-style fallback.
|
||||||
|
private func libraryPlan(for name: String) -> ExerciseDocument {
|
||||||
|
if let recent = mostRecentLog(named: name) {
|
||||||
|
return ExerciseDocument(
|
||||||
|
id: ULID.make(), name: name, order: doc.logs.count,
|
||||||
|
sets: recent.sets, reps: recent.reps, weight: recent.weight,
|
||||||
|
loadType: recent.loadType, durationSeconds: recent.durationTotalSeconds,
|
||||||
|
machineSettings: recent.machineSettings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let info = ExerciseInfoLibrary.info(for: name)
|
||||||
|
if let defaults = info?.defaults {
|
||||||
|
return ExerciseDocument(
|
||||||
|
id: ULID.make(), name: name, order: doc.logs.count,
|
||||||
|
sets: defaults.sets, reps: defaults.reps, weight: 0,
|
||||||
|
loadType: defaults.loadType.rawValue, durationSeconds: defaults.durationSeconds,
|
||||||
|
machineSettings: info?.isMachineBased == true ? [] : nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ExerciseDocument(
|
||||||
|
id: ULID.make(), name: name, order: doc.logs.count,
|
||||||
|
sets: 3, reps: 10, weight: 0, loadType: LoadType.none.rawValue, durationSeconds: 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Most recent `WorkoutLog` cache entity logged under `name`, across all
|
||||||
|
/// workouts — the best available signal for "what did I actually do last time."
|
||||||
|
private func mostRecentLog(named name: String) -> WorkoutLog? {
|
||||||
|
var descriptor = FetchDescriptor<WorkoutLog>(
|
||||||
|
predicate: #Predicate { $0.exerciseName == name },
|
||||||
|
sortBy: [SortDescriptor(\.date, order: .reverse)]
|
||||||
|
)
|
||||||
|
descriptor.fetchLimit = 1
|
||||||
|
return try? modelContext.fetch(descriptor).first
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply edited machine settings from the sheet: update the log's plan-time
|
/// Apply edited machine settings from the sheet: update the log's plan-time
|
||||||
/// snapshot (persisted with the workout), then write the same settings back to
|
/// snapshot (persisted with the workout), then write the same settings back to
|
||||||
/// the originating split's exercise as the durable default. Sequenced in one
|
/// the originating split's exercise as the durable default. Sequenced in one
|
||||||
@@ -490,22 +548,77 @@ struct SplitExercisePickerSheet: View {
|
|||||||
|
|
||||||
let split: Split?
|
let split: Split?
|
||||||
let existingExerciseNames: Set<String>
|
let existingExerciseNames: Set<String>
|
||||||
let onExerciseSelected: (Exercise) -> Void
|
let onSelected: (Selection) -> Void
|
||||||
@AppStorage("weightUnit") private var weightUnit: WeightUnit = .lb
|
@AppStorage("weightUnit") private var weightUnit: WeightUnit = .lb
|
||||||
|
@State private var searchText = ""
|
||||||
|
/// Parsed once per sheet presentation (`onAppear`), not per row render — the
|
||||||
|
/// library section's name list is stable for the sheet's lifetime.
|
||||||
|
@State private var libraryInfoByName: [String: ExerciseInfo] = [:]
|
||||||
|
|
||||||
private var availableExercises: [Exercise] {
|
/// A pick from either source: the split path hands back the live `Exercise`
|
||||||
|
/// entity (as today), the library path just the exercise name.
|
||||||
|
enum Selection {
|
||||||
|
case fromSplit(Exercise)
|
||||||
|
case fromLibrary(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Section 1 — this workout's split, minus exercises already added.
|
||||||
|
private var splitExercises: [Exercise] {
|
||||||
guard let split else { return [] }
|
guard let split else { return [] }
|
||||||
return split.exercisesArray.filter { !existingExerciseNames.contains($0.name) }
|
return split.exercisesArray.filter { !existingExerciseNames.contains($0.name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Section 2 — every library exercise not already in the workout and not
|
||||||
|
/// already offered in section 1.
|
||||||
|
private var libraryExerciseNames: [String] {
|
||||||
|
let shown = Set(splitExercises.map(\.name))
|
||||||
|
return ExerciseMotionLibrary.exerciseNames.filter {
|
||||||
|
!existingExerciseNames.contains($0) && !shown.contains($0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filteredSplitExercises: [Exercise] {
|
||||||
|
guard !searchText.isEmpty else { return splitExercises }
|
||||||
|
return splitExercises.filter { $0.name.localizedCaseInsensitiveContains(searchText) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filteredLibraryNames: [String] {
|
||||||
|
guard !searchText.isEmpty else { return libraryExerciseNames }
|
||||||
|
return libraryExerciseNames.filter { $0.localizedCaseInsensitiveContains(searchText) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether there's anything left to add at all — independent of the current
|
||||||
|
/// search, so a no-results search doesn't get confused with a truly empty sheet.
|
||||||
|
private var hasAnyExercises: Bool {
|
||||||
|
!splitExercises.isEmpty || !libraryExerciseNames.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "3 × 12" / "3 × 30 s" — the library's suggested plan for a row's caption.
|
||||||
|
private func defaultsCaption(_ defaults: ExerciseInfo.Defaults) -> String {
|
||||||
|
switch defaults.loadType {
|
||||||
|
case .duration: "\(defaults.sets) × \(defaults.durationSeconds) s"
|
||||||
|
case .weight, .none: "\(defaults.sets) × \(defaults.reps)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
Group {
|
Group {
|
||||||
if !availableExercises.isEmpty {
|
if !hasAnyExercises {
|
||||||
|
ContentUnavailableView(
|
||||||
|
"All Exercises Added",
|
||||||
|
systemImage: "checkmark.circle",
|
||||||
|
description: Text("Every exercise is already part of this workout.")
|
||||||
|
)
|
||||||
|
} else if filteredSplitExercises.isEmpty && filteredLibraryNames.isEmpty {
|
||||||
|
ContentUnavailableView.search(text: searchText)
|
||||||
|
} else {
|
||||||
List {
|
List {
|
||||||
ForEach(availableExercises) { exercise in
|
if !filteredSplitExercises.isEmpty, let split {
|
||||||
|
Section("From \(split.name)") {
|
||||||
|
ForEach(filteredSplitExercises) { exercise in
|
||||||
Button {
|
Button {
|
||||||
onExerciseSelected(exercise)
|
onSelected(.fromSplit(exercise))
|
||||||
dismiss()
|
dismiss()
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
@@ -523,24 +636,41 @@ struct SplitExercisePickerSheet: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if split == nil {
|
}
|
||||||
ContentUnavailableView(
|
|
||||||
"No Split Selected",
|
if !filteredLibraryNames.isEmpty {
|
||||||
systemImage: "dumbbell",
|
Section("All Exercises") {
|
||||||
description: Text("This workout has no associated split.")
|
ForEach(filteredLibraryNames, id: \.self) { name in
|
||||||
)
|
Button {
|
||||||
} else if split?.exercisesArray.isEmpty == true {
|
onSelected(.fromLibrary(name))
|
||||||
ContentUnavailableView(
|
dismiss()
|
||||||
"No Exercises in Split",
|
} label: {
|
||||||
systemImage: "dumbbell",
|
HStack {
|
||||||
description: Text("Add exercises to your split first.")
|
VStack(alignment: .leading) {
|
||||||
)
|
Text(name)
|
||||||
} else {
|
.foregroundColor(.primary)
|
||||||
ContentUnavailableView(
|
if let defaults = libraryInfoByName[name]?.defaults {
|
||||||
"All Exercises Added",
|
Text(defaultsCaption(defaults))
|
||||||
systemImage: "checkmark.circle",
|
.font(.caption)
|
||||||
description: Text("You've added all exercises from this split.")
|
.foregroundColor(.secondary)
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
Image(systemName: "plus.circle")
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.searchable(text: $searchText)
|
||||||
|
.onAppear {
|
||||||
|
guard libraryInfoByName.isEmpty else { return }
|
||||||
|
for name in libraryExerciseNames {
|
||||||
|
libraryInfoByName[name] = ExerciseInfoLibrary.info(for: name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Add Exercise")
|
.navigationTitle("Add Exercise")
|
||||||
|
|||||||
Reference in New Issue
Block a user