All files / libs/payout-definition/plans/components/src/lib/duplicate-plan-form DuplicatePlanForm.tsx

91.25% Statements 73/80
75% Branches 3/4
100% Functions 0/0
91.25% Lines 73/80

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 811x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 3x 3x 3x 3x 5x 5x 5x 5x 5x 5x 2x 2x 2x 2x 2x 2x 2x 2x 2x               5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x  
import { memo, useCallback, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { z } from 'zod';
 
import { isConflictError } from '@amalia/core/http/client';
import { FormikForm, type FormikFormProps } from '@amalia/ext/formik';
import { type Plan } from '@amalia/payout-definition/plans/types';
import { useDuplicatePlan } from '@amalia/payout-definition/state';
 
export type DuplicatePlanFormValues = {
  name: string;
  shouldImportAssignments: boolean;
  assignmentsEffectiveAsOf: number | null;
  assignmentsEffectiveUntil: number | null;
};
 
const validationSchema = z.strictObject({
  name: z.string().min(2).max(100),
  shouldImportAssignments: z.boolean(),
  assignmentsEffectiveAsOf: z.number().nullable(),
  assignmentsEffectiveUntil: z.number().nullable(),
});
 
type DuplicatePlanFormikProps = FormikFormProps<DuplicatePlanFormValues, Plan>;
 
export type DuplicatePlanFormProps = Omit<
  DuplicatePlanFormikProps,
  'enableReinitialize' | 'initialValues' | 'onSubmit' | 'validationSchema'
> & {
  readonly plan: Pick<Plan, 'id' | 'name'>;
};
 
export const DuplicatePlanForm = memo(function DuplicatePlanForm({ plan, children, ...props }: DuplicatePlanFormProps) {
  const { formatMessage } = useIntl();
  const { mutateAsync: duplicatePlan } = useDuplicatePlan();
 
  const initialValues = useMemo(
    (): DuplicatePlanFormValues => ({
      name: formatMessage({ defaultMessage: '{planName} (copy)' }, { planName: plan.name }),
      shouldImportAssignments: false,
      assignmentsEffectiveAsOf: null,
      assignmentsEffectiveUntil: null,
    }),
    [plan.name, formatMessage],
  );
 
  const handleSubmit: DuplicatePlanFormikProps['onSubmit'] = useCallback(
    async (values, { setFieldError }) => {
      try {
        return await duplicatePlan({
          planId: plan.id,
          newPlanName: values.name,
          shouldImportAssignments: values.shouldImportAssignments,
          assignmentsEffectiveAsOf: values.assignmentsEffectiveAsOf,
          assignmentsEffectiveUntil: values.assignmentsEffectiveUntil,
        });
      } catch (err) {
        if (isConflictError(err)) {
          setFieldError('name', formatMessage({ defaultMessage: 'A plan with this name already exists.' }));
        }

        // Don't forget to throw the error again so `onSubmitSuccess` is not called
        throw err;
      }
    },
    [duplicatePlan, formatMessage, plan.id],
  );
 
  return (
    <FormikForm
      {...props}
      enableReinitialize={false}
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={handleSubmit}
    >
      {children}
    </FormikForm>
  );
});