Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | // useListTeamMembersV2.ts
import { useMemo, useRef, useState } from "react";
import { useGetCurrentMerchantId } from "@hooks/common";
import { useAppSelector } from "@redux/hooks";
import { sorting as sortingReducer } from "@redux/slices/fundraisers";
import { selectQueryString } from "@redux/slices/search";
import { QKEY_LIST_TEAM_MEMBERS } from "@constants/queryKeys";
import { useTeamPermissions } from "features/Permissions/AccessControl/hooks";
import useCheckPAH from "@hooks/common/useCheckPAH";
import { usePahReassignmentStatus } from "@hooks/common/usePahReassignmentStatus";
import { useInfiniteQuery } from "react-query";
import { teamMembersInfiniteQueryFunction } from "./teamMembersInfiniteQueryFunction";
import { ROWS_PER_PAGE } from "@hooks/common/usePagination";
import { MemberData } from "@customTypes/team.member";
import {
buildInvitedPahRow,
excludeInvitedPah,
} from "../helpers/pahReassignmentRows";
const useListTeamMembersV2 = () => {
const { merchantId } = useGetCurrentMerchantId();
const sorting = useAppSelector(sortingReducer);
const searchQuery = useAppSelector((state) =>
selectQueryString(state, QKEY_LIST_TEAM_MEMBERS),
);
const { isListAllowed } = useTeamPermissions();
const { owner, isLoading: isOwnerLoading } = useCheckPAH(isListAllowed);
const { reassignment } = usePahReassignmentStatus(isListAllowed);
const {
data,
fetchNextPage,
isLoading,
isFetching,
isFetchingNextPage,
hasNextPage,
} = useInfiniteQuery(
[QKEY_LIST_TEAM_MEMBERS, merchantId, sorting, searchQuery],
teamMembersInfiniteQueryFunction({
merchantId,
sorting,
searchQuery,
memberStatus: "",
rowsPerPage: ROWS_PER_PAGE,
}),
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
enabled: Boolean(merchantId),
},
);
const allData = data?.pages.map((page: any) => page.data).flat() ?? [];
const members = useMemo(
() => allData.filter((row: any) => row.roleName !== "owner"),
[allData],
);
// GB-21472: while a reassignment is pending, surface the invited new PAH in
// the Primary Account Holder section (with an "Invitation Sent" status) and
// keep them out of the Members list — otherwise they show as their previous
// role (e.g. Administrator).
const visibleMembers = useMemo(
() => excludeInvitedPah(members, reassignment),
[members, reassignment],
);
const pahRows = useMemo(
() =>
[buildInvitedPahRow(reassignment, members), owner].filter(
Boolean,
) as MemberData[],
[reassignment, members, owner],
);
const [page, setPage] = useState(1);
const pageRef = useRef(1);
const handlePageChange = () => {
if (!isFetchingNextPage && hasNextPage) {
const newPage = pageRef.current + 1;
fetchNextPage();
pageRef.current = newPage;
setPage(newPage);
}
};
return {
data,
owner,
isLoading,
isFetching,
isFetchingNextPage,
hasNextPage,
page,
setPageDispatcher: setPage,
handlePageChange,
allRows: allData,
members: visibleMembers,
pahRows,
reassignment,
// Keep the total in step with the rows actually rendered: the invited PAH is
// moved out of Members into the PAH section, so drop it from the count
// (otherwise pagination over-counts by the excluded row). GB-21472.
totalRows: Math.max(
0,
(data?.pages?.[0]?.total ?? 0) - (members.length - visibleMembers.length),
),
searchQuery,
isOwnerLoading,
};
};
export default useListTeamMembersV2;
|