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 | 13x 113x 113x 113x 113x 113x 113x 3x 5x 5x | import { Stack } from "@mui/material";
import { ClipboardTextIcon } from "@phosphor-icons/react";
import { Controller, useFormContext } from "react-hook-form";
import { GiveInput } from "@shared/GiveInputs/GiveInput";
import { usePayBuilderForm } from "@sections/PayBuilder/provider/PayBuilderFormProvider";
import { useGetFeatureFlagValues } from "FeatureFlags/useGetFeatureFlagValues";
import SectionHeader from "./SectionHeader";
import WithCheckoutTooltip from "./CheckoutTooltip";
import {
MAX_CUSTOM_FIELD_LABEL_LEN,
getRenderableCustomFields,
} from "../customFields.helpers";
/**
* Customer-facing / live-preview render of the checkout custom fields
* (AC011/AC012/AC020/AC022). Same component in the builder preview and the
* public checkout — it reads the config from the shared builder form.
*/
const CustomFieldsPreview = ({
isDisabledFields,
}: {
isDisabledFields?: boolean;
}) => {
const { isPayBuilderCustomFieldsEnabled } = useGetFeatureFlagValues();
const { control } = useFormContext();
const {
methods: leftSidepanelMethods,
parsedValues: { checkoutInputStyles },
} = usePayBuilderForm();
// Subscribe only to the custom-fields subtree — a full-form watch() re-rendered
// the whole preview on every keystroke in any builder field (name, amount, etc.).
const customFields = leftSidepanelMethods.watch("Checkout.customFields");
const fields = getRenderableCustomFields(customFields);
// AC-ROLLOUT + AC003 — nothing renders unless flagged on and configured.
if (!isPayBuilderCustomFieldsEnabled || fields.length === 0) return null;
return (
<Stack spacing="20px" data-testid="checkout-custom-fields">
<SectionHeader
title={customFields?.sectionTitle || "Additional Information"}
icon={<ClipboardTextIcon size={24} />}
/>
<Stack spacing={2}>
{fields.map((field) => (
<Controller
key={field.fieldId}
control={control}
name={`customFields.${field.fieldId}`}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<WithCheckoutTooltip disabled={isDisabledFields}>
<GiveInput
name={`customFields.${field.fieldId}`}
fullWidth
// AC012 — required fields are marked with an asterisk.
label={`${field.label}${field.isRequired ? " *" : ""}`}
value={value ?? ""}
onChange={onChange}
error={!!error}
helperText={error?.message}
disabled={isDisabledFields}
maxLength={MAX_CUSTOM_FIELD_LABEL_LEN}
sx={checkoutInputStyles}
data-testid={`checkout-custom-field-${field.fieldId}`}
/>
</WithCheckoutTooltip>
)}
/>
))}
</Stack>
</Stack>
);
};
export default CustomFieldsPreview;
|