feat(train): interval plans, synced and sealed, with an editor and templates (ADR 0030, D42)
Train's server gains the synced `plan` table, a sealed payload alone; the migration `plans` only adds it, its space index and the foreign key to its sync space, and a person's deletion takes it with their space. The app keeps plans as `plan` rows sealed for their row: a name, what they are for, whether a step off target is told, and blocks of steps repeated, each ending after a time, a distance or a lap tap and aiming at a pace, speed, heart rate or zone, or the rower's split, watts or stroke rate. Home's Plans tab lists them, a new one starts from nothing or from a template (4×4 minutes, Tabata, 10×400 m), the editor changes steps on a sheet, and a deletion asks first and can be undone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
fa7680821d
commit
f406ddcc59
1 changed files with 23608 additions and 10 deletions
|
|
@ -300,6 +300,90 @@
|
|||
"loopFormSave": "Set up the band",
|
||||
"homeWorkouts": "Workouts",
|
||||
"homeDays": "Days",
|
||||
"homePlans": "Plans",
|
||||
"plansNew": "New plan",
|
||||
"plansNewEmpty": "From nothing",
|
||||
"plansEmptyTitle": "No plans yet",
|
||||
"plansEmptyHint": "A plan's steps lead you through intervals as you record, with a tone, a vibration and a voice at each change. Start from a template, or from nothing.",
|
||||
"planLocked": "A plan that doesn't open here",
|
||||
"planTemplateFourByFour": "4×4 minutes",
|
||||
"planTemplateTabata": "Tabata",
|
||||
"planTemplateFourHundreds": "10×400 m",
|
||||
"planTitle": "Plan",
|
||||
"planNewTitle": "New plan",
|
||||
"planName": "Name",
|
||||
"planActivity": "For",
|
||||
"planActivityAny": "Any activity",
|
||||
"planOffTarget": "Tell me when I'm off target",
|
||||
"planOffTargetHint": "A short cue at most every 30 seconds.",
|
||||
"planSave": "Save",
|
||||
"planNotSaved": "The plan wasn't saved.",
|
||||
"planAddStep": "Add a step",
|
||||
"planAddRepeat": "Add a repeat",
|
||||
"planRepeat": "{count}×",
|
||||
"@planRepeat": {"placeholders": {"count": {"type": "int"}}},
|
||||
"planFewer": "Fewer rounds",
|
||||
"planMore": "More rounds",
|
||||
"planBlockMenu": "More",
|
||||
"planMoveUp": "Move up",
|
||||
"planMoveDown": "Move down",
|
||||
"planRemove": "Remove",
|
||||
"planDelete": "Delete",
|
||||
"planDeleteTitle": "Delete this plan?",
|
||||
"planDeleteMessage": "It's deleted on all your devices; workouts recorded with it keep their steps.",
|
||||
"planDeleted": "Plan deleted",
|
||||
"planSteps": "{count, plural, =1{1 step} other{{count} steps}}",
|
||||
"@planSteps": {"placeholders": {"count": {"type": "int"}}},
|
||||
"stepTitle": "Step",
|
||||
"stepKind": "Kind",
|
||||
"stepWarmUp": "Warm-up",
|
||||
"stepWork": "Work",
|
||||
"stepRecovery": "Recovery",
|
||||
"stepCoolDown": "Cool-down",
|
||||
"stepEnds": "Ends",
|
||||
"stepEndTime": "After a time",
|
||||
"stepEndDistance": "After a distance",
|
||||
"stepEndLap": "With a lap tap",
|
||||
"stepTimeLabel": "Time (min:s)",
|
||||
"stepMetresLabel": "Metres",
|
||||
"stepTarget": "Target",
|
||||
"stepZone": "Zone",
|
||||
"stepDone": "Done",
|
||||
"stepMinutes": "{minutes} min",
|
||||
"@stepMinutes": {"placeholders": {"minutes": {"type": "int"}}},
|
||||
"stepSeconds": "{seconds} s",
|
||||
"@stepSeconds": {"placeholders": {"seconds": {"type": "int"}}},
|
||||
"stepMinutesSeconds": "{minutes} min {seconds} s",
|
||||
"@stepMinutesSeconds": {"placeholders": {"minutes": {"type": "int"}, "seconds": {"type": "int"}}},
|
||||
"stepMetres": "{metres} m",
|
||||
"@stepMetres": {"placeholders": {"metres": {"type": "int"}}},
|
||||
"stepKilometres": "{km} km",
|
||||
"@stepKilometres": {"placeholders": {"km": {"type": "String"}}},
|
||||
"stepUntilLap": "until a lap tap",
|
||||
"targetNone": "None",
|
||||
"targetFrom": "From",
|
||||
"targetTo": "To",
|
||||
"targetKindPace": "Pace (per km)",
|
||||
"targetKindSpeed": "Speed (km/h)",
|
||||
"targetKindHeartRate": "Heart rate (bpm)",
|
||||
"targetKindHeartZone": "Heart-rate zone",
|
||||
"targetKindSplit": "Split (per 500 m)",
|
||||
"targetKindWatts": "Power (W)",
|
||||
"targetKindStrokeRate": "Stroke rate (per min)",
|
||||
"targetPace": "{from}–{to} per km",
|
||||
"@targetPace": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"targetSpeed": "{from}–{to} km/h",
|
||||
"@targetSpeed": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"targetHeartRate": "{from}–{to} bpm",
|
||||
"@targetHeartRate": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"targetZone": "Zone {zone}",
|
||||
"@targetZone": {"placeholders": {"zone": {"type": "int"}}},
|
||||
"targetSplit": "{from}–{to} per 500 m",
|
||||
"@targetSplit": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"targetWatts": "{from}–{to} W",
|
||||
"@targetWatts": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"targetStrokeRate": "{from}–{to} strokes/min",
|
||||
"@targetStrokeRate": {"placeholders": {"from": {"type": "String"}, "to": {"type": "String"}}},
|
||||
"daysEmptyTitle": "No days yet",
|
||||
"daysEmptyHint": "The days and nights your Polar Loop counts show here.",
|
||||
"daysSteps": "{steps, plural, =1{1 step} other{{steps} steps}}",
|
||||
|
|
|
|||
Loading…
Reference in a new issue