Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesDaily ProgrammingDaily programming — code map

Daily programming — code map

API

Base path: /organizations/:orgId/daily-programming

RouteMethodService method
PUT /Whole-day replaceset
GET /?weekStart=Week readfindByWeek
GET /?date=Date readfindByDate
PATCH /statusFlip draft↔publishedsetStatus
DELETE /?classTypeId&datePhysical removeremove
GET /board?weekStart=&programId=Week board; programId narrows rows to one program’s class types, optionalgetBoard
POST /copy-weekCopy last week’s published cells as draftscopyWeek
POST /publish-weekPublish every draft cell on a weekpublishWeek
POST /quick-workoutBoard quick freeform note → publishcreateQuickWorkout

Plus GET /organizations/:orgId/workouts/posted?weekStart=&classTypeId=&page= on WorkoutsController, delegating to DailyProgrammingService.listPosted (WorkoutsModule imports DailyProgrammingModule for this).

Controller: apps/api/src/daily-programming/daily-programming.controller.ts Service: apps/api/src/daily-programming/daily-programming.service.ts Module: apps/api/src/daily-programming/daily-programming.module.ts

Cross-feature internal export: findByDateRange(orgId, startDate, endDate, publishedOnly) is consumed by ClassSessionsService. Section payloads come from the shared toWorkoutSectionResponses in apps/api/src/common/workout-section.ts — the one serializer every member-facing section read uses. getSessionCountsInWindow (private) is the shared “does this class type have a live session on this date” lookup getBoard uses.

DTOs

  • apps/api/src/daily-programming/dto/set-daily-programming.dto.ts — SetDailyProgrammingDto (classTypeId, date, status?, entry?: 'pick'|'quick_note'|'paste', workouts:[{workoutId, sortOrder}]).
  • Inline SetStatusDto in the controller — classTypeId, date, status: 'draft'|'published'.
  • dto/copy-week.dto.ts, dto/publish-week.dto.ts, dto/quick-workout.dto.ts — the board’s three new writes.

Tracking

libs/shared/src/lib/analytics/programming-events.ts — ProgrammingEvents.WOD_PUBLISHED ('wod_published') and ProgrammingEvents.WOD_POST_COMPLETED ('wod_post_completed'), emitted via EventTrackingService.track. See the README’s Analytics bullet for exactly which writes fire which.

Web

PathFile
Class session detail (consumer)apps/web/src/app/[lang]/(protected)/dashboard/schedule/sessions/[sessionId]/page.tsx
Paste page (board round-trip)apps/web/src/app/[lang]/(protected)/dashboard/workouts/new/paste/page.tsx → paste-workout-view.tsx. Publish rides on the parse commit request itself (publishTo) rather than a second PUT /daily-programming call.

There is no standalone Programming route. The Schedule surface owns the Programming matrix beside Calendar and Condensed.

Components

  • apps/web/src/hooks/use-programming-week-actions.ts — useProgrammingWeekActions({ orgId, weekStartIso, programId?, programName?, rows, sessions }): the Spotter handler for WeeklyCalendar’s toolbar. Carries only draftWithSpotter — copy-week/publish-week mutations were removed with the standalone board, their only caller. draftWithSpotter is async: it best-effort fetches last week’s board and the program’s saved schedule templates (useApi().fetchWithAuth, each swallowed on failure — the affected section is just omitted), builds the message with buildSpotterWeekPrompt (apps/web/src/lib/programming/spotter-week-prompt.ts, unit-tested pure function — locale-aware date/day formatting, per-class-type status line composition, last-wee…
  • apps/web/src/components/overview/schedule/weekly-calendar.tsx — with enableClassStudioExtras (the Schedule screen), the calendar exposes Calendar, Condensed, and Programming display modes. Programming consumes the existing board query, renders its class-type × day matrix, writes PUT /daily-programming, and clears same-day session overrides so every live session inherits the shared workout.
  • apps/web/src/components/overview/schedule/daily-programming-view.tsx — presentational programming matrix. It renders an assignment target only when a class type has live sessions on that date.
  • apps/web/src/components/overview/schedule/weekly-condensed.tsx — each condensed row shows the session’s workout name (data-testid="condensed-session-workout"); no board-specific props remain.
  • apps/web/src/components/overview/schedule/setup-timetable-menu.tsx — a showClassTypes prop (Schedule screen only) adds a “Class types” item (data-testid="schedule-setup-class-types") opening a sheet with ProgramClassTypesTab for the schedule program.
  • apps/web/src/components/overview/programming/week-grid.tsx — presentational “row × 7 days” grid shared with the coaching program grid (member-week-grid.tsx, see the workout-assignments code map). Owns the header (translated day labels, today highlight), sticky first column, cell box model/skeleton (weekGridCellBaseClass); callers supply rows, renderCell, and optionally onCellClick/renderRowActions. Its only current caller is member-week-grid.tsx — the class-type × day board that used it (programming-week-board.tsx) was deleted with the standalone board.
  • apps/web/src/components/overview/workouts/posted-by-day-view.tsx — the Workouts page’s “Posted by day” segmented view; toggled from apps/web/src/app/[lang]/(protected)/dashboard/workouts/page.tsx.
  • enableClassStudioExtras (passed only by the Schedule screen) decides whether WeeklyCalendar fetches the board and shows its actions at all.

DB

libs/db/src/lib/schema/scheduling.ts:

  • daily_programming table. See data-model.md. No schema change for the board — it composes existing daily_programming + class_sessions + workouts.is_library.

Shared

libs/shared/src/lib/schemas/daily-programming.schema.ts — response/request types for the existing endpoints plus the board (ProgrammingBoardResponse, BoardCellState, CopyWeekResponse, PublishWeekResponse, PostedWorkoutRow/PostedWorkoutsResponse).

libs/shared/src/lib/agent-schemas/daily-programming.ts — the daily_programming agent router’s input schemas. libs/shared/src/lib/agent-schemas/class-sessions.ts — classSessionsCopyWeekInputSchema (programId, fromWeekStart, toWeekStart), the Spotter-facing mirror of CopyWeekDto.

Tests

  • daily-programming.service.unit.spec.ts — findByDateRange live/dead-programme filtering.
  • daily-programming.week-board.unit.spec.ts — getBoard cell-state derivation, copyWeek, publishWeek.
  • daily-programming.events.unit.spec.ts — wod_published/wod_post_completed emission from set, and createQuickWorkout.
  • apps/api/src/ai/agent/tools/leaves/class-sessions.copy-week.tools.unit.spec.ts — class_sessions.copy_week’s decorator metadata (router/action/scope/sideEffects/confirm/audit) and delegation to ClassSessionsService.copyWeek.
  • apps/web/src/lib/programming/spotter-week-prompt.unit.spec.ts — buildSpotterWeekPrompt: locale-aware date/day formatting (en/he/ru), per-class-type status line composition and omissions, the “no sessions this week” case, the ran-last-week diff.
  • apps/web/src/components/overview/schedule/weekly-calendar.int.spec.tsx (describe('Schedule screen extras')) — the folded-in toolbar (Spotter button in both views, draft-session bulk actions inside the timetable menu, the condensed Add-a-session row — all gated on enableClassStudioExtras), and the Class types menu item (gated on enableClassStudioExtras alone).
  • apps/web/src/components/overview/workouts/posted-by-day-view.int.spec.tsx, .../workouts/workouts-page.int.spec.tsx — Posted-by-day listing, Save to Workouts, and the segmented control.
  • Apply-from-template path is exercised by:
    • apps/web/e2e/specs/schedule-setup.spec.ts
    • apps/web/e2e/specs/session-sheets.spec.ts