v1.1.0:1 — Programs UI (manual create / save / follow)
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.
This commit is contained in:
@@ -6,20 +6,32 @@ import { v_1_0_0_4 } from './v1.0.0.4'
|
||||
import { v_1_0_0_5 } from './v1.0.0.5'
|
||||
import { v_1_0_0_6 } from './v1.0.0.6'
|
||||
import { v_1_0_0_7 } from './v1.0.0.7'
|
||||
import { v_1_1_0_1 } from './v1.1.0.1'
|
||||
|
||||
/**
|
||||
* Version graph for the `proof-of-work` package.
|
||||
*
|
||||
* v1.0.0:1 — initial release, seeded cutover from `workout-log`.
|
||||
* 1.0.0 line — feature-complete logger + multi-user + library curation.
|
||||
* 1.1.0 line — Programs (manual + AI) + AI integration.
|
||||
*
|
||||
* v1.0.0:1 — initial release, seeded cutover.
|
||||
* v1.0.0:2 — CSP fix.
|
||||
* v1.0.0:3 — post-cutover seed strip.
|
||||
* v1.0.0:4 — removes default admin@local credentials.
|
||||
* v1.0.0:5 — internal cleanup (caloriesBurned raw-SQL workaround).
|
||||
* v1.0.0:5 — caloriesBurned raw-SQL workaround removed.
|
||||
* v1.0.0:6 — paginate workout history (infinite scroll).
|
||||
* v1.0.0:7 — exercise library cleanup, photo-import removal,
|
||||
* UI honesty about AI.
|
||||
* v1.0.0:7 — exercise library cleanup, photo-import removal.
|
||||
* v1.1.0:1 — Programs UI (manual create / save / follow).
|
||||
*/
|
||||
export const versionGraph = VersionGraph.of({
|
||||
current: v_1_0_0_7,
|
||||
other: [v_1_0_0_1, v_1_0_0_2, v_1_0_0_3, v_1_0_0_4, v_1_0_0_5, v_1_0_0_6],
|
||||
current: v_1_1_0_1,
|
||||
other: [
|
||||
v_1_0_0_1,
|
||||
v_1_0_0_2,
|
||||
v_1_0_0_3,
|
||||
v_1_0_0_4,
|
||||
v_1_0_0_5,
|
||||
v_1_0_0_6,
|
||||
v_1_0_0_7,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
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,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user