Files
GroundedHelper/frontend/lib/Grounded/utils/RoutineTemplates.dart
alvocool 1a5867a98f Add routines module and full goal management
Routines: workout, meditation and must-do routines with timed, rep and
tick steps, sets and rest. A library screen, a builder with templates
and drag-to-reorder steps, and a full-screen player that auto-advances
timed phases, counts backgrounding and logs broken chains as partial.

Goals: a goal editor (deadline, colour, category, default class, archive),
routines linked to goals, and a goal field on tasks and routines. Tasks
added from inside a goal are now actually attached to it via parentId.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhQh614DMeYoQEH9SoMRUw
2026-11-02 08:45:41 +03:00

233 lines
6.8 KiB
Dart

import '../about/external/data/RoutineChain.dart';
import '../about/external/data/RoutineStep.dart';
import '../about/internal/application/CommitmentClass.dart';
import '../about/internal/application/RoutineKind.dart';
import '../about/internal/application/StepMode.dart';
/// Starting points for the routine builder. A blank routine is a harder
/// thing to commit to than one you only have to adjust.
class RoutineTemplates {
static List<RoutineChain> forKind(RoutineKind kind) {
switch (kind) {
case RoutineKind.Workout:
return <RoutineChain>[fullBody(), upperPush(), mobility()];
case RoutineKind.Meditation:
return <RoutineChain>[boxBreathing(), bodyScan()];
case RoutineKind.MustDo:
return <RoutineChain>[morning(), shutdown()];
}
}
static RoutineChain fullBody() {
return RoutineChain(
title: "Full body strength",
kind: RoutineKind.Workout,
days: <int>[1, 3, 5],
startMinute: 7 * 60,
steps: <RoutineStep>[
RoutineStep(
title: "Warm up",
mode: StepMode.Timed,
timerSeconds: 300,
cue: "Easy pace. Raise the heart rate, not the effort."),
RoutineStep(
title: "Deadlifts",
mode: StepMode.Reps,
sets: 4,
reps: 6,
timerSeconds: 45,
restSeconds: 120,
cue: "Brace, then push the floor away."),
RoutineStep(
title: "Goblet squats",
mode: StepMode.Reps,
sets: 3,
reps: 10,
timerSeconds: 40,
restSeconds: 90),
RoutineStep(
title: "Push-ups",
mode: StepMode.Reps,
sets: 3,
reps: 12,
timerSeconds: 30,
restSeconds: 60),
RoutineStep(
title: "Plank",
mode: StepMode.Timed,
sets: 3,
timerSeconds: 45,
restSeconds: 30,
cue: "Ribs down. Squeeze everything."),
RoutineStep(
title: "Cool down",
mode: StepMode.Timed,
timerSeconds: 180),
],
);
}
static RoutineChain upperPush() {
return RoutineChain(
title: "Shoulders & chest",
kind: RoutineKind.Workout,
days: <int>[2, 4],
startMinute: 18 * 60,
steps: <RoutineStep>[
RoutineStep(
title: "Band pull-aparts",
mode: StepMode.Reps,
sets: 2,
reps: 15,
timerSeconds: 30,
restSeconds: 30),
RoutineStep(
title: "Overhead press",
mode: StepMode.Reps,
sets: 4,
reps: 8,
timerSeconds: 40,
restSeconds: 90),
RoutineStep(
title: "Incline press",
mode: StepMode.Reps,
sets: 3,
reps: 10,
timerSeconds: 40,
restSeconds: 90),
RoutineStep(
title: "Lateral raises",
mode: StepMode.Reps,
sets: 3,
reps: 15,
timerSeconds: 35,
restSeconds: 45),
RoutineStep(
title: "Dips",
mode: StepMode.Reps,
sets: 3,
reps: 10,
timerSeconds: 35,
restSeconds: 60),
],
);
}
static RoutineChain mobility() {
return RoutineChain(
title: "Mobility flow",
kind: RoutineKind.Workout,
commitmentClass: CommitmentClass.Elective,
steps: <RoutineStep>[
RoutineStep(
title: "Cat-cow", mode: StepMode.Timed, timerSeconds: 60),
RoutineStep(
title: "World's greatest stretch",
mode: StepMode.Timed,
sets: 2,
timerSeconds: 45,
restSeconds: 10),
RoutineStep(
title: "Hip 90/90", mode: StepMode.Timed, timerSeconds: 90),
RoutineStep(
title: "Thoracic rotations",
mode: StepMode.Timed,
timerSeconds: 60),
],
);
}
static RoutineChain boxBreathing() {
return RoutineChain(
title: "Box breathing",
kind: RoutineKind.Meditation,
days: <int>[1, 2, 3, 4, 5, 6, 7],
startMinute: 6 * 60 + 30,
steps: <RoutineStep>[
RoutineStep(
title: "Settle",
mode: StepMode.Timed,
timerSeconds: 60,
cue: "Sit tall. Let the breath find its own pace."),
RoutineStep(
title: "Box breathing",
mode: StepMode.Timed,
timerSeconds: 300,
cue: "In 4 · hold 4 · out 4 · hold 4"),
RoutineStep(
title: "Open awareness",
mode: StepMode.Timed,
timerSeconds: 120,
cue: "Notice sounds, then let them go."),
],
);
}
static RoutineChain bodyScan() {
return RoutineChain(
title: "Evening body scan",
kind: RoutineKind.Meditation,
commitmentClass: CommitmentClass.Elective,
startMinute: 22 * 60,
steps: <RoutineStep>[
RoutineStep(
title: "Feet to hips",
mode: StepMode.Timed,
timerSeconds: 240,
cue: "Move attention slowly. Nothing to fix."),
RoutineStep(
title: "Torso and arms",
mode: StepMode.Timed,
timerSeconds: 240),
RoutineStep(
title: "Neck and face", mode: StepMode.Timed, timerSeconds: 180),
],
);
}
static RoutineChain morning() {
return RoutineChain(
title: "Morning non-negotiables",
kind: RoutineKind.MustDo,
commitmentClass: CommitmentClass.NonNegotiable,
days: <int>[1, 2, 3, 4, 5],
startMinute: 6 * 60,
steps: <RoutineStep>[
RoutineStep(
title: "Out of bed, no phone",
mode: StepMode.Check,
timerSeconds: 60),
RoutineStep(
title: "Glass of water", mode: StepMode.Check, timerSeconds: 60),
RoutineStep(
title: "Make the bed", mode: StepMode.Check, timerSeconds: 120),
RoutineStep(
title: "Write the three things for today",
mode: StepMode.Check,
timerSeconds: 300),
],
);
}
static RoutineChain shutdown() {
return RoutineChain(
title: "Evening shutdown",
kind: RoutineKind.MustDo,
days: <int>[1, 2, 3, 4, 5],
startMinute: 21 * 60 + 30,
steps: <RoutineStep>[
RoutineStep(
title: "Clear the desk", mode: StepMode.Check, timerSeconds: 180),
RoutineStep(
title: "Plan tomorrow's first task",
mode: StepMode.Check,
timerSeconds: 300),
RoutineStep(
title: "Phone on the charger, outside the bedroom",
mode: StepMode.Check,
timerSeconds: 60),
],
);
}
}