Skip to content

As an instruktør I want my training data linked to my gym so I can keep my classes varied alongside co-instruktører #136

@ChristopherRotnes

Description

@ChristopherRotnes

Summary

Workout Lens is moving from a single-user logger toward a tool for instruktører at the same gym (Sporty business unit). The primary value is helping an instruktør keep their sessions varied over time — and crucially, when several instruktører share a recurring class slot (e.g. Styrke Mandag 18:00 taught by different people on different weeks), they need visibility into the joint session history for that slot to avoid repetition. Before building this, we need an explicit decision on identity, sharing default, and the foundation table that links users to a gym.

This is a large epic — only the foundational decisions and the smallest schema change land here; sharing UI, joint-class views, opt-out toggles, and the temporal roles table are tracked as follow-up issues.

Priority

High (blocks: instruktør variety view, joint-class history, future profile/sharing/permission UI)

Decisions to record

  • Primary user: instruktører at the same Sporty business unit. Class participants (the ~20 people in the room) are not modelled as users in this iteration.
  • Sharing default: opt-out, scoped to same gym (same Sporty business unit). By default, an instruktør's sessions are visible to other instruktører at the same gym; they can opt out per session.
  • Exercise model: keep per-user exercise_library and denormalised snapshots in session_template_exercises (no canonical global exercise catalogue in this iteration).
  • Joint-class aggregation: rely on existing gym_calendar linkage — sessions already reference gym_calendar_id, so "all sessions for Styrke Mandag" is a query, not a schema change.

Smallest schema change

Add a user_gyms table linking users to a Sporty business unit. The role column is included now as a temporary placeholder; it will be replaced by a FK to a dedicated roles table (id, name, title, valid_from, valid_to) for temporal role tracking in a later issue.

create table user_gyms (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null references auth.users(id) on delete cascade,
  sporty_business_unit_id int not null,
  -- role is a temporary text placeholder; will be replaced by a FK to a
  -- dedicated roles table (id, name, title, valid_from, valid_to) in a later issue.
  role text not null default 'instruktor',
  created_at timestamptz not null default now(),
  unique (user_id, sporty_business_unit_id)
);

-- RLS
alter table user_gyms enable row level security;
create policy "users see own membership" on user_gyms
  for select using (auth.uid() = user_id);
create policy "users manage own membership" on user_gyms
  for all using (auth.uid() = user_id) with check (auth.uid() = user_id);

This unlocks the "same gym" visibility scope without any read-side changes yet — a follow-up issue will use it to expose joint-class history.

Acceptance criteria

  • user_gyms table created via Supabase migration with RLS as above
  • role column added as a text placeholder defaulting to 'instruktor'
  • CLAUDE.md updated under "Key architecture decisions" recording the instruktør-primary, opt-out-same-gym sharing model and user_gyms purpose
  • Hardcoded business unit 8 reference in app/api/sportySync.js flagged as the membership default for first users (or a follow-up issue opened to remove the hardcode once membership lookup replaces it)
  • Follow-up issue opened: joint-class history view across instruktører at same gym
  • Follow-up issue opened: per-session opt-out toggle (visibility flag on sessions)
  • Follow-up issue opened: dedicated roles table with temporal validity (id, name, title, valid_from, valid_to) and migration of user_gyms.role to a FK
  • Follow-up issue opened: profile visibility fields (display name, etc.) once names appear next to shared data
  • Verified by developer on dev/qa/prod before closing

Out of scope

  • Any sharing UI (read or write)
  • Coach ↔ client model
  • Participant-side users (members attending the class)
  • Global exercise catalogue / cross-user exercise canonicalisation
  • Profile visibility / display name fields
  • Cross-gym visibility
  • Building the roles/titles lookup table with temporal validity (separate issue)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions