All files / libs/lti/components/src/lib/grants PlanInviteUsersButton.tsx

0% Statements 0/100
0% Branches 0/1
0% Functions 0/1
0% Lines 0/100

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                                                                                                                                                                                                         
import { IconRefresh, IconSend } from '@tabler/icons-react';
import { Fragment, memo, useCallback, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';

import { IconLoading, Modal, Table, Typography } from '@allshares/studio-design-system';
import { useBoolState } from '@amalia/ext/react/hooks';
import { useSendInvitations } from '@amalia/lti/state';
import { type LtiGrant, type LtiGrantWithUser, type LtiPlan } from '@amalia/lti/types';

interface PlanInviteUsersButtonProps {
  readonly plan: LtiPlan;
  readonly grants?: LtiGrantWithUser[];
  readonly selectedGrantIds: LtiGrant['id'][];
  readonly setSelectedGrantIds: (selectedGrantIds: LtiGrant['id'][]) => void;
}

export const PlanInviteUsersButton = memo(function PlanInviteUsersButton({
  grants,
  plan,
  selectedGrantIds,
  setSelectedGrantIds,
}: PlanInviteUsersButtonProps) {
  const { mutate: sendInvitations, isPending } = useSendInvitations();
  const { isModalOpen, setModalOpenFalse, setModalOpenTrue } = useBoolState(false, 'modalOpen');

  const grantsToSend = useMemo(
    () => (grants ?? []).filter((g) => selectedGrantIds.includes(g.id) && !g.invitationSentAt),
    [grants, selectedGrantIds],
  );

  const handleOpenModal = useCallback(() => {
    setModalOpenTrue();
  }, [setModalOpenTrue]);

  const handleConfirm = useCallback(() => {
    sendInvitations({
      planId: plan.id,
      sendInvitationsRequest: { grantIds: grantsToSend.map((g) => g.id) },
    });
    setModalOpenFalse();
    setSelectedGrantIds([]);
  }, [setModalOpenFalse, sendInvitations, setSelectedGrantIds, grantsToSend, plan]);

  const handleCancel = () => {
    setModalOpenFalse();
  };

  return (
    <Fragment>
      <Table.BulkAction
        icon={<IconSend />}
        iconLoading={<IconLoading icon={IconRefresh} />}
        isLoading={isPending}
        onClick={handleOpenModal}
      >
        <FormattedMessage
          defaultMessage="Send {count, plural, one {invitation} other {invitations}}"
          values={{ count: selectedGrantIds.length }}
        />
      </Table.BulkAction>

      <Modal
        isOpen={isModalOpen}
        onClose={handleCancel}
      >
        <Modal.Content>
          <Modal.Header>
            <Modal.Title>
              <FormattedMessage defaultMessage="Send invitations" />
            </Modal.Title>
          </Modal.Header>

          <Modal.Body>
            <Typography variant="bodyBaseRegular">
              <FormattedMessage
                defaultMessage="Confirm sending {grantsCount, plural, one {# invitation} other {# grants}}, this will allocate {sharesCount, plural, one {# share} other {# shares}}."
                values={{
                  grantsCount: grantsToSend.length,
                  sharesCount: grantsToSend.reduce((acc, curr) => acc + curr.nbShares, 0),
                }}
              />
            </Typography>
          </Modal.Body>
        </Modal.Content>

        <Modal.Actions>
          <Modal.CancelAction />

          <Modal.MainAction
            disabled={!grantsToSend.length}
            isLoading={isPending}
            onClick={handleConfirm}
          >
            <FormattedMessage defaultMessage="Confirm" />
          </Modal.MainAction>
        </Modal.Actions>
      </Modal>
    </Fragment>
  );
});