All files / libs/plan-agreements/components/src/lib/modals PlanAgreementsDuplicateModal.tsx

17.92% Statements 19/106
100% Branches 0/0
100% Functions 0/0
17.92% Lines 19/106

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 1071x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                                                                               1x  
import { IconCopy } from '@tabler/icons-react';
import { memo, useCallback, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import { generatePath } from 'react-router-dom';
 
import { FormLayout, Modal, useSnackbars } from '@allshares/studio-design-system';
import { routes } from '@amalia/core/routes';
import { FormikInput } from '@amalia/design-system/ext';
import { FormikForm } from '@amalia/ext/formik';
import { useNavigate } from '@amalia/ext/react-router-dom';
import { nameGenerator } from '@amalia/ext/string';
import { assert, toError } from '@amalia/ext/typescript';
import { useDuplicatePlanAgreement, useFindPlanAgreements } from '@amalia/plan-agreements/state';
import { duplicatePlanAgreementSchema, type DuplicatePlanAgreementRequest } from '@amalia/plan-agreements/types';
 
import { usePlanAgreementsModalsContext } from './PlanAgreementsModals.context';
 
export const PlanAgreementsDuplicateModal = memo(function PlanAgreementsDuplicateModal() {
  const navigate = useNavigate();
  const { snackError } = useSnackbars();

  const { data: planAgreements } = useFindPlanAgreements();

  const { closeModal, planAgreementForModal } = usePlanAgreementsModalsContext();

  const { mutateAsync: duplicatePlanAgreement, isPending } = useDuplicatePlanAgreement(planAgreementForModal?.id);

  const initialValues = useMemo<DuplicatePlanAgreementRequest>(() => {
    assert(planAgreementForModal, 'Plan agreement is required');

    return {
      name: nameGenerator(
        `${planAgreementForModal.name} (copy)`,
        planAgreements?.map((planAgreement) => planAgreement.name) ?? [],
      ),
    };
  }, [planAgreementForModal, planAgreements]);

  const handleSubmit = useCallback(
    async (values: DuplicatePlanAgreementRequest) => {
      try {
        const duplicatedPlanAgreement = await duplicatePlanAgreement({
          name: values.name.trim(),
        });

        closeModal();
        navigate(generatePath(routes.PLAN_AGREEMENT_EDIT, { planAgreementId: duplicatedPlanAgreement.id }));
      } catch (error) {
        snackError(toError(error).message);
      }
    },
    [closeModal, duplicatePlanAgreement, navigate, snackError],
  );

  assert(planAgreementForModal, 'Plan agreement is required');

  return (
    <Modal
      isOpen
      onClose={closeModal}
    >
      <FormikForm
        initialValues={initialValues}
        validationSchema={duplicatePlanAgreementSchema}
        onSubmit={handleSubmit}
      >
        {({ isValid }) => (
          <FormikForm.FormDisplayContents>
            <Modal.Content>
              <Modal.Header>
                <Modal.Title>
                  <FormattedMessage defaultMessage="Duplicate plan agreement" />
                </Modal.Title>
              </Modal.Header>

              <Modal.Body>
                <FormLayout>
                  <FormLayout.Group>
                    <FormikInput
                      required
                      label={<FormattedMessage defaultMessage="New agreement name" />}
                      name="name"
                    />
                  </FormLayout.Group>
                </FormLayout>
              </Modal.Body>
            </Modal.Content>

            <Modal.Actions>
              <Modal.CancelAction disabled={isPending} />

              <Modal.MainAction
                disabled={!isValid}
                icon={<IconCopy />}
                isLoading={isPending}
                type="submit"
              >
                <FormattedMessage defaultMessage="Duplicate" />
              </Modal.MainAction>
            </Modal.Actions>
          </FormikForm.FormDisplayContents>
        )}
      </FormikForm>
    </Modal>
  );
});