3a5b929284
Schema
- Workout.programDayId added (nullable FK to ProgramDay) so a
Workout logged from a program day can be tied back to the planned
session for adherence analytics. Compat ALTER in entrypoint adds
the column + index to existing /data; ON DELETE SET NULL so
deleting a program doesn't remove historical workouts logged
against it.
- Back-relation `workouts: Workout[]` added to ProgramDay.
API (proof-of-work/app/api/programs/...)
- GET /api/programs — list user's programs
- POST /api/programs — create with full nested
weeks/days/exercises
tree in one transaction
- GET /api/programs/[id] — full tree
- PATCH /api/programs/[id] — update metadata AND/OR
replace entire weeks
tree (same shape as
POST). UI editor + AI
apply flow share this.
- DELETE /api/programs/[id] — cascading
- POST /api/programs/[id]/days/[dayId]/start
— creates a Workout
pre-populated with
empty SetLogs (one per
planned set), tagged
with programDayId.
UI (proof-of-work/app/main/programs/...)
- /main/programs — list with cards, today's-session
callout, "active" badge
- /main/programs/new — create form using ProgramEditor
- /main/programs/[id] — detail + edit using same editor;
today's-session card + Start button
if program is active
- ProgramEditor component (components/programs/ProgramEditor.tsx) —
expandable tree editor for weeks -> days -> exercises with
per-row sets/reps/RPE/rest/notes fields + library exercise picker
- ProgramActions: delete button
- StartSessionButton: POSTs to start endpoint, redirects to new
workout
Navigation
- "Programs" link added to bottom nav + sidebar (between Workouts
and Exercises).
- /main/programs page itself shows the today's-session card; the
same component pattern can be lifted into the dashboard later
if we want.
lib/db/programs.ts
- getPrograms, getProgramById, getActivePrograms,
computeTodaysSessionForProgram, getTodaysSession helpers.
- Today's session math: floor((todayUTC - startDateUTC) / 1day),
weekNumber = floor(.../7) + 1, dayOfWeek = today.getUTCDay().
Returns null if not started, past durationWeeks, or no day
matching today's slot (= rest day).
Tests (tests/routes-programs.test.ts)
- 11 new tests covering: 401 unauthenticated, full-tree create
with nested weeks+days+exercises, cross-user exerciseId
rejection, list scoped to actor, GET detail returns 404 for
another user's program, PATCH replace-tree atomicity,
cascading DELETE, start-day Workout creation with the right
number of empty SetLogs + programDayId stamped, start-day
refused for cross-user program day.
- Total: 96 tests across 11 files.
This is the foundation for v1.1.0:2's AI-generated programs —
the AI will produce the same JSON shape POST /api/programs
already accepts, so the apply path is `editor.tsx + POST
/api/programs` with no new API surface.
53 lines
2.3 KiB
TypeScript
53 lines
2.3 KiB
TypeScript
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
|
|
|
/**
|
|
* v1.1.0:1 — Programs (manual create / save / follow).
|
|
*
|
|
* The Program / ProgramWeek / ProgramDay / ProgramExercise schema
|
|
* has existed since the legacy `workout-log` package but had no
|
|
* UI to use it. This release ships:
|
|
*
|
|
* - /main/programs (list) with a today's-session card if any
|
|
* program is active.
|
|
* - /main/programs/new (create form) with the full nested
|
|
* editor: program metadata -> weeks -> days -> exercises.
|
|
* - /main/programs/[id] (detail + edit) using the same editor,
|
|
* plus today's-session callout + "Start this session"
|
|
* button when applicable.
|
|
* - API: GET/POST /api/programs, GET/PATCH/DELETE
|
|
* /api/programs/[id]. PATCH replaces the entire weeks tree
|
|
* in one transaction (same shape POST accepts) — keeps the
|
|
* UI editor and the upcoming AI apply flow on the same code
|
|
* path.
|
|
* - "Start this session" wires through
|
|
* POST /api/programs/[id]/days/[dayId]/start which creates a
|
|
* Workout pre-populated with empty SetLogs from the planned
|
|
* ProgramExercises (one row per planned set), tagged with
|
|
* Workout.programDayId so we can later compute adherence.
|
|
*
|
|
* Schema change
|
|
* - Workout.programDayId (nullable FK to ProgramDay) added.
|
|
* - Compat ALTER in docker_entrypoint.sh adds the column +
|
|
* index to existing /data on first boot. ON DELETE SET NULL
|
|
* so deleting a program doesn't catastrophically remove
|
|
* historical workouts logged against it.
|
|
*
|
|
* This release is the foundation for v1.1.0:2's AI-generated
|
|
* programs — the AI will produce the same JSON shape that POST
|
|
* /api/programs already accepts.
|
|
*
|
|
* No data migration. /data on existing installs is untouched
|
|
* apart from the new column.
|
|
*/
|
|
export const v_1_1_0_1 = VersionInfo.of({
|
|
version: '1.1.0:1',
|
|
releaseNotes: {
|
|
en_US:
|
|
'Programs UI shipped. Build a multi-week training plan, mark it active, and follow it day by day from a new "Today\'s session" card. Includes a full nested editor (program -> weeks -> days -> exercises), starts a session as a pre-populated workout you fill in as you go, and tracks Workout.programDayId for upcoming adherence analytics. Foundation for v1.1.0:2 (AI-generated programs).',
|
|
},
|
|
migrations: {
|
|
up: async () => {},
|
|
down: IMPOSSIBLE,
|
|
},
|
|
})
|