Skip to content

Commit

Permalink
Add PlusMinus icon and allow negative values in MoneyRequestAmountInput
Browse files Browse the repository at this point in the history
  • Loading branch information
pasyukevich committed Jan 30, 2025
1 parent 5ec2edd commit 2e03057
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
7 changes: 7 additions & 0 deletions assets/images/plus-minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ import Phone from '@assets/images/phone.svg';
import Pin from '@assets/images/pin.svg';
import Plane from '@assets/images/plane.svg';
import Play from '@assets/images/play.svg';
import PlusMinus from '@assets/images/plus-minus.svg';
import Plus from '@assets/images/plus.svg';
import Printer from '@assets/images/printer.svg';
import Profile from '@assets/images/profile.svg';
Expand Down Expand Up @@ -422,4 +423,5 @@ export {
GalleryNotFound,
Train,
boltSlash,
PlusMinus,
};
8 changes: 6 additions & 2 deletions src/components/MoneyRequestAmountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ type MoneyRequestAmountInputProps = {

/** The width of inner content */
contentWidth?: number;

/** Allow negative values for the input */
allowNegative?: boolean;
} & Pick<TextInputWithCurrencySymbolProps, 'autoGrowExtraSpace'>;

type Selection = {
Expand Down Expand Up @@ -129,6 +132,7 @@ function MoneyRequestAmountInput(
autoGrow = true,
autoGrowExtraSpace,
contentWidth,
allowNegative = false,
...props
}: MoneyRequestAmountInputProps,
forwardedRef: ForwardedRef<BaseTextInputRef>,
Expand Down Expand Up @@ -167,7 +171,7 @@ function MoneyRequestAmountInput(
: MoneyRequestUtils.replaceCommasWithPeriod(newAmountWithoutSpaces);
// Use a shallow copy of selection to trigger setSelection
// More info: https://github.com/Expensify/App/issues/16385
if (!MoneyRequestUtils.validateAmount(finalAmount, decimals)) {
if (!MoneyRequestUtils.validateAmount(finalAmount, decimals, undefined, true)) {
setSelection((prevSelection) => ({...prevSelection}));
return;
}
Expand Down Expand Up @@ -233,7 +237,7 @@ function MoneyRequestAmountInput(
// Modifies the amount to match the decimals for changed currency.
useEffect(() => {
// If the changed currency supports decimals, we can return
if (MoneyRequestUtils.validateAmount(currentAmount, decimals)) {
if (MoneyRequestUtils.validateAmount(currentAmount, decimals, undefined, true)) {
return;
}

Expand Down
10 changes: 7 additions & 3 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,9 @@ function getDescription(transaction: OnyxInputOrEntry<Transaction>): string {
/**
* Return the amount field from the transaction, return the modifiedAmount if present.
*/
function getAmount(transaction: OnyxInputOrEntry<Transaction>, isFromExpenseReport = false, isFromTrackedExpense = false): number {
function getAmount(transaction: OnyxInputOrEntry<Transaction>, isFromExpenseReport = false, isFromTrackedExpense = false, allowNegative = false): number {
// IOU requests cannot have negative values, but they can be stored as negative values, let's return absolute value
if (!isFromExpenseReport || isFromTrackedExpense) {
if ((!isFromExpenseReport || isFromTrackedExpense) && !allowNegative) {
const amount = transaction?.modifiedAmount ?? 0;
if (amount) {
return Math.abs(amount);
Expand All @@ -505,10 +505,14 @@ function getAmount(transaction: OnyxInputOrEntry<Transaction>, isFromExpenseRepo
// The amounts are stored using an opposite sign and negative values can be set,
// we need to return an opposite sign than is saved in the transaction object
let amount = transaction?.modifiedAmount ?? 0;
if (amount) {
if (amount && !allowNegative) {
return -amount;
}

if (amount) {
return amount;
}

// To avoid -0 being shown, lets only change the sign if the value is other than 0.
amount = transaction?.amount ?? 0;
return amount ? -amount : 0;
Expand Down
34 changes: 31 additions & 3 deletions src/pages/iou/MoneyRequestAmountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {ValueOf} from 'type-fest';
import BigNumberPad from '@components/BigNumberPad';
import Button from '@components/Button';
import FormHelpMessage from '@components/FormHelpMessage';
import * as Expensicons from '@components/Icon/Expensicons';
import MoneyRequestAmountInput from '@components/MoneyRequestAmountInput';
import type {MoneyRequestAmountInputRef} from '@components/MoneyRequestAmountInput';
import ScrollView from '@components/ScrollView';
Expand Down Expand Up @@ -58,7 +59,7 @@ type MoneyRequestAmountFormProps = {
isCurrencyPressable?: boolean;

/** Fired when back button pressed, navigates to currency selection page */
onCurrencyButtonPress?: () => void;
onCurrencyButtonPress: () => void;

/** Fired when submit button pressed, saves the given amount and navigates to the next page */
onSubmitButtonPress: (currentMoney: CurrentMoney) => void;
Expand All @@ -70,7 +71,7 @@ type MoneyRequestAmountFormProps = {
shouldKeepUserInput?: boolean;
};

const isAmountInvalid = (amount: string) => !amount.length || parseFloat(amount) < 0.01;
const isAmountInvalid = (amount: string) => !amount.length || parseFloat(amount) === 0;
const isTaxAmountInvalid = (currentAmount: string, taxAmount: number, isTaxAmountForm: boolean, currency: string) =>
isTaxAmountForm && Number.parseFloat(currentAmount) > convertToFrontendAmountAsInteger(Math.abs(taxAmount), currency);

Expand All @@ -83,7 +84,7 @@ function MoneyRequestAmountForm(
amount = 0,
taxAmount = 0,
currency = CONST.CURRENCY.USD,
isCurrencyPressable = true,
isCurrencyPressable = false,
isEditing = false,
skipConfirmation = false,
iouType = CONST.IOU.TYPE.SUBMIT,
Expand Down Expand Up @@ -161,6 +162,12 @@ function MoneyRequestAmountForm(
[currency],
);

const onFlipAmount = useCallback(() => {
const currentAmount = moneyRequestAmountInput.current?.getAmount() ?? '';
const newAmount = convertToFrontendAmountAsInteger(-Number(currentAmount), currency);
initializeAmount(newAmount);
}, [currency, initializeAmount]);

useEffect(() => {
if (!currency || typeof amount !== 'number') {
return;
Expand Down Expand Up @@ -281,6 +288,7 @@ function MoneyRequestAmountForm(
moneyRequestAmountInputRef={moneyRequestAmountInput}
inputStyle={[styles.iouAmountTextInput]}
containerStyle={[styles.iouAmountTextInputContainer]}
allowNegative
/>
{!!formError && (
<FormHelpMessage
Expand All @@ -290,6 +298,26 @@ function MoneyRequestAmountForm(
/>
)}
</View>
<View>
<View style={[styles.flexRow, styles.justifyContentCenter, styles.mt5, styles.gap2]}>
<Button
allowBubble={!isEditing}
pressOnEnter
shouldShowRightIcon
iconRight={Expensicons.DownArrow}
onPress={onCurrencyButtonPress}
text={currency}
/>
<Button
allowBubble={!isEditing}
pressOnEnter
shouldShowRightIcon
iconRight={Expensicons.PlusMinus}
onPress={onFlipAmount}
text={'Flip'}
/>
</View>
</View>
<View
onMouseDown={(event) => onMouseDown(event, [NUM_PAD_CONTAINER_VIEW_ID, NUM_PAD_VIEW_ID])}
style={[styles.w100, styles.justifyContentEnd, styles.pageWrapper, styles.pt0]}
Expand Down

0 comments on commit 2e03057

Please sign in to comment.