Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: resolve strange behaviors in amount levels #7018

Merged
merged 11 commits into from
Nov 9, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,45 @@ 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,
};

const checkedLevel = options.filter((option) => option.checked);
setDonationLevels([...donationLevels, newLevel]);
setAttributes({levels: [...levels, Number(newLevelValue)]});
JasonTheAdams marked this conversation as resolved.
Show resolved Hide resolved
};

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 +247,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 @@ -10,8 +10,14 @@ export default function OptionsList({
multiple,
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 @@ -37,6 +43,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 @@ -65,27 +76,27 @@ 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,
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}
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,23 @@ import OptionsList from './OptionsList';

import {OptionsPanelProps} from './types';

export default function Options({currency, multiple, options, setOptions, defaultControlsTooltip}: OptionsPanelProps) {
export default function Options({
currency,
multiple,
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,14 +41,13 @@ export default function Options({currency, multiple, options, setOptions, defaul
<BaseControl id={'give'}>
<OptionsHeader handleAddOption={handleAddOption} />
<OptionsList
{...{
currency,
options,
showValues,
multiple,
setOptions,
defaultControlsTooltip,
}}
currency={currency}
options={options}
JasonTheAdams marked this conversation as resolved.
Show resolved Hide resolved
showValues={showValues}
multiple={multiple}
setOptions={setOptions}
defaultControlsTooltip={defaultControlsTooltip}
onRemoveOption={onRemoveOption}
/>
</BaseControl>
</PanelRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ export interface OptionsPanelProps {
currency: boolean;
multiple: boolean;
options: OptionProps[];
setOptions: (options: OptionProps[]) => void;
defaultControlsTooltip?: string;
setOptions: (options: OptionProps[]) => void;
onRemoveOption?: (option: OptionProps, index: number) => void;
onAddOption?: () => void;
}

export interface OptionsListProps {
currency: boolean;
options: OptionProps[];
showValues: boolean;
multiple: boolean;
setOptions: (options: OptionProps[]) => void;
defaultControlsTooltip?: string;
setOptions: (options: OptionProps[]) => void;
onRemoveOption?: (option: OptionProps, index: number) => void;
}

export interface OptionsItemProps {
Expand All @@ -29,6 +32,7 @@ export interface OptionsItemProps {
}

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