All files / libs/payout-definition/plans/components/src/lib/create-plan-form CreatePlanForm.tsx

100% Statements 81/81
85.71% Branches 6/7
100% Functions 0/0
100% Lines 81/81

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 821x 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 12x 12x 12x 12x 12x 12x 12x 12x 7x 7x 12x 12x 12x 12x 12x 12x 7x 7x 7x 12x 12x 12x 12x 12x 12x 5x 5x 5x 3x 2x 2x 3x 3x 3x 3x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 1x  
import { memo, useCallback, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { z } from 'zod';
 
import { isConflictError } from '@amalia/core/http/client';
import { getSupportedPlanFrequencies } from '@amalia/core/types';
import { FormikForm, type FormikFormProps } from '@amalia/ext/formik';
import { type MergeAll } from '@amalia/ext/typescript';
import { type PeriodFrequencyEnum } from '@amalia/payout-definition/periods/types';
import { type Plan } from '@amalia/payout-definition/plans/types';
import { useCreatePlan } from '@amalia/payout-definition/state';
import { useCurrentCompany } from '@amalia/tenants/companies/state';
 
type CreatePlanFormValues = {
  name: string;
  frequency: PeriodFrequencyEnum;
};
 
type CreatePlanFormikProps = FormikFormProps<CreatePlanFormValues, Plan>;
 
export type CreatePlanFormProps = MergeAll<
  [
    Omit<CreatePlanFormikProps, 'initialValues' | 'onSubmit' | 'validationSchema'>,
    {
      duplicateOf?: {
        id: string;
        name: string;
      };
    },
  ]
>;
 
export const CreatePlanForm = memo(function CreatePlanForm({ duplicateOf, ...props }: CreatePlanFormProps) {
  const { formatMessage } = useIntl();
  const { data: company } = useCurrentCompany();
  const { mutateAsync: createPlan } = useCreatePlan();
 
  const defaultFrequency = getSupportedPlanFrequencies(company)[0];
 
  const initialValues: CreatePlanFormValues = useMemo(
    () => ({
      name: duplicateOf?.name ?? '',
      frequency: defaultFrequency,
    }),
    [duplicateOf, defaultFrequency],
  );
 
  const validationSchema = useMemo(
    () =>
      z.strictObject({
        name: z.string().min(2).max(100),
        frequency: z.enum(getSupportedPlanFrequencies(company)),
      }) satisfies z.ZodType<CreatePlanFormValues>,
    [company],
  );
 
  const handleSubmit: Required<CreatePlanFormikProps>['onSubmit'] = useCallback(
    async (values: CreatePlanFormValues, { setFieldError }) => {
      try {
        return await createPlan(values);
      } catch (err) {
        if (isConflictError(err)) {
          setFieldError('name', formatMessage({ defaultMessage: 'A plan with this name already exists.' }));
        }
 
        // Throw for FormikForm.
        throw err;
      }
    },
    [createPlan, formatMessage],
  );
 
  return (
    <FormikForm
      {...props}
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={handleSubmit}
    />
  );
});