All files / src/features/Merchants/MerchantSidePanel/AgreementAndSnapshot/Agreement/components TerminationForm.tsx

61.29% Statements 19/31
27.27% Branches 6/22
60% Functions 6/10
58.62% Lines 17/29

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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176                                                                28x                           1x     1x 1x 1x     1x         1x     1x                 1x   1x   1x                         1x                                 1x                 1x                                                             1x                                       28x         28x          
import { useRef } from "react";
import { styled, useAppTheme } from "@theme/v2/Provider";
import { Stack } from "@mui/material";
import {
  useForm,
  Controller,
  SubmitHandler,
  FormProvider,
} from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";
import { GiveInput } from "@shared/GiveInputs/GiveInput";
import GiveDatePicker from "@shared/DatePicker/GiveDatePicker";
import useUpdateMerchant from "features/Merchants/MerchantSidePanel/hooks/useUpdateMerchant";
import moment from "moment";
import { PLATFORM_TIMEZONE } from "@utils/timezones";
import { TMerchantBaseContextData } from "@components/Merchants/MerchantPreview/data.types";
 
// Define form values type
type FormValues = {
  processorName: string;
  terminationDate: Date | null | string;
  terminationReason: string;
};
 
interface Props {
  msaPreviousTerminationProcessorName: string | null | undefined;
  msaPreviousTerminationAt: number | Date | null | undefined;
  msaPreviousTerminationReason: string | null | undefined;
  defaultContext?: TMerchantBaseContextData;
}
// Define validation schema with Yup
const validationSchema = Yup.object().shape({
  processorName: Yup.string().required("Processor Name is required"),
  terminationDate: Yup.date()
    .required("Termination Date is required")
    .nullable(),
  terminationReason: Yup.string().required("Termination Reason is required"),
});
 
function TerminationForm({
  msaPreviousTerminationProcessorName,
  msaPreviousTerminationAt,
  msaPreviousTerminationReason,
  defaultContext,
}: Props) {
  const { palette, customs } = useAppTheme();
  const {
    updateMerchantMutation: { mutate, isLoading },
  } = useUpdateMerchant(defaultContext);
  const parsedTerminationDate = (() => {
    Iif (typeof msaPreviousTerminationAt === "number") {
      // If it's a UNIX timestamp, convert it to a formatted string
      return moment.unix(msaPreviousTerminationAt).tz(PLATFORM_TIMEZONE).format("MM/DD/YYYY");
    } else Iif (msaPreviousTerminationAt instanceof Date) {
      // If it's already a Date, format it as well
      return moment(msaPreviousTerminationAt).tz(PLATFORM_TIMEZONE).format("MM/DD/YYYY");
    }
    // If it's null or undefined, return an empty string or a specific default value
    return ""; // Or you can use null if preferred
  })();
 
  const methods = useForm<FormValues>({
    defaultValues: {
      processorName: msaPreviousTerminationProcessorName || "",
      terminationDate: parsedTerminationDate,
      terminationReason: msaPreviousTerminationReason || "",
    },
    resolver: yupResolver(validationSchema),
  });
 
  const { control, handleSubmit, getValues, setValue, watch } = methods;
 
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
 
  const onSubmit: SubmitHandler<FormValues> = (data) => {
    mutate({
      msaPreviousTermination: true,
      msaPreviousTerminationAt: moment(
        data?.terminationDate,
        "ddd MMM DD YYYY HH:mm:ss [GMT]ZZ",
      ).unix(),
      msaPreviousTerminationProcessorName: data?.processorName,
      msaPreviousTerminationReason: data?.terminationReason,
    });
  };
 
  // Handle blur to trigger submit if all fields are valid and filled
  const handleBlur = () => {
    clearTimeout(timeoutRef.current as NodeJS.Timeout);
    timeoutRef.current = setTimeout(() => {
      if (!document.activeElement || !document.activeElement.closest("form")) {
        const values = getValues();
 
        if (
          values.processorName &&
          values.terminationDate &&
          values.terminationReason
        ) {
          handleSubmit(onSubmit)();
        }
      }
    }, 100);
  };
 
  return (
    <FormProvider {...methods}>
      <form>
        <Stack flexDirection="column" mt="24px" gap="24px">
          <Controller
            name="processorName"
            control={control}
            disabled={isLoading}
            render={({ field, fieldState: { error } }) => (
              <Input
                {...field}
                label="Name of Previous Processor"
                onBlur={handleBlur}
                error={!!error}
                helperText={error?.message}
              />
            )}
          />
          <DatePicker
            name="terminationDate"
            disabled={isLoading}
            label="Date of Termination"
            onSetDate={(val) => {
              setValue("terminationDate", val, { shouldDirty: true });
              if (watch("processorName") && val && watch("terminationReason")) {
                handleSubmit(onSubmit)();
              }
            }}
            textFieldSx={{
              border: `1px solid ${palette.border?.secondary}`,
              borderRadius: `${customs?.radius.small}px`,
            }}
            maxDate={new Date()}
          />
 
          <Controller
            name="terminationReason"
            control={control}
            disabled={isLoading}
            render={({ field, fieldState: { error } }) => (
              <Input
                {...field}
                label="Reason for Termination"
                multiline
                rows={6}
                onBlur={handleBlur}
                error={!!error}
                helperText={error?.message}
              />
            )}
          />
        </Stack>
      </form>
    </FormProvider>
  );
}
 
export default TerminationForm;
 
// Styled input components
const Input = styled(GiveInput)(({ theme }) => ({
  border: `1px solid ${theme.palette.border?.secondary}`,
  borderRadius: `${theme.customs?.radius.small}px`,
}));
 
const DatePicker = styled(GiveDatePicker)(({ theme }) => ({
  border: `1px solid ${theme.palette.border?.secondary}`,
  borderRadius: `${theme.customs?.radius.small}px`,
  borderColor: "red",
}));