diff --git a/src/FormBuilder/resources/js/form-builder/src/blocks/fields/amount/inspector/index.tsx b/src/FormBuilder/resources/js/form-builder/src/blocks/fields/amount/inspector/index.tsx index a2f7b68e47..9c54e745c6 100644 --- a/src/FormBuilder/resources/js/form-builder/src/blocks/fields/amount/inspector/index.tsx +++ b/src/FormBuilder/resources/js/form-builder/src/blocks/fields/amount/inspector/index.tsx @@ -121,32 +121,51 @@ const Inspector = ({attributes, setAttributes}) => { const [donationLevels, setDonationLevels] = useState( levels.map((level) => ({ + id: String(Math.floor(Math.random() * 1000000)), label: formatCurrencyAmount(level.toString()), value: level.toString(), checked: defaultLevel === level, })) ); - const handleLevelsChange = (options: OptionProps[]) => { - if (options.length > 1 && options[options.length - 1].value === '') { - const values = options.filter((option) => Number(option.value) > 0).map((option) => Number(option.value)); - options[options.length - 1].value = String(2 * Math.max(...values)); - } else if (options.length === 1 && options[0].value === '') { - options[0].value = '10'; + const handleLevelAdded = () => { + const newLevelValue = levels.length ? String(Math.max(...levels) * 2) : '10'; + const newLevel = { + id: String(Math.floor(Math.random() * 1000000)), + label: formatCurrencyAmount(newLevelValue), + value: newLevelValue, + checked: false, + }; + + // If there are no levels, set the new level as the default. + if (!levels.length) { + newLevel.checked = true; + setAttributes({defaultLevel: Number(newLevelValue)}); } - const checkedLevel = options.filter((option) => option.checked); + setDonationLevels([...donationLevels, newLevel]); + setAttributes({levels: [...levels, Number(newLevelValue)]}); + }; - if (!!checkedLevel && checkedLevel.length === 1) { - setAttributes({defaultLevel: Number(checkedLevel[0].value)}); - } else if (options.length > 0) { - options[0].checked = true; + const handleLevelRemoved = (level: OptionProps, index: number) => { + const newLevels = levels.filter((_, i) => i !== index); + const newDonationLevels = donationLevels.filter((_, i) => i !== index); + + if (level.checked && newDonationLevels.length > 0) { + newDonationLevels[0].checked = true; + setAttributes({defaultLevel: Number(newDonationLevels[0].value)}); } - setDonationLevels(options); + setDonationLevels(newDonationLevels); + setAttributes({levels: newLevels}); + }; + + const handleLevelsChange = (options: OptionProps[]) => { + const checkedLevel = options.filter((option) => option.checked); const newLevels = options.filter((option) => option.value).map((option) => Number(option.value)); - setAttributes({levels: newLevels}); + setDonationLevels(options); + setAttributes({levels: newLevels, defaultLevel: Number(checkedLevel[0].value)}); }; const getDefaultBillingPeriodOptions = useCallback( @@ -234,6 +253,8 @@ const Inspector = ({attributes, setAttributes}) => { multiple={false} options={donationLevels} setOptions={handleLevelsChange} + onAddOption={handleLevelAdded} + onRemoveOption={handleLevelRemoved} defaultControlsTooltip={__('Default Level', 'give')} /> diff --git a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/OptionsList.tsx b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/OptionsList.tsx index a1608af1ed..231a0cae1d 100644 --- a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/OptionsList.tsx +++ b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/OptionsList.tsx @@ -11,8 +11,14 @@ export default function OptionsList({ selectable, setOptions, defaultControlsTooltip, + onRemoveOption, }: OptionsListProps) { const handleRemoveOption = (index: number) => (): void => { + if (onRemoveOption) { + onRemoveOption(options[index], index); + return; + } + options[index].label = ''; options[index].value = ''; setOptions(options.filter((option, optionIndex) => optionIndex !== index)); @@ -38,6 +44,11 @@ export default function OptionsList({ const handleUpdateOptionChecked = (index: number, multiple: boolean) => (checked: boolean): void => { + // bail if we're trying to uncheck a single option + if (!multiple && options[index].checked) { + return; + } + const updatedOptions = [...options]; if (!multiple) { updatedOptions.forEach((option, optionIndex) => { @@ -66,28 +77,28 @@ export default function OptionsList({ {(provided) => (
- {options.map((option: OptionProps, index: number) => ( - - {(provided) => ( - - )} - - ))} + {options.map((option: OptionProps, index: number) => { + const key = option.id ? option.id : index; + return ( + + {(provided) => ( + + )} + + ); + })} {provided.placeholder}
)} diff --git a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/index.tsx b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/index.tsx index 59cd923912..6d5fafc2b5 100644 --- a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/index.tsx +++ b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/index.tsx @@ -6,10 +6,24 @@ import OptionsList from './OptionsList'; import {OptionsPanelProps} from './types'; -export default function Options({currency, multiple, selectable = true, options, setOptions, defaultControlsTooltip}: OptionsPanelProps) { +export default function Options({ + currency, + multiple, + selectable = true, + options, + setOptions, + defaultControlsTooltip, + onAddOption, + onRemoveOption, +}: OptionsPanelProps) { const [showValues, setShowValues] = useState(false); const handleAddOption = (): void => { + if (onAddOption) { + onAddOption(); + return; + } + setOptions([...options, {label: '', value: '', checked: false}]); }; @@ -28,15 +42,14 @@ export default function Options({currency, multiple, selectable = true, options, diff --git a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/types.ts b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/types.ts index 4f50794d53..a13e1d4237 100644 --- a/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/types.ts +++ b/src/FormBuilder/resources/js/form-builder/src/components/OptionsPanel/types.ts @@ -3,8 +3,10 @@ export interface OptionsPanelProps { multiple: boolean; selectable?: boolean; options: OptionProps[]; - setOptions: (options: OptionProps[]) => void; defaultControlsTooltip?: string; + setOptions: (options: OptionProps[]) => void; + onRemoveOption?: (option: OptionProps, index: number) => void; + onAddOption?: () => void; } export interface OptionsListProps { @@ -13,8 +15,9 @@ export interface OptionsListProps { showValues: boolean; multiple: boolean; selectable: boolean; - setOptions: (options: OptionProps[]) => void; defaultControlsTooltip?: string; + setOptions: (options: OptionProps[]) => void; + onRemoveOption?: (option: OptionProps, index: number) => void; } export interface OptionsItemProps { @@ -32,6 +35,7 @@ export interface OptionsItemProps { } export interface OptionProps { + id?: string; label: string; value: string; checked: boolean;