Skip to content

Commit

Permalink
Fix: resolve strange behaviors in amount levels (#7018)
Browse files Browse the repository at this point in the history
Co-authored-by: Jon Waldstein <[email protected]>
  • Loading branch information
JasonTheAdams and jonwaldstein authored Nov 9, 2023
1 parent 9fd8de1 commit 1f3fd2c
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,51 @@ const Inspector = ({attributes, setAttributes}) => {

const [donationLevels, setDonationLevels] = useState<OptionProps[]>(
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(
Expand Down Expand Up @@ -234,6 +253,8 @@ const Inspector = ({attributes, setAttributes}) => {
multiple={false}
options={donationLevels}
setOptions={handleLevelsChange}
onAddOption={handleLevelAdded}
onRemoveOption={handleLevelRemoved}
defaultControlsTooltip={__('Default Level', 'give')}
/>
</PanelBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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) => {
Expand Down Expand Up @@ -66,28 +77,28 @@ export default function OptionsList({
<Droppable droppableId="options">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{options.map((option: OptionProps, index: number) => (
<Draggable key={index} draggableId={`option-${index}`} index={index}>
{(provided) => (
<OptionsItem
{...{
currency,
provided,
option,
index,
showValues,
multiple,
selectable,
defaultTooltip: defaultControlsTooltip,
handleRemoveOption: handleRemoveOption(index),
handleUpdateOptionLabel: handleUpdateOptionLabel(index),
handleUpdateOptionValue: handleUpdateOptionValue(index),
handleUpdateOptionChecked: handleUpdateOptionChecked(index, multiple),
}}
/>
)}
</Draggable>
))}
{options.map((option: OptionProps, index: number) => {
const key = option.id ? option.id : index;
return (
<Draggable key={key} draggableId={`option-${key}`} index={index}>
{(provided) => (
<OptionsItem
currency={currency}
provided={provided}
option={option}
showValues={showValues}
multiple={multiple}
selectable={selectable}
defaultTooltip={defaultControlsTooltip}
handleRemoveOption={handleRemoveOption(index)}
handleUpdateOptionLabel={handleUpdateOptionLabel(index)}
handleUpdateOptionValue={handleUpdateOptionValue(index)}
handleUpdateOptionChecked={handleUpdateOptionChecked(index, multiple)}
/>
)}
</Draggable>
);
})}
{provided.placeholder}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>(false);

const handleAddOption = (): void => {
if (onAddOption) {
onAddOption();
return;
}

setOptions([...options, {label: '', value: '', checked: false}]);
};

Expand All @@ -28,15 +42,14 @@ export default function Options({currency, multiple, selectable = true, options,
<BaseControl id={'give'}>
<OptionsHeader handleAddOption={handleAddOption} />
<OptionsList
{...{
currency,
options,
showValues,
multiple,
selectable,
setOptions,
defaultControlsTooltip,
}}
currency={currency}
options={options}
showValues={showValues}
multiple={multiple}
selectable={selectable}
setOptions={setOptions}
defaultControlsTooltip={defaultControlsTooltip}
onRemoveOption={onRemoveOption}
/>
</BaseControl>
</PanelRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -32,6 +35,7 @@ export interface OptionsItemProps {
}

export interface OptionProps {
id?: string;
label: string;
value: string;
checked: boolean;
Expand Down

0 comments on commit 1f3fd2c

Please sign in to comment.