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",
}));
|