Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesClass TypesClass Types

Class Types

What is this

A class type is a reusable template that names a class (e.g. “CrossFit WOD”, “Open Gym”, “Pilates Reformer”), pins it to a parent program, and supplies sensible defaults that class_sessions inherit at creation time (defaultDurationMin, defaultCapacity, defaultLocationId, color). It also carries a hasWorkout flag — used to mark non-workout classes like “Open Gym” so the schedule UI knows not to demand programming for them.

Class types are studio-configured (owners/admins) and are the schedule’s vocabulary: every class_session row points at exactly one class_type, and every class_type points at exactly one program (which carries organizationId).

Who uses it

PersonaWhy
OwnerCreates/edits class types; sets defaults the schedule reuses.
AdminSame as owner.
CoachRead-only — selects a class type when creating a session.
MemberReads the class type name + color when browsing the schedule. No mutation.

Persona impact

  • Owner/admin edit-only via /dashboard/settings and /dashboard/schedule tabs (see i18n schedule.classTypes, schedule.classTypesTab).
  • Coach picks a class type at session-create time; if the class type’s hasWorkout=false the UI hides workout-attachment controls.
  • Member never interacts directly; sees the name and color in the calendar.

High-level capabilities

  1. CRUD — create, list, get, update, deactivate. Soft “deactivate” via isActive=false; rows are never hard-deleted.
  2. Program scoping — every class type belongs to a single program; the program (not the class type) is what carries the organizationId.
  3. Defaults inheritance — when POST /sessions runs without explicit capacity, the session inherits classType.defaultCapacity. When it runs with locationId omitted and the class type’s defaultLocationId points at an active space, the session gets that space (not flag-gated). defaultDurationMin and color are UI hints.
  4. No-workout marker — hasWorkout=false opts the class type out of the “this session needs programming” UX; used for Open Gym, drop-ins, etc.
  5. Safe day replication — Spotter can copy a schedule-mode program’s active sessions from one org-local date to several dates in one confirmed action. Each copied session is a draft; any conflicting destination is left untouched as a whole day. With the spaces flag on, a clash in an exclusive space also blocks the date.
  6. Default space — defaultLocationId pre-fills new sessions (ADR-0024 D4). It does not tie the class type to a space: each session stores its own location_id. The class-type form has a default space picker.

Relationship to other features

  • scheduling-bookings — every class_sessions.class_type_id FKs here.
  • locations — class_types.default_location_id FKs to a space (ON DELETE SET NULL).
  • organizations — org boundary lives on programs.organization_id; class types sit one level below.
  • Daily programming (daily_programming table) — keys by (class_type_id, date) so the same daily workout flows into every session of that class type on that day (unless the session has explicit class_session_workouts).

Current status

Shipped and stable. The hasWorkout flag is the most recent addition (i18n key schedule.classTypeSheet.hasWorkoutHelper: “Off for class types like Open Gym that don’t carry programmed workouts — only sessions are generated.”). A class type with it off carries the badge classTypes.noWorkoutBadge (“No workout” / “ללא אימון”).

Known gaps

  • findAll filters in JS after fetching all active class types (filters by program.organizationId post-query). Acceptable at current scale but inefficient — should push the org filter into SQL via join. (See class-types.service.ts:60-79.)
  • No “duplicate class type” affordance; owners re-type defaults if they want a sibling type.