40227-vm/frontend/docs/my-class-integration.md

61 lines
3.8 KiB
Markdown

# My Class Integration
## Purpose
`/my-class` gives class-scoped staff a roster view for their assigned class and lets higher-scope
users view a classroom roster after drilling into a class from the scope switcher. The page lists
students, linked guardians, and assigned class staff. Users with the required user-management
permissions can add and edit student user accounts directly from the Students section, including
linked guardian accounts for each student.
## Slice Files
- Page: `frontend/src/pages/modules/MyClassPage.tsx`
- Business API re-exports: `frontend/src/business/my-class/api.ts`
- Business selectors: `frontend/src/business/my-class/selectors.ts`
- Shared APIs reused from User Admin: `frontend/src/shared/api/users.ts`, `frontend/src/shared/api/roles.ts`
- Shared UI reused from User Admin: `ImageUpload`, `UserAvatar`, common inputs/selects/buttons
## Behavior
- The page resolves the current class from the selected effective scope first. If the selected scope
is a classroom, that classroom is used; otherwise the signed-in user's own `classId` is used for
class-scoped staff.
- Higher-scope users must drill into a classroom before `/my-class` can show a roster. Class-scoped
users without an assigned class see the unassigned-class message.
- The Students section lists class-scoped student users from `GET /api/users?classId=<classId>`.
Backend listing includes both direct `users.classId` matches and students linked through
`class_enrollments`, which is how the seeded class roster is represented.
- The add/edit form is collapsible. It is fixed to the current class, the seeded `student` role id,
and the seeded `guardian` role id. It does not show arbitrary role, tenant, or custom-permission
controls.
- Form fields mirror the reusable User Admin identity fields: avatar, title, first name, last name,
email, and phone number.
- Creating a student calls `POST /api/users` with `app_role=<student role id>` and the current
`classId`; editing calls `PUT /api/users/:id` with the same fixed role and class scope.
- When the backend returns `temporaryPassword` because the mailer is not configured, the form stays
open and shows the generated password once with copy instructions. Teachers must copy the student
or guardian password before leaving the form and deliver it manually.
- The same form includes a repeatable Guardians section with photo upload. When guardian fields are
entered, the UI creates or updates each `guardian` user through the shared user API, then calls
`POST /api/guardian_students` to link that guardian to the student. The link endpoint is
idempotent.
- On edit, all existing guardian links for the student are loaded into the Guardians section. The
teacher can add additional unsaved guardian rows from the same form.
- The UI enables create/edit controls only when the current user has `CREATE_USERS` or
`UPDATE_USERS`, a current `classId`, and the `student` / `guardian` role ids have loaded.
- Backend user service guards remain authoritative: class-scoped users can only manage student
accounts in their own class and guardian accounts linked to students in their own class. Direct
`users.classId` and `class_enrollments` membership both count as own-class membership, so seeded
enrollment-backed students can be edited from `/my-class`. The guardian-student link service also
verifies that class-scoped links connect a `guardian` user to a `student` user in the teacher's
own class. Class-scoped user management cannot add custom permissions or permission exclusions.
## Tests
- `frontend/src/business/my-class/selectors.test.ts` covers payload normalization and permission /
class / role gating.
- Backend coverage lives in `backend/src/services/users.test.ts`,
`backend/src/services/guardian_students.test.ts`,
`backend/src/services/shared/role-policy.test.ts`, and `backend/src/db/seeders/user-roles.test.ts`.