Skip to content

Homeroom↔course link — FE usage (quick guide)

The three integration points for the new class↔course link, in one page. Full contract (cascade behavior, courseCascade[] toast, error codes): docs/fe-guides/2026-08-06-homeroom-course-link-FE-guide.md.

A course can declare which class it belongs to ("1B's math course"). One optional key, three places to touch:

1. Create-course form — add a class selector (optional homeroomId)

POST /api/v1/subject-groups accepts an optional homeroomId inside composition:

{
  "composition": {
    "name": "Matematica 1B",
    "curriculumSubjectId": "cs_…",
    "gradeId": "g_…",
    "studentIds": [],
    "homeroomId": "hr_…"        // ← the new selector; omit = unlinked course
  }
}
  • Populate the selector from GET /api/v1/filters/homerooms?surface=homerooms&curriculumId=<id>&gradeId=<id>. The homeroom surface projects policy-visible candidate classes and the cascade filters server-side — the BE still 409s a mismatched class (SUBJECT_GROUP_LINK_MISMATCH).
  • Show the selector only for mandatory subjects — an option-block course cannot be linked (SUBJECT_GROUP_LINK_ANCHOR_IN_BLOCK).
  • The response (and every course detail/list/table row) echoes it back as homeroom: { id, name } | null.
  • Editable later via PATCH /subject-groups/:id with { "composition": { "homeroomId": "hr_…" } } to re-link or { "composition": { "homeroomId": null } } to clear — metadata only, the roster is never touched by a link change.

No new field to send. POST /api/v1/subject-groups/from-homeroom already carries the class in its top-level homeroomId, and the BE stamps the link automatically on every mandatory CREATE item:

{
  "homeroomId": "hr_…",                  // already there — this IS the link source
  "courses": [
    { "curriculumSubjectId": "cs_…", "studentIds": ["st_…"], "name": "Matematica 1B" }
  ]
}
  • The created courses come back with homeroom: { id, name } already set — do not render a class selector in the wizard.
  • In-block (optional) creates stay unlinked; MERGE items never change the target course's existing link.

3. Homeroom page — render the linked courses from linkedCourses[]

GET /api/v1/homerooms/:id (and every homeroom write response) now carries:

"linkedCourses": [
  { "id": "sg_…", "name": "Matematica 1B", "subject": { "id": "cs_…", "name": "Matematica" } },
  { "id": "sg_…", "name": "Italiano 1B",   "subject": { "id": "cs_…", "name": "Italiano" } }
]
  • Use id + name to render the course cards on the class page (link each card to the course detail by id); subject.name is there for grouping or a subtitle.
  • Already ordered by subject name, then course name. [] = no linked courses.

Good to know

  • Roster changes on a class now cascade into its linked courses (add / remove / move students): the write responses carry a courseCascade[] report that must be surfaced to the admin. See the full guide before touching the class roster screens.
  • The courses table filter ?homeroomId= now also matches linked courses even with an empty roster (union with the old roster-overlap semantics — no wire change).