Skip to content

Commit

Permalink
Merge pull request Expensify#39059 from software-mansion-labs/@szymcz…
Browse files Browse the repository at this point in the history
…ak/TaxRequestPage+TaxAmmountPage

[TS migration] Migrate IOURequestStepTaxRatePage and IOURequestStepTaxAmountPage to TypeScript
  • Loading branch information
rlinoz authored Apr 4, 2024
2 parents 38f2d7c + 38e9558 commit 0b2f55f
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 180 deletions.
3 changes: 1 addition & 2 deletions src/components/TaxPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {Policy} from '@src/types/onyx';
import SelectionList from './SelectionList';
import RadioListItem from './SelectionList/RadioListItem';
import type {ListItem} from './SelectionList/types';

type TaxPickerOnyxProps = {
/** The policy which the user has access to and which the report is tied to */
Expand All @@ -33,7 +32,7 @@ type TaxPickerProps = TaxPickerOnyxProps & {
insets?: EdgeInsets;

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

function TaxPicker({selectedTaxRate = '', policy, insets, onSubmit}: TaxPickerProps) {
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ type MoneyRequestNavigatorParamList = {
backTo: Routes;
};
[SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: {
iouType: string;
iouType: ValueOf<typeof CONST.IOU.TYPE>;
transactionID: string;
reportID: string;
backTo: Routes;
Expand All @@ -395,7 +395,7 @@ type MoneyRequestNavigatorParamList = {
backTo: Routes;
};
[SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: {
iouType: string;
iouType: ValueOf<typeof CONST.IOU.TYPE>;
transactionID: string;
reportID: string;
backTo: Routes;
Expand Down
22 changes: 19 additions & 3 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ type CategorySection = CategorySectionBase & {
data: Option[];
};

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

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

type CategoryTreeSection = CategorySectionBase & {
data: OptionTree[];
};
Expand Down Expand Up @@ -1240,7 +1256,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.modifiedName,
Expand All @@ -1254,7 +1270,7 @@ function getTaxRatesOptions(taxRates: Array<Partial<TaxRate>>): Option[] {
/**
* Builds the section list for tax rates
*/
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] {
function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): TaxSection[] {
const policyRatesSections = [];

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

export type {MemberForList, CategorySection, GetOptions, OptionList, SearchOption, PayeePersonalDetails, Category};
export type {MemberForList, CategorySection, GetOptions, OptionList, SearchOption, 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 @@ -35,6 +35,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 @@ -54,7 +55,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 @@ -5112,7 +5113,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,84 +1,69 @@
import {useFocusEffect} from '@react-navigation/native';
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useRef} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import taxPropTypes from '@components/taxPropTypes';
import transactionPropTypes from '@components/transactionPropTypes';
import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
import useLocalize from '@hooks/useLocalize';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as TransactionUtils from '@libs/TransactionUtils';
import type {CurrentMoney} from '@pages/iou/steps/MoneyRequestAmountForm';
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 SCREENS from '@src/SCREENS';
import type {Policy, Transaction} from '@src/types/onyx';
import StepScreenWrapper from './StepScreenWrapper';
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,
}),
type IOURequestStepTaxAmountPageOnyxProps = {
policy: OnyxEntry<Policy>;
};

const defaultProps = {
report: {},
policy: {},
transaction: {},
};
type IOURequestStepTaxAmountPageProps = IOURequestStepTaxAmountPageOnyxProps &
WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT> & {
transaction: OnyxEntry<Transaction>;
};

const getTaxAmount = (transaction, defaultTaxValue) => {
const percentage = (transaction.taxRate ? transaction.taxRate.data.value : defaultTaxValue) || '';
return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transaction.amount)));
};
function getTaxAmount(transaction: OnyxEntry<Transaction>, defaultTaxValue: string | undefined): number | undefined {
if (!transaction?.amount) {
return;
}
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 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) {
originalCurrency.current = transaction.currency;
IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, transaction?.currency);
}
return () => {
if (isSaveButtonPressed.current) {
if (isSaveButtonPressed.current || !originalCurrency.current) {
return;
}
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, originalCurrency.current, true);
Expand All @@ -88,7 +73,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 @@ -111,12 +96,13 @@ function IOURequestStepTaxAmountPage({
);
};

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

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 @@ -126,7 +112,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(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID));
Expand All @@ -148,9 +134,9 @@ function IOURequestStepTaxAmountPage({
>
<MoneyRequestAmountForm
isEditing={isEditing}
currency={currency}
amount={transaction.taxAmount}
taxAmount={getTaxAmount(transaction, taxRates.defaultValue)}
currency={transaction?.currency}
amount={transaction?.taxAmount}
taxAmount={getTaxAmount(transaction, taxRates?.defaultValue)}
ref={(e) => (textInput.current = e)}
onCurrencyButtonPress={navigateToCurrencySelectionPage}
onSubmitButtonPress={updateTaxAmount}
Expand All @@ -159,16 +145,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;
Loading

0 comments on commit 0b2f55f

Please sign in to comment.