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

65.38% Statements 17/26
77.27% Branches 17/22
75% Functions 3/4
62.5% Lines 15/24

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                                                  36x                                 47x 47x 47x 47x 47x 47x   47x     47x       47x                   47x 1x       47x                                         47x   34x                                                              
import React, { forwardRef, useImperativeHandle } from "react";
import { FormProvider, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";
import { StatusInfo } from "../../agreements.types";
import { REFUND_POLICY_MAX_TEXT_LENGTH } from "@constants/constants";
import SectionCardBase from "@shared/SidePanel/components/SectionCard/SectionCardBase";
import GiveText from "@shared/Text/GiveText";
import useUpdateMerchant from "features/Merchants/MerchantSidePanel/hooks/useUpdateMerchant";
import { useMerchantSidePanelContext } from "features/Merchants/MerchantSidePanel/Provider/MerchantSidePanelProvider";
import { HFGiveInput } from "@shared/HFInputs/HFGiveInput/HFGiveInput";
import { useEnterprisePermissions } from "@components/AcquirerEnterprises/CreateEnterprise/hooks/useEnterprisePermissions";
import { checkPortals } from "@utils/routing";
import { TMerchantBaseContextData } from "@components/Merchants/MerchantPreview/data.types";
import { RefundPolicyHandle } from "@features/Merchants/MerchantSidePanel/ApprovalFlowPanel/types";
 
interface Props {
  statusInfo?: StatusInfo;
  defaultContext?: TMerchantBaseContextData;
  isOnboarding?: boolean;
  merchantID?: number;
  msaRefundPolicyFromParent?: string;
}
 
// Define Yup validation schema
const validationSchema = Yup.object().shape({
  msaRefundPolicy: Yup.string()
    .trim()
    .min(3, "Refund policy must be at least 3 characters")
    .required("Refund policy is required"),
});
 
function RefundPolicy(
  {
    statusInfo,
    defaultContext,
    isOnboarding,
    merchantID,
    msaRefundPolicyFromParent,
  }: Props,
  ref: React.Ref<RefundPolicyHandle>,
) {
  const { status } = statusInfo || {};
  const context = useMerchantSidePanelContext();
  const { data } = defaultContext ?? context;
  const { updateMerchantMutation } = useUpdateMerchant(context, merchantID);
  const { agreement_signing } = useEnterprisePermissions();
  const { isEnterprisePortal } = checkPortals();
 
  const isInputHidden = status === "signed";
 
  const isInputDisabled =
    updateMerchantMutation.isLoading ||
    (!agreement_signing && isEnterprisePortal);
 
  // Initialize useForm with validation schema
  const methods = useForm({
    resolver: yupResolver(validationSchema),
    defaultValues: {
      msaRefundPolicy:
        data?.merchantAgreement?.msaRefundPolicy ||
        msaRefundPolicyFromParent ||
        "",
    },
  });
 
  useImperativeHandle(ref, () => ({
    getValue: () => methods.getValues("msaRefundPolicy"),
  }));
 
  // Handle blur event
  const handleBlur = (
    e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) => {
    const value = e.target.value;
    // Check validation and update if valid
    methods.clearErrors("msaRefundPolicy");
    if (value) {
      const trimmedValue = value.trim();
      try {
        const { error } = validationSchema.validateSync({
          msaRefundPolicy: trimmedValue,
        });
        if (!error) {
          updateMerchantMutation.mutate({ msaRefundPolicy: trimmedValue });
        }
      } catch (err: any) {
        methods.setError("msaRefundPolicy", err.message);
      }
    }
  };
 
  if (isInputHidden) return null;
 
  return (
    <SectionCardBase
      sx={{ mt: "20px" }}
      leftTitle="Refund Policy"
      {...(isOnboarding ? { childrenContainerSx: { padding: 0 } } : {})}
    >
      <FormProvider {...methods}>
        <HFGiveInput
          name="msaRefundPolicy"
          onBlur={handleBlur}
          multiline
          rows={6}
          placeholder="30 Days of Purchase"
          disabled={isInputDisabled}
          maxLength={REFUND_POLICY_MAX_TEXT_LENGTH}
        />
      </FormProvider>
      <GiveText
        mt={isOnboarding ? "12px" : "8px"}
        variant={isOnboarding ? "bodyS" : "bodyXS"}
        color="secondary"
      >
        Please provide a detailed description of your refund policy. This should
        include conditions for eligibility, the refund process, and any time
        constraints.
      </GiveText>
    </SectionCardBase>
  );
}
 
export default forwardRef(RefundPolicy);