Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesDashboard ShellCode map — dashboard shell

Code map — dashboard shell

Shared

PathResponsibility
libs/shared/src/lib/i18n/dictionaries/{en,he,ru}.jsonnav.* (reused), dashboardShell.* (sections, switcher, home, Schedule title/subtitle/WOD chip/stats.wodsPosted*, Coaching list/new-plan dialog/stats.plans*/workoutsThisWeekCount, Ways to train’s two switches and its waysToTrain.blocked.* “still in use” dialog), programs.stats.* (reused by both screens’ strips — enrolled, workoutsThisWeek, completionRate, sessionsThisWeek, bookingsThisWeek, membersThisWeek, fillRate; the strips use short stats.* subtitles instead of the tooltips), announcements.title (reused for the Thrive entry), schedule.setupTimetable.classTypes* (the Schedule screen’s Class types menu item)

API

PathResponsibility
apps/api/src/programs/programs.service.tscoachingStats(orgId, programId, weekStart) (private, extracted from findByIdWithStats’s coaching branch — no behavior change) and coachingSummary(orgId, clerkId, weekStart?), which fans it out over every active coaching program and aggregates totals; getDeactivationBlockers(orgId, programId) (counts future published sessions / active enrollments by delivery mode) and checkDeactivationBlockers(orgId, programId, clerkId) (membership + owner/admin gate, then delegates), both consumed by remove() and the isActive: true → false path of update() to refuse deactivation with a 409 while either count is nonzero
apps/api/src/programs/programs.controller.tsGET :orgId/programs/coaching-summary, registered in the literal sub-routes block before :id; GET :orgId/programs/:id/deactivation-blockers, returning { data: { futurePublishedSessions, activeEnrollments } }

Config

PathResponsibility
apps/web/src/config/dashboard-sections.tsSectionId, ROUTE_PLACEMENT for optional Home cards and exhaustive route coverage, SECTION_DEFAULT_ROUTE, sectionsForRole, sectionForPath

Hooks

PathResponsibility
apps/web/src/hooks/dashboard-shell/use-section-nav-items.tsxBuilds optional Home-card item lists — icons, hrefs, badges, and feature gates
apps/web/src/hooks/dashboard-shell/use-section-navigation.tsResolves Home-card sections and their destinations; records Home preferences and computes Train’s live default
apps/web/src/lib/dashboard-shell/home-prefs.tslocalStorage read/write for optional Home preferences, keyed by user+org
apps/web/src/hooks/use-programming-week-actions.tsThe Spotter handler for WeeklyCalendar’s condensed-view toolbar — see daily-programming/code-map.md. Copy-week/publish-week mutations were removed along with their only caller, the standalone board

Components

PathResponsibility
apps/web/src/components/dashboard-shell/section-greeting.tsxSectionGreeting({eyebrow, action?}) — the Overview greeting under a section-name eyebrow, reused by Schedule and Coaching. Overview keeps its own copy
apps/web/src/components/programs/stats-strip.tsxStatsStrip({tiles, isLoading}) — a row of ProgramStatCard tiles, column count tracking tile count, each with a soft stagger-in animation
apps/web/src/components/programs/program-stat-card.tsxProgramStatCard — one KPI tile (icon, value/skeleton, label, info tooltip). Moved out of the program detail page; imported back there unchanged
apps/web/src/components/programs/program-with-stats.tsProgramWithStats type (the GET .../programs/:id?weekStart= payload shape) — shared by the detail page and ScheduleScreen

Routes

PathResponsibility
apps/web/src/app/[lang]/(protected)/dashboard/layout.tsxAlways renders DashboardSidebar and the original dashboard header
apps/web/src/app/[lang]/(protected)/dashboard/home/page.tsxOptional direct Home landing — greeting, role-aware work-area cards, “remember my choice”, and “continue where I left off”; never an entry redirect
apps/web/src/app/[lang]/(protected)/dashboard/schedule/page.tsxRenders schedule-screen.tsx
apps/web/src/app/[lang]/(protected)/dashboard/schedule/schedule-screen.tsxThe Schedule destination: SectionGreeting, a StatsStrip for the viewed week (Sessions/Bookings/Members/Fill rate/WODs posted), then WeeklyCalendar for the org’s one active schedule program (enableClassStudioExtras). Redirects to Workouts when the org runs no schedule program
apps/web/src/app/[lang]/(protected)/dashboard/coaching/page.tsxThe Coaching destination: SectionGreeting with the “New coaching plan” action, a StatsStrip from .../programs/coaching-summary, then a list of the org’s active coaching plans (name, active state, per-plan enrolled/workouts/completion line) — each row sourced from the same summary payload, no per-row fetch. Opening a plan navigates to /dashboard/programs/:id. None: redirects to Workouts.
apps/web/src/app/[lang]/(protected)/dashboard/programs/page.tsxNo list: forwards to Settings > General’s Ways to train section (#settings-ways-to-train).
apps/web/src/components/settings/ways-to-train-settings.tsxOwner/admin-only training-mode configuration in Settings > General: Schedule and Cohorts switches create/reactivate/deactivate their underlying program(s) through the existing programs API. Turning a switch off first fetches deactivation blockers for the affected program(s) (fetchBlockers); zero counts show the existing confirm dialog, a nonzero count opens the blocking “still in use” dialog instead (and the same dialog reopens from a racing 409 on the DELETE itself).
apps/web/src/app/[lang]/(protected)/dashboard/programs/[id]/page.tsxRenders every tab for both delivery modes. Its delete button shows a deleteBlocked toast on a 409 program_in_use (upcoming published sessions or active enrollments), the generic failure toast otherwise; a successful delete lands on Coaching
apps/web/src/app/[lang]/(protected)/dashboard/audit-log/page.tsxNew standalone route for the top bar’s Audit log link — renders the existing AuditLogContent, gated by useCan('audit', 'view')
apps/web/src/app/[lang]/(protected)/dashboard/messages/page.tsxReads ?tab=announcements once at mount for deep links (announcements is a tab of Messages under Train, not a sidebar entry)

Flat navigation

PathResponsibility
apps/web/src/components/overview/sidebar-nav.tsx (DashboardSidebar)The permanent flat sidebar: all permitted navigation items remain concurrently visible. Training shows enabled Schedule/Cohorts plus Workouts/Movements. Courses and Programs are hidden.
apps/web/src/app/[lang]/(protected)/dashboard/settings/(shell)/admin/page.tsxAudit log route inside Settings
apps/web/src/app/[lang]/(protected)/dashboard/programs/[id]/page.tsxSee Routes above

Test infra

PathResponsibility
apps/web/vitest.setup.ts, apps/web/src/testing/global-mock-state.tsxuseFeatureFlag/useGatedFeature mocks now forward the flag key to mockFeatureFlag, so a spec can discriminate flags with mockFeatureFlag.mockImplementation((flag) => flag === FeatureFlags.X). Backward compatible with existing mockReturnValue(...) usage

Existing coverage

  • apps/web/src/config/dashboard-sections.unit.spec.ts — placement map vs. the actual route folders on disk
  • apps/web/src/lib/dashboard-shell/home-prefs.unit.spec.ts — optional Home preferences
  • apps/web/src/components/overview/sidebar-nav.int.spec.tsx — flat sidebar navigation contract
  • apps/web/src/app/[lang]/(protected)/dashboard/schedule/schedule-screen.int.spec.tsx — single-schedule-program resolution and empty-state redirect, the section greeting, the week stats strip (sourced from the detail-stats endpoint), and the WODs-posted tile
  • apps/web/src/components/overview/schedule/weekly-calendar.int.spec.tsx — includes the folded-in WOD chip, board toolbar actions, and Class types menu item, all gated on enableClassStudioExtras (see daily-programming/code-map.md)
  • apps/web/src/app/[lang]/(protected)/dashboard/coaching/coaching-page.int.spec.tsx — the plan list, enrolled count, “New coaching plan”, the section greeting’s action button, the stats-strip totals and per-row stats sourced from coaching-summary
  • apps/api/src/programs/programs.service.unit.spec.ts — ProgramsService.coachingSummary: totals aggregation, enrolled-weighted completion mean excluding programs with no assignments that week, zero-plan org, membership enforcement; getDeactivationBlockers/remove/update — per-mode blocker counts, 409 program_in_use with the counts when either is nonzero, deactivation proceeding at zero
  • apps/web/src/components/settings/ways-to-train-settings.int.spec.tsx — the two Settings > General switches: create/reactivate/deactivate for each, confirm dialogs, the blocked “still in use” dialog for a nonzero session/enrollment count (per switch, never calling DELETE), the same dialog from a racing 409, the coach omission
  • apps/web/src/app/[lang]/(protected)/dashboard/home/home-page.int.spec.tsx — includes the “Ways to train” secondary link
  • apps/web/src/app/[lang]/(protected)/dashboard/layout.int.spec.tsx
  • These are coverage locations, not claims that this documentation pass ran validation.