PR: #338: [Story-1330] Add Team Deactivated tab by @ayush-pramaan
View PR →

Team Deactivated tab

Story-1330 - pramaan-app - Settings - Firm configuration - Team

Files changed

15 file(s), +470 / -78 lines

Path Role + -
messages/en.jsonConfig+7-1
messages/hi.jsonConfig+7-1
src/components/settings/team/members-table.stories.tsxComponent+21-1
src/components/settings/team/members-table.tsxComponent+3-1
src/components/settings/team/presentation.tsComponent+46-2
src/components/settings/team/team-list-content.stories.tsxComponent+142-9
src/components/settings/team/team-list-content.tsxComponent+11-18
src/components/settings/team/team-list-page.stories.tsxComponent+9-0
src/components/settings/team/team-list-page.tsxComponent+29-24
src/components/settings/team/team-list-toolbar.stories.tsxComponent+13-2
src/components/settings/team/team-list-toolbar.tsxComponent+15-7
src/components/settings/team/use-team-list-actions.tsComponent+16-9
src/components/settings/team/use-team-mutations.tsComponent+31-3
src/components/settings/team/use-team-tab-state.tsComponent+73-0
tests/unit/team-presentation.test.tsTest+47-0

1 - Three tab model

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.

2 - Deactivate -> Deactivated

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.

3 - Reactivate -> Members

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.

4 - Search, counts, pagination

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.

5 - Verification map

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.