Skip to content

Commit edaf6c7

Browse files
authored
Merge pull request Expensify#81626 from ikevin127/ikevin127-splitsLogicRework
2 parents 7ccc11c + f4b4caf commit edaf6c7

File tree

9 files changed

+618
-35
lines changed

9 files changed

+618
-35
lines changed

src/components/MoneyRequestAmountInput.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ type MoneyRequestAmountInputProps = {
9696
/** Whether to allow flipping amount */
9797
allowFlippingAmount?: boolean;
9898

99+
/** Whether to allow direct negative input (for split amounts where value is already negative) */
100+
allowNegativeInput?: boolean;
101+
99102
/** The testID of the input. Used to locate this view in end-to-end tests. */
100103
testID?: string;
101104

@@ -162,6 +165,7 @@ function MoneyRequestAmountInput({
162165
shouldWrapInputInContainer = true,
163166
isNegative = false,
164167
allowFlippingAmount = false,
168+
allowNegativeInput = false,
165169
toggleNegative,
166170
clearNegative,
167171
ref,
@@ -257,6 +261,7 @@ function MoneyRequestAmountInput({
257261
autoGrowExtraSpace={autoGrowExtraSpace}
258262
submitBehavior={submitBehavior}
259263
allowFlippingAmount={allowFlippingAmount}
264+
allowNegativeInput={allowNegativeInput}
260265
toggleNegative={toggleNegative}
261266
clearNegative={clearNegative}
262267
onFocus={props.onFocus}

src/components/NumberWithSymbolForm.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ type NumberWithSymbolFormProps = {
7979
/** Whether to allow flipping amount */
8080
allowFlippingAmount?: boolean;
8181

82+
/** Whether to allow direct negative input (for split amounts where value is already negative) */
83+
allowNegativeInput?: boolean;
84+
8285
/** Whether the input is disabled or not */
8386
disabled?: boolean;
8487

@@ -144,6 +147,7 @@ function NumberWithSymbolForm({
144147
shouldWrapInputInContainer = true,
145148
isNegative = false,
146149
allowFlippingAmount = false,
150+
allowNegativeInput = false,
147151
toggleNegative,
148152
clearNegative,
149153
ref,
@@ -218,11 +222,13 @@ function NumberWithSymbolForm({
218222
const newNumberWithoutSpaces = stripSpacesFromAmount(newNumber);
219223
const rawFinalNumber = newNumberWithoutSpaces.includes('.') ? stripCommaFromAmount(newNumberWithoutSpaces) : replaceCommasWithPeriod(newNumberWithoutSpaces);
220224

221-
const finalNumber = handleNegativeAmountFlipping(rawFinalNumber, allowFlippingAmount, toggleNegative);
225+
// When allowNegativeInput is true, keep negative sign as-is (for split amounts)
226+
// When allowFlippingAmount is true, strip the negative sign and call toggleNegative
227+
const finalNumber = allowNegativeInput ? rawFinalNumber : handleNegativeAmountFlipping(rawFinalNumber, allowFlippingAmount, toggleNegative);
222228

223229
// Use a shallow copy of selection to trigger setSelection
224230
// More info: https://github.com/Expensify/App/issues/16385
225-
if (!validateAmount(finalNumber, decimals, maxLength)) {
231+
if (!validateAmount(finalNumber, decimals, maxLength, allowNegativeInput)) {
226232
setSelection((prevSelection) => ({...prevSelection}));
227233
return;
228234
}
@@ -242,7 +248,7 @@ function NumberWithSymbolForm({
242248
});
243249
onInputChange?.(strippedNumber);
244250
},
245-
[decimals, maxLength, onInputChange, allowFlippingAmount, toggleNegative],
251+
[decimals, maxLength, onInputChange, allowFlippingAmount, toggleNegative, allowNegativeInput],
246252
);
247253

248254
/**
@@ -253,11 +259,14 @@ function NumberWithSymbolForm({
253259
// Remove spaces from the new number because Safari on iOS adds spaces when pasting a copied number
254260
// More info: https://github.com/Expensify/App/issues/16974
255261
const newNumberWithoutSpaces = stripSpacesFromAmount(text);
256-
const replacedCommasNumber = handleNegativeAmountFlipping(replaceCommasWithPeriod(newNumberWithoutSpaces), allowFlippingAmount, toggleNegative);
262+
// When allowNegativeInput is true, keep negative sign as-is
263+
const replacedCommasNumber = allowNegativeInput
264+
? replaceCommasWithPeriod(newNumberWithoutSpaces)
265+
: handleNegativeAmountFlipping(replaceCommasWithPeriod(newNumberWithoutSpaces), allowFlippingAmount, toggleNegative);
257266

258-
const withLeadingZero = addLeadingZero(replacedCommasNumber);
267+
const withLeadingZero = addLeadingZero(replacedCommasNumber, allowNegativeInput);
259268

260-
if (!validateAmount(withLeadingZero, decimals, maxLength)) {
269+
if (!validateAmount(withLeadingZero, decimals, maxLength, allowNegativeInput)) {
261270
setSelection((prevSelection) => ({...prevSelection}));
262271
return;
263272
}
@@ -280,7 +289,7 @@ function NumberWithSymbolForm({
280289
// Modifies the number to match changed decimals.
281290
useEffect(() => {
282291
// If the number supports decimals, we can return
283-
if (validateAmount(currentNumber, decimals, maxLength, allowFlippingAmount)) {
292+
if (validateAmount(currentNumber, decimals, maxLength, allowNegativeInput || allowFlippingAmount)) {
284293
return;
285294
}
286295

@@ -305,14 +314,14 @@ function NumberWithSymbolForm({
305314
if (currentNumber.length > 0) {
306315
const selectionStart = selection.start === selection.end ? selection.start - 1 : selection.start;
307316
const newNumber = `${currentNumber.substring(0, selectionStart)}${currentNumber.substring(selection.end)}`;
308-
setNewNumber(addLeadingZero(newNumber));
317+
setNewNumber(addLeadingZero(newNumber, allowNegativeInput));
309318
}
310319
return;
311320
}
312-
const newNumber = addLeadingZero(`${currentNumber.substring(0, selection.start)}${key}${currentNumber.substring(selection.end)}`);
321+
const newNumber = addLeadingZero(`${currentNumber.substring(0, selection.start)}${key}${currentNumber.substring(selection.end)}`, allowNegativeInput);
313322
setNewNumber(newNumber);
314323
},
315-
[currentNumber, selection.start, selection.end, shouldUpdateSelection, setNewNumber],
324+
[currentNumber, selection.start, selection.end, shouldUpdateSelection, setNewNumber, allowNegativeInput],
316325
);
317326

318327
/**

src/components/SelectionList/ListItem/SplitListItem.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,17 @@ function SplitListItem<TItem extends ListItem>({
4343

4444
const formattedOriginalAmount = convertToDisplayStringWithoutCurrency(splitItem.originalAmount, splitItem.currency);
4545

46-
const onSplitExpenseValueChange = useCallback((value: string) => splitItem.onSplitExpenseValueChange(splitItem.transactionID, Number(value), splitItem.mode), [splitItem]);
46+
const onSplitExpenseValueChange = useCallback(
47+
(value: string) => {
48+
const numericValue = Number(value);
49+
// Skip update if value is just "-" or produces NaN (intermediate input state)
50+
if (Number.isNaN(numericValue)) {
51+
return;
52+
}
53+
splitItem.onSplitExpenseValueChange(splitItem.transactionID, numericValue, splitItem.mode);
54+
},
55+
[splitItem],
56+
);
4757

4858
const inputRef = useRef<BaseTextInputRef | null>(null);
4959

src/components/SelectionList/ListItem/SplitListItem/SplitAmountInput.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ function SplitAmountInput({splitItem, formattedOriginalAmount, contentWidth, onS
5454
shouldWrapInputInContainer={false}
5555
onFocus={focusHandler}
5656
onBlur={onInputBlur}
57+
allowNegativeInput
5758
/>
5859
);
5960
}

0 commit comments

Comments
 (0)