import type { Table } from "@tanstack/react-table"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; import { DataTableSelectionBar } from "@calcom/features/data-table"; import classNames from "@calcom/lib/classNames"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc"; import { Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Icon, Popover, PopoverContent, PopoverTrigger, showToast, } from "@calcom/ui"; import type { UserTableUser } from "../types"; interface Props { table: Table; } export function TeamListBulkAction({ table }: Props) { const { data: teams } = trpc.viewer.organizations.getTeams.useQuery(); const [selectedValues, setSelectedValues] = useState>(new Set()); const [removeFromTeams, setRemoveFromTeams] = useState>(new Set()); const utils = trpc.useUtils(); const mutation = trpc.viewer.organizations.addMembersToTeams.useMutation({ onError: (error) => { showToast(error.message, "error"); }, onSuccess: (res) => { showToast( `${res.invitedTotalUsers} Users invited to ${Array.from(selectedValues).length} teams`, "success" ); // Optimistically update the data from query trpc cache listMembers // We may need to set this data instead of invalidating. Will see how performance handles it utils.viewer.organizations.listMembers.invalidate(); // Clear the selected values setSelectedValues(new Set()); table.toggleAllRowsSelected(false); }, }); const removeMemberMutation = trpc.viewer.teams.removeMember.useMutation({ onError: (error) => { showToast(error.message, "error"); }, onSuccess: () => { showToast(`${selectedUsers.length} Users removed from ${removeFromTeams.size} teams`, "success"); utils.viewer.organizations.listMembers.invalidate(); // Clear the selected values setRemoveFromTeams(new Set()); table.toggleAllRowsSelected(false); }, }); const { t } = useLocale(); const selectedUsers = table.getSelectedRowModel().flatRows.map((row) => row.original); // Add a value to the set const addValue = (set: Set, setSet: Dispatch>>, value: number) => { const updatedSet = new Set(set); updatedSet.add(value); setSet(updatedSet); }; // Remove value from the set const removeValue = (set: Set, setSet: Dispatch>>, value: number) => { const updatedSet = new Set(set); updatedSet.delete(value); setSet(updatedSet); }; return ( <> {t("add_to_team")} {/* We dont really use shadows much - but its needed here */} No results found. {teams && teams.map((option) => { const areAllUsersInTeam = selectedUsers.every((user) => user.teams.some((team) => team.id === option.id) ); const isSelected = (selectedValues.has(option.id) || areAllUsersInTeam) && !removeFromTeams.has(option.id); return ( { if (!isSelected) { if (areAllUsersInTeam) { removeValue(removeFromTeams, setRemoveFromTeams, option.id); } else { addValue(selectedValues, setSelectedValues, option.id); } } else { if (areAllUsersInTeam) { addValue(removeFromTeams, setRemoveFromTeams, option.id); } else { removeValue(selectedValues, setSelectedValues, option.id); } } }}> {option.name}
); })}
); }