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

[TS migration] Migrate IOURequestStepTaxRatePage and IOURequestStepTaxAmountPage to TypeScript #39059

3 changes: 1 addition & 2 deletions src/components/TaxPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import CONST from '@src/CONST';
import type {TaxRatesWithDefault} from '@src/types/onyx';
import SelectionList from './SelectionList';
import RadioListItem from './SelectionList/RadioListItem';
import type {ListItem} from './SelectionList/types';

type TaxPickerProps = {
/** Collection of tax rates attached to a policy */
Expand All @@ -24,7 +23,7 @@ type TaxPickerProps = {
insets?: EdgeInsets;

/** Callback to fire when a tax is pressed */
onSubmit: (tax: ListItem) => void;
onSubmit: (tax: OptionsListUtils.TaxRatesOption) => void;
};

function TaxPicker({selectedTaxRate = '', taxRates, insets, onSubmit}: TaxPickerProps) {
Expand Down
22 changes: 19 additions & 3 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ type CategorySection = CategorySectionBase & {
data: Option[];
};

type TaxRatesOption = {
text?: string;
code?: string;
searchText?: string;
tooltipText?: string;
isDisabled?: boolean;
data: Partial<TaxRate>;
};

type TaxSection = {
title: string | undefined;
shouldShow: boolean;
indexOffset: number;
data: TaxRatesOption[];
};

type CategoryTreeSection = CategorySectionBase & {
data: OptionTree[];
};
Expand Down Expand Up @@ -1250,7 +1266,7 @@ function sortTaxRates(taxRates: TaxRates): TaxRate[] {
/**
* Builds the options for taxRates
*/
function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): Option[] {
function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): TaxRatesOption[] {
return taxRates.map((taxRate) => ({
text: taxRate.modifiedName,
keyForList: taxRate.code,
Expand All @@ -1264,7 +1280,7 @@ function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): Option[] {
/**
* Builds the section list for tax rates
*/
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string, defaultTaxKey?: string): CategorySection[] {
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string, defaultTaxKey?: string): TaxSection[] {
const policyRatesSections = [];

const taxes = transformedTaxRates(taxRates, defaultTaxKey);
Expand Down Expand Up @@ -2110,4 +2126,4 @@ export {
getTaxRatesSection,
};

export type {MemberForList, CategorySection, GetOptions, PayeePersonalDetails, Category};
export type {MemberForList, CategorySection, GetOptions, PayeePersonalDetails, Category, TaxRatesOption};
5 changes: 3 additions & 2 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import * as Localize from '@libs/Localize';
import Navigation from '@libs/Navigation/Navigation';
import * as NextStepUtils from '@libs/NextStepUtils';
import type {TaxRatesOption} from '@libs/OptionsListUtils';
import Permissions from '@libs/Permissions';
import * as PhoneNumber from '@libs/PhoneNumber';
import * as PolicyUtils from '@libs/PolicyUtils';
Expand All @@ -56,7 +57,7 @@ import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type ReportAction from '@src/types/onyx/ReportAction';
import type {OnyxData} from '@src/types/onyx/Request';
import type {Comment, Receipt, ReceiptSource, TaxRate, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction';
import type {Comment, Receipt, ReceiptSource, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import * as CachedPDFPaths from './CachedPDFPaths';
Expand Down Expand Up @@ -4970,7 +4971,7 @@ function setMoneyRequestCurrency(currency: string) {
Onyx.merge(ONYXKEYS.IOU, {currency});
}

function setMoneyRequestTaxRate(transactionID: string, taxRate: TaxRate) {
function setMoneyRequestTaxRate(transactionID: string, taxRate: TaxRatesOption) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxRate});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,90 +1,73 @@
import {useFocusEffect} from '@react-navigation/native';
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useRef} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import taxPropTypes from '@components/taxPropTypes';
import transactionPropTypes from '@components/transactionPropTypes';
import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as TransactionUtils from '@libs/TransactionUtils';
import MoneyRequestAmountForm from '@pages/iou/steps/MoneyRequestAmountForm';
import reportPropTypes from '@pages/reportPropTypes';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes';
import type {Policy, Transaction} from '@src/types/onyx';
import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
import withWritableReportOrNotFound from './withWritableReportOrNotFound';

const propTypes = {
/** Navigation route context info provided by react navigation */
route: IOURequestStepRoutePropTypes.isRequired,

/* Onyx Props */
/** The report that the transaction belongs to */
report: reportPropTypes,

/** The transaction object being modified in Onyx */
transaction: transactionPropTypes,

/* Onyx Props */
/** The policy of the report */
policy: PropTypes.shape({
/** Collection of tax rates attached to a policy */
taxRates: taxPropTypes,
}),
};

const defaultProps = {
report: {},
transaction: {},
policy: {},
type IOURequestStepTaxAmountPageOnyxProps = {
policy: OnyxEntry<Policy>;
};

const getTaxAmount = (transaction, defaultTaxValue) => {
const percentage = (transaction.taxRate ? transaction.taxRate.data.value : defaultTaxValue) || '';
return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transaction.amount)));
type IOURequestStepTaxAmountPageProps = {
transaction: OnyxEntry<Transaction>;
} & IOURequestStepTaxAmountPageOnyxProps &
WithWritableReportOrNotFoundProps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
type IOURequestStepTaxAmountPageProps = {
transaction: OnyxEntry<Transaction>;
} & IOURequestStepTaxAmountPageOnyxProps &
WithWritableReportOrNotFoundProps;
type IOURequestStepTaxAmountPageProps = IOURequestStepTaxAmountPageOnyxProps & WithWritableReportOrNotFoundProps & {
transaction: OnyxEntry<Transaction>;
};


const getTaxAmount = (transaction: OnyxEntry<Transaction>, defaultTaxValue: string | undefined) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: transform to named function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add a return type here

if (!transaction?.amount) {
return;
}
Comment on lines +33 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This incomplete condition lead to this bug here #41434

const percentage = (transaction?.taxRate ? transaction?.taxRate?.data?.value : defaultTaxValue) ?? '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const percentage = (transaction?.taxRate ? transaction?.taxRate?.data?.value : defaultTaxValue) ?? '';
const percentage = (transaction?.taxRate ? transaction?.taxRate?.data?.value : defaultTaxValue) ?? '';

return CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(percentage, transaction?.amount));
};

function IOURequestStepTaxAmountPage({
route: {
params: {iouType, reportID, transactionID, backTo},
},
transaction,
transaction: {currency},
report,
policy,
}) {
}: IOURequestStepTaxAmountPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const textInput = useRef(null);
const textInput = useRef<BaseTextInputRef | null>();
const isEditing = Navigation.getActiveRoute().includes('taxAmount');

const focusTimeoutRef = useRef(null);
const focusTimeoutRef = useRef<NodeJS.Timeout>();

const isSaveButtonPressed = useRef(false);
const originalCurrency = useRef(null);
const taxRates = lodashGet(policy, 'taxRates', {});
const originalCurrency = useRef<string>();
const taxRates = policy?.taxRates;

useEffect(() => {
if (transaction.originalCurrency) {
if (transaction?.originalCurrency) {
originalCurrency.current = transaction.originalCurrency;
} else {
originalCurrency.current = currency;
IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, currency);
} else if (transaction?.currency) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure this change won't create regressions

originalCurrency.current = transaction.currency;
IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, transaction?.currency);
}
return () => {
if (isSaveButtonPressed.current) {
if (isSaveButtonPressed.current || !originalCurrency.current) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

return;
}
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, originalCurrency.current, true);
Expand All @@ -94,7 +77,7 @@ function IOURequestStepTaxAmountPage({

useFocusEffect(
useCallback(() => {
focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION);
focusTimeoutRef.current = setTimeout(() => textInput.current?.focus(), CONST.ANIMATED_TRANSITION);
return () => {
if (!focusTimeoutRef.current) {
return;
Expand All @@ -115,12 +98,13 @@ function IOURequestStepTaxAmountPage({
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CURRENCY.getRoute(iouType, transactionID, reportID, backTo ? 'confirm' : '', Navigation.getActiveRouteWithoutParams()));
};

const updateTaxAmount = (currentAmount) => {
const updateTaxAmount = (currentAmount: {amount: string}) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract this inline type to a separate line

isSaveButtonPressed.current = true;
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount.amount));
IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits);

IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency || CONST.CURRENCY.USD, true);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, transaction?.currency || CONST.CURRENCY.USD, true);

if (backTo) {
Navigation.goBack(backTo);
Expand All @@ -130,7 +114,7 @@ function IOURequestStepTaxAmountPage({
// If a reportID exists in the report object, it's because the user started this flow from using the + button in the composer
// inside a report. In this case, the participants can be automatically assigned from the report and the user can skip the participants step and go straight
// to the confirm step.
if (report.reportID) {
if (report?.reportID) {
// TODO: Is this really needed at all?
IOU.setMoneyRequestParticipantsFromReport(transactionID, report);
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(iouType, transactionID, reportID));
Expand All @@ -145,10 +129,9 @@ function IOURequestStepTaxAmountPage({
const content = (
<MoneyRequestAmountForm
isEditing={isEditing}
currency={currency}
amount={transaction.taxAmount}
taxAmount={getTaxAmount(transaction, taxRates.defaultValue)}
transaction={transaction}
currency={transaction?.currency}
amount={transaction?.taxAmount}
taxAmount={getTaxAmount(transaction, taxRates?.defaultValue)}
ref={(e) => (textInput.current = e)}
onCurrencyButtonPress={navigateToCurrencySelectionPage}
onSubmitButtonPress={updateTaxAmount}
Expand Down Expand Up @@ -176,16 +159,17 @@ function IOURequestStepTaxAmountPage({
);
}

IOURequestStepTaxAmountPage.propTypes = propTypes;
IOURequestStepTaxAmountPage.defaultProps = defaultProps;
IOURequestStepTaxAmountPage.displayName = 'IOURequestStepTaxAmountPage';

export default compose(
withWritableReportOrNotFound,
withFullTransactionOrNotFound,
withOnyx({
policy: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`,
},
}),
)(IOURequestStepTaxAmountPage);
const IOURequestStepTaxAmountPageWithOnyx = withOnyx<IOURequestStepTaxAmountPageProps, IOURequestStepTaxAmountPageOnyxProps>({
policy: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`,
},
})(IOURequestStepTaxAmountPage);

// eslint-disable-next-line rulesdir/no-negated-variables
const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPageWithOnyx);
// eslint-disable-next-line rulesdir/no-negated-variables
const IOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxAmountPageWithWritableReportOrNotFound);

export default IOURequestStepTaxAmountPageWithFullTransactionOrNotFound;
109 changes: 0 additions & 109 deletions src/pages/iou/request/step/IOURequestStepTaxRatePage.js

This file was deleted.

Loading
Loading