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 | 90x 90x 376x 41x 335x 335x 26x 384x 87x 99x 36x 161x 1x 36x 36x 36x 36x 1x 2x 1x 3x 1x 1x 1x 1x 36x 1x 1x 2x 1x 2x 1x 36x 15x 155x 153x 36x 2x 1x 1x 36x | import { ExportField, RadioMultiselect } from "../giveExportTypes";
import { Stack } from "@mui/material";
import GiveText from "@shared/Text/GiveText";
import { useAppTheme } from "@theme/v2/Provider";
import ExportRadioComponent from "./ExportRadioComponent";
import ExportSelectComponent from "./ExportSelectComponent";
import { HFGiveInput } from "@shared/HFInputs/HFGiveInput/HFGiveInput";
import GiveButton from "@shared/Button/GiveButton";
import ExportRadioMultiselect from "./ExportRadioMultiselect";
import GiveLink from "@shared/Link/GiveLink";
import { useFormContext } from "react-hook-form";
import { useMemo } from "react";
function ExportModalContent({ fieldRawData }: { fieldRawData: ExportField[] }) {
const theme = useAppTheme();
return (
<Stack gap="37px" px="20px" py="37px">
{fieldRawData?.map((field) => {
if (field.fieldType === "button") {
return (
<GiveButton
key={field.label}
label={field.label}
onClick={field.onClick}
size="large"
variant="filled"
color="light"
fullWidth
sx={{ marginTop: "-17px" }}
//between other sections the gap should 37px, but to follow the right logic for the export view,
//the button should be treated its 'own' section, but here the gap should be smaller
/>
);
}
const { secondaryField, label, fieldType } = field;
return (
<Stack key={field.label}>
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
>
<GiveText fontWeight={400} fontSize="16px">
{label}
</GiveText>
{fieldType === "radio-multiselect" && (
<MultiSelectButton field={field} />
)}
</Stack>
<Stack
width="100%"
p="20px"
mt="20px"
borderRadius="20px"
bgcolor={theme.palette.surface?.primary}
gap="20px"
>
{field.controlLabel ? (
<Stack gap="8px">
<GiveText variant="bodyS">{field.controlLabel}</GiveText>
<ComponentSwitcher field={field} />
</Stack>
) : (
<ComponentSwitcher field={field} />
)}
{secondaryField && (
<Stack gap="8px">
<GiveText variant="bodyS">{secondaryField.label}</GiveText>
<ComponentSwitcher field={secondaryField} />
</Stack>
)}
</Stack>
</Stack>
);
})}
</Stack>
);
}
export default ExportModalContent;
const ComponentSwitcher = ({ field }: { field: ExportField }) => {
switch (field.fieldType) {
case "input":
return <HFGiveInput name={field.fieldName} />;
case "radio":
return <ExportRadioComponent field={field} />;
case "radio-multiselect":
return <ExportRadioMultiselect field={field} />;
case "select":
return <ExportSelectComponent field={field} />;
default:
return null;
}
};
function MultiSelectButton({ field }: { field: RadioMultiselect }) {
const { setValue, watch } = useFormContext();
const { fieldName, options } = field;
const selectedValues: string[] = watch(fieldName) || [];
const deselectSpecificSection = () => {
const currentSelectedValues = watch(fieldName) || [];
const optionsValues = options.map((option) => option.value);
const deselectedValues = currentSelectedValues.filter(
(value: string) => !optionsValues.includes(value),
);
const hadSelectionInSection = optionsValues.some((opt) =>
currentSelectedValues.includes(opt),
);
// Only keep one option in this section when deselecting would leave the entire selection empty
// (no other section has any selection). Otherwise just apply the deselect.
const valueToSet =
hadSelectionInSection &&
options.length > 0 &&
deselectedValues.length === 0
? [options[options.length - 1].value]
: deselectedValues;
setValue(fieldName, valueToSet, { shouldValidate: true });
};
const selectAllSpecificSection = () => {
const currentSelectedValues: string[] = watch(fieldName) || [];
const optionsValues: string[] = options.map(
(option) => option.value as string,
);
const unselectedOptions = optionsValues.filter(
(value: string) => !currentSelectedValues.includes(value),
);
setValue(fieldName, [...currentSelectedValues, ...unselectedOptions]);
};
const allSelected = useMemo(() => {
const optionsValues: string[] = options.map(
(option) => option.value as string,
);
return optionsValues.every((value) => selectedValues.includes(value));
}, [selectedValues, options]);
const handleMultiSelect = () => {
if (allSelected) {
deselectSpecificSection();
} else {
selectAllSpecificSection();
}
};
return (
<GiveLink component="button" color="secondary" onClick={handleMultiSelect}>
{allSelected ? "Deselect All" : "Select All"}
</GiveLink>
);
}
|