All files / packages/app/features/receipt-components receipt-participant-role-input.tsx

90.9% Statements 20/22
83.33% Branches 10/12
100% Functions 9/9
90.9% Lines 20/22

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                                88x           60x     54x 54x 54x 54x   54x     327x         54x   5x     5x       54x 54x               54x   42x                   137x                 6x     5x   84x   42x        
import React from "react";
 
import { useTranslation } from "react-i18next";
import { keys } from "remeda";
 
import { useTrpcMutationState } from "~app/hooks/use-trpc-mutation-state";
import { useTRPC } from "~app/utils/trpc";
import { Icon } from "~components/icons";
import { Select } from "~components/select";
import { Text } from "~components/text";
import { View } from "~components/view";
import type { AssignableRole, Role } from "~web/handlers/receipts/utils";
 
import { useActionsHooksContext, useReceiptContext } from "./context";
import type { Participant } from "./state";
 
const ROLES: Record<AssignableRole, true> = { editor: true, viewer: true };
 
type Props = {
	participant: Participant;
};
 
export const ReceiptParticipantRoleInput: React.FC<Props> = ({
	participant,
}) => {
	const { t } = useTranslation("receipts");
	const { receiptId, receiptDisabled } = useReceiptContext();
	const { updateParticipantRole } = useActionsHooksContext();
	const trpc = useTRPC();
	const removeParticipantMutationState =
		useTrpcMutationState<"receiptParticipants.update">(
			trpc.receiptParticipants.update.mutationKey(),
			(vars) =>
				vars.receiptId === receiptId &&
				vars.peerId === participant.peerId &&
				// oxlint-disable-next-line typescript/no-unnecessary-condition
				vars.update.type === "role",
		);
	const changeRole = React.useCallback(
		(nextRole: AssignableRole) => {
			Iif (nextRole === participant.role) {
				return;
			}
			updateParticipantRole(participant.peerId, nextRole);
		},
		[participant.role, participant.peerId, updateParticipantRole],
	);
	const roleTexts = React.useMemo<Record<Role, string>>(
		() => ({
			viewer: t("participant.role.viewer"),
			editor: t("participant.role.editor"),
			owner: t("participant.role.owner"),
		}),
		[t],
	);
 
	return (
		<Select
			items={keys(ROLES).map((role) => ({ role }))}
			label={t("participant.role.select.label")}
			placeholder=""
			isDisabled={
				receiptDisabled ||
				participant.role === "owner" ||
				removeParticipantMutationState?.status === "pending"
			}
			className="min-w-[160px]"
			renderValue={() => (
				<View className="flex flex-row gap-2">
					<Icon className="size-6" name={participant.role} />
					<Text>{roleTexts[participant.role]}</Text>
				</View>
			)}
			selectedKeys={[
				participant.role === "owner" ? "viewer" : participant.role,
			]}
			onSelectionChange={(nextKeys) => {
				Iif (!nextKeys[0]) {
					return;
				}
				changeRole(nextKeys[0]);
			}}
			getKey={({ role }) => role}
		>
			{({ role }) => <Text>{roleTexts[role]}</Text>}
		</Select>
	);
};