15 file(s), +470 / -78 lines
| Path | Role | + | - |
|---|---|---|---|
| messages/en.json | Config | +7 | -1 |
| messages/hi.json | Config | +7 | -1 |
| src/components/settings/team/members-table.stories.tsx | Component | +21 | -1 |
| src/components/settings/team/members-table.tsx | Component | +3 | -1 |
| src/components/settings/team/presentation.ts | Component | +46 | -2 |
| src/components/settings/team/team-list-content.stories.tsx | Component | +142 | -9 |
| src/components/settings/team/team-list-content.tsx | Component | +11 | -18 |
| src/components/settings/team/team-list-page.stories.tsx | Component | +9 | -0 |
| src/components/settings/team/team-list-page.tsx | Component | +29 | -24 |
| src/components/settings/team/team-list-toolbar.stories.tsx | Component | +13 | -2 |
| src/components/settings/team/team-list-toolbar.tsx | Component | +15 | -7 |
| src/components/settings/team/use-team-list-actions.ts | Component | +16 | -9 |
| src/components/settings/team/use-team-mutations.ts | Component | +31 | -3 |
| src/components/settings/team/use-team-tab-state.ts | Component | +73 | -0 |
| tests/unit/team-presentation.test.ts | Test | +47 | -0 |
The Team surface now renders Members, Pending,
and Deactivated in that order. Accepted PRAMAAN member rows
come from useAppListMembers(status: all); Clerk organization
invitations remain isolated behind the existing pending-invitation query.
| Tab | Rows shown | Empty state |
|---|---|---|
Members |
Accepted firm members where status === "active". |
No active members. |
Pending |
Clerk organization invitation records only. | No pending invitations. |
Deactivated |
Accepted firm members where
status === "deactivated".
|
No deactivated members. |
Deactivation still uses the generated
useAppDeactivateMember mutation. On success, the returned
FirmMemberListItem is written into the hydrated Team member
cache before the collection is invalidated. Because tab rows are derived
from member status, the row leaves Members and appears under
Deactivated without a manual refresh.
Reactivation uses the generated
useAppReactivateMember mutation and the same cache-sync path.
The returned active member row leaves Deactivated, re-enters
Members, and seat billing is invalidated with the existing
seat query.
Each tab keeps its own search query and page index. Counts are computed
from the filtered rows for each tab, so a search in Members
cannot hide pending invitations or deactivated accounts. Pagination reads
the active tab's own page state.
| Surface | Evidence |
|---|---|
presentation.ts |
Unit tests cover active, pending, and deactivated row splitting, search isolation, and filtered counts. |
TeamListContent |
Storybook states cover populated, empty, loading, error, search, pagination, and mutation-pending rows for all three tabs. |
messages/en.json / messages/hi.json |
New tab label, placeholder, deactivated error, and deactivated empty-state copy exist in both locales. |
Backend status modelling and Clerk invitation lifecycle were intentionally left unchanged. This story only separates the existing accepted-member statuses on the app surface.