Skip to content

feat(projects): pick each member's project role in the staff picker - #374

Merged
nourshoreibah merged 1 commit into
mainfrom
worktree-project-member-roles
Aug 25, 2026
Merged

feat(projects): pick each member's project role in the staff picker#374
nourshoreibah merged 1 commit into
mainfrom
worktree-project-member-roles

Conversation

@nourshoreibah

Copy link
Copy Markdown
Collaborator

Problem

The UI gave no way to say what role someone holds on a project. The projects API has accepted [{ user_id, role }] since roles were introduced (validateMembers, apps/backend/lambdas/projects/validation-utils.ts), but ProjectFormModal posted members: number[], so every assignment fell through to the API's Student default.

Editing was the sharper edge: seeding the form dropped member.role entirely, so a save re-sent bare ids and relied on syncMemberships' "keep the role they already held" fallback. Correct by accident, and impossible to change a role through.

Change

  • StaffPicker carries a MemberAssignment per person instead of a user id. The selected chips become rows: name + email, a role dropdown, and the remove button. New picks start at DEFAULT_PROJECT_ROLE, which is exactly what the API would have applied on its own.
  • ProjectFormModal seeds each row from the role that member already holds and posts the assignments as-is.
  • ProjectDetailView renders the role beside the name via the title slot StaffCard already had, so a role you set is visible without reopening the form.
  • types/project.ts re-exports PROJECT_ROLES / ProjectRole / DEFAULT_PROJECT_ROLE from @branch/rbac instead of keeping the second copy that had grown there — the same re-export the projects lambda does, so the picker's options and the values the API accepts cannot drift.
  • DropdownSelector gains disabled and ariaLabel. Its own doc comment already anticipated "callers that repeat the control per row, where the visible label is the row rather than the field"; this is that caller.

No backend, schema, or @branch/rbac changes — the API side was already there.

Tests

New test/components/ProjectFormModal.test.tsx (4 cases): existing members seed with the role they hold, a changed role reaches the request body, a newly picked member defaults to Student and posts whatever it is changed to, and a removed member drops out of the roster.

Verified locally in apps/frontend: tsc --noEmit clean, next lint clean, npm run build green, full jest suite 38/38 suites and 366 tests passing.

🤖 Generated with Claude Code

The projects API has always accepted `[{ user_id, role }]` for a project's
roster, but the form only ever posted bare ids, so every assignment landed on
the API's `Student` default and there was no way to make anyone a Director or
project Admin from the UI. Editing a project was worse than that: seeding
dropped `member.role`, so a save re-sent ids with no role and silently relied
on the backend's "keep the role they already held" fallback.

The staff picker now carries an assignment per person instead of an id. The
selected chips become rows with a role dropdown, defaulting new picks to the
same `DEFAULT_PROJECT_ROLE` the API would have applied, and edit mode seeds
each row with the role that member already holds. The project page shows the
role beside the name, using the slot `StaffCard` already had for it.

Roles come from `@branch/rbac` rather than the copy that had grown in
`types/project.ts` — the same re-export the projects lambda does, so the
picker's options and the values `validateMembers` accepts cannot drift.

`DropdownSelector` gains `disabled` and `ariaLabel`, which a control repeated
per row needs: the visible label is the row, not the field.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nourshoreibah
nourshoreibah force-pushed the worktree-project-member-roles branch from 448e35c to 8ce2e31 Compare August 25, 2026 02:23
@nourshoreibah nourshoreibah added no-review The PR review bot won't run test-environment Creates a temporary (nearly free) test environment. Uses prod DB and cognito labels Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🌿 ⏳ Creating preview environment… (logs)

@github-actions

Copy link
Copy Markdown
Contributor

🌿 Preview environment — ready ✅

Open: https://d3nmtjoh6ir9ym.cloudfront.net/pr-374/
API: https://jli01mwdx9.execute-api.us-east-2.amazonaws.com/prod

Shared RDS + Cognito (prod data); DB migrations are not applied here — if this PR adds a migration, endpoints using the new columns will fail until it merges. New commits update this environment in place — a note is posted here on each update. Remove the test-environment label or close the PR to tear it down.

@nourshoreibah
nourshoreibah marked this pull request as ready for review August 25, 2026 02:46
@nourshoreibah
nourshoreibah merged commit 4796c9f into main Aug 25, 2026
27 checks passed
@nourshoreibah
nourshoreibah deleted the worktree-project-member-roles branch August 25, 2026 02:46
@github-actions

Copy link
Copy Markdown
Contributor

🌿 Preview environment torn down 🧹 — the stack for this PR has been destroyed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-review The PR review bot won't run test-environment Creates a temporary (nearly free) test environment. Uses prod DB and cognito

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant