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 'IOU' page to TypeScript #35253

Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
be682af
refactor(typescript): migrate iou page
pac-guerreiro Jan 26, 2024
546e43a
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Jan 26, 2024
cf5f1cd
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Feb 5, 2024
4ff2192
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Feb 7, 2024
3c16bee
chore(typescript): migrate IOU related components
pac-guerreiro Feb 7, 2024
96c467f
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Feb 9, 2024
b25f22f
chore: apply pull request suggestions
pac-guerreiro Feb 9, 2024
9eebd1b
fix: typing issues
pac-guerreiro Feb 9, 2024
9ee97a0
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Feb 15, 2024
264dbbc
chore: apply pull request feedback
pac-guerreiro Feb 16, 2024
45a08a8
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Feb 22, 2024
9ab98e0
chore: remove unused typescript expect error
pac-guerreiro Feb 22, 2024
b2ab8c6
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 11, 2024
0845c3e
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 13, 2024
54a4ac9
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 13, 2024
6f8fcb7
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 14, 2024
fad75a9
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 15, 2024
dfdb162
fix(typescript): type mismatches
pac-guerreiro Mar 15, 2024
c6b427b
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 18, 2024
a0655e1
refactor(typescript): apply pull request feedback
pac-guerreiro Mar 18, 2024
a1794d0
refactor(typescript): apply pull request feedback
pac-guerreiro Mar 18, 2024
521f2ba
fix: add missing dependency on useEffect
pac-guerreiro Mar 18, 2024
3b41c2e
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 20, 2024
c67fad2
refactor(typescript): apply pull request feedback
pac-guerreiro Mar 20, 2024
e554a10
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 22, 2024
6431baf
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 26, 2024
38be36d
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 26, 2024
2f643b2
refactor(typescript): apply pull request suggestions
pac-guerreiro Mar 26, 2024
ad93e44
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 28, 2024
49b4982
Merge branch 'main' into pac-guerreiro/refactor/migrate-iou-page-to-t…
pac-guerreiro Mar 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ type OnyxCollectionValuesMapping = {
[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolations;
[ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags;
[ONYXKEYS.COLLECTION.SELECTED_TAB]: string;
[ONYXKEYS.COLLECTION.SELECTED_TAB]: ValueOf<typeof CONST.TAB_REQUEST>;
pac-guerreiro marked this conversation as resolved.
Show resolved Hide resolved
[ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string;
[ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep;
[ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER]: OnyxTypes.PolicyJoinMember;
Expand Down
20 changes: 12 additions & 8 deletions src/components/DistanceRequest/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,19 @@ type DistanceRequestProps = DistanceRequestOnyxProps & {
onSubmit: (waypoints?: WaypointCollection) => void;

/** React Navigation route */
route: RouteProp<{
route: RouteProp<
/** Params from the route */
params: {
/** The type of IOU report, i.e. bill, request, send */
iouType: string;
/** The report ID of the IOU */
reportID: string;
};
}>;
Record<
string,
| {
/** The type of IOU report, i.e. bill, request, send */
iouType: string;
/** The report ID of the IOU */
reportID: string;
}
| undefined
>
>;
pac-guerreiro marked this conversation as resolved.
Show resolved Hide resolved
};

function DistanceRequest({transactionID = '', report, transaction, route, isEditingRequest = false, isEditingNewRequest = false, onSubmit}: DistanceRequestProps) {
Expand Down
18 changes: 11 additions & 7 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {Participant} from '@src/types/onyx/IOU';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type {ReceiptSource} from '@src/types/onyx/Transaction';
import ButtonWithDropdownMenu from './ButtonWithDropdownMenu';
import type {DropdownOption} from './ButtonWithDropdownMenu/types';
import ConfirmedRoute from './ConfirmedRoute';
Expand Down Expand Up @@ -67,7 +68,7 @@ type MoneyRequestConfirmationListOnyxProps = {
};
type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & {
/** Callback to inform parent modal of success */
onConfirm?: (selectedParticipants: Participant[]) => void;
onConfirm?: (selectedParticipants: Array<Participant | ReportUtils.OptionData>) => void;

/** Callback to parent modal to send money */
onSendMoney?: (paymentMethod: IouType | PaymentMethodType | undefined) => void;
Expand Down Expand Up @@ -109,10 +110,10 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps &
onToggleBillable?: (isOn: boolean) => void;

/** Selected participants from MoneyRequestModal with login / accountID */
selectedParticipants: Participant[];
selectedParticipants: Array<Participant | ReportUtils.OptionData>;

/** Payee of the money request with login */
payeePersonalDetails?: OnyxTypes.PersonalDetails;
payeePersonalDetails?: OnyxEntry<OnyxTypes.PersonalDetails>;

/** Can the participants be modified or not */
canModifyParticipants?: boolean;
Expand All @@ -130,7 +131,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps &
reportID?: string;

/** File path of the receipt */
receiptPath?: string;
receiptPath?: ReceiptSource;

/** File name of the receipt */
receiptFilename?: string;
Expand Down Expand Up @@ -322,7 +323,7 @@ function MoneyRequestConfirmationList({
* Returns the participants with amount
*/
const getParticipantsWithAmount = useCallback(
(participantsList: Participant[]): Participant[] => {
(participantsList: Array<Participant | ReportUtils.OptionData>): Array<Participant | ReportUtils.OptionData> => {
const calculatedIouAmount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? '');
return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(
participantsList,
Expand Down Expand Up @@ -358,7 +359,10 @@ function MoneyRequestConfirmationList({
];
}, [isSplitBill, isTypeRequest, iouType, iouAmount, receiptPath, formattedAmount, isDistanceRequestWithPendingRoute, translate]);

const selectedParticipants: Participant[] = useMemo(() => selectedParticipantsProp.filter((participant) => participant.selected), [selectedParticipantsProp]);
const selectedParticipants: Array<Participant | ReportUtils.OptionData> = useMemo(
() => selectedParticipantsProp.filter((participant) => participant.selected),
[selectedParticipantsProp],
);
const payeePersonalDetails = useMemo(() => payeePersonalDetailsProp ?? currentUserPersonalDetails, [payeePersonalDetailsProp, currentUserPersonalDetails]);
const canModifyParticipants = !isReadOnly && canModifyParticipantsProp && hasMultipleParticipants;
const shouldDisablePaidBySection = canModifyParticipants;
Expand Down Expand Up @@ -424,7 +428,7 @@ function MoneyRequestConfirmationList({
canModifyParticipants,
]);

const selectedOptions: Array<Participant | OptionsListUtils.PayeePersonalDetails> = useMemo(() => {
const selectedOptions: Array<Participant | ReportUtils.OptionData | OptionsListUtils.PayeePersonalDetails> = useMemo(() => {
if (!hasMultipleParticipants) {
return [];
}
Expand Down
3 changes: 2 additions & 1 deletion src/libs/MoneyRequestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';

Expand Down Expand Up @@ -78,7 +79,7 @@ function replaceAllDigits(text: string, convertFn: (char: string) => string): st
/**
* Check if distance request or not
*/
function isDistanceRequest(iouType: ValueOf<typeof CONST.IOU.TYPE>, selectedTab: ValueOf<typeof CONST.TAB_REQUEST>): boolean {
function isDistanceRequest(iouType: ValueOf<typeof CONST.IOU.TYPE>, selectedTab: OnyxEntry<ValueOf<typeof CONST.TAB_REQUEST>>): boolean {
return iouType === CONST.IOU.TYPE.REQUEST && selectedTab === CONST.TAB_REQUEST.DISTANCE;
}

Expand Down
10 changes: 6 additions & 4 deletions src/libs/Navigation/OnyxTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import type {EventMapCore, NavigationState, ScreenListeners} from '@react-naviga
import React from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import Tab from '@userActions/Tab';
import type CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type ChildrenProps from '@src/types/utils/ChildrenProps';
import {defaultScreenOptions} from './OnyxTabNavigatorConfig';

type OnyxTabNavigatorOnyxProps = {
selectedTab: OnyxEntry<string>;
selectedTab: OnyxEntry<ValueOf<typeof CONST.TAB_REQUEST>>;
};

type OnyxTabNavigatorProps = OnyxTabNavigatorOnyxProps &
Expand All @@ -19,7 +21,7 @@ type OnyxTabNavigatorProps = OnyxTabNavigatorOnyxProps &
id: string;

/** Name of the selected tab */
selectedTab?: string;
selectedTab?: ValueOf<typeof CONST.TAB_REQUEST>;

/** A function triggered when a tab has been selected */
onTabSelected?: (newIouType: string) => void;
Expand All @@ -32,7 +34,7 @@ export const TopTab = createMaterialTopTabNavigator();

// This takes all the same props as MaterialTopTabsNavigator: https://reactnavigation.org/docs/material-top-tab-navigator/#props,
// except ID is now required, and it gets a `selectedTab` from Onyx
function OnyxTabNavigator({id, selectedTab = '', children, onTabSelected = () => {}, screenListeners, ...rest}: OnyxTabNavigatorProps) {
function OnyxTabNavigator({id, selectedTab, children, onTabSelected = () => {}, screenListeners, ...rest}: OnyxTabNavigatorProps) {
return (
<TopTab.Navigator
/* eslint-disable-next-line react/jsx-props-no-spreading */
Expand All @@ -47,7 +49,7 @@ function OnyxTabNavigator({id, selectedTab = '', children, onTabSelected = () =>
const state = event.data.state;
const index = state.index;
const routeNames = state.routeNames;
Tab.setSelectedTab(id, routeNames[index]);
Tab.setSelectedTab(id, routeNames[index] as ValueOf<typeof CONST.TAB_REQUEST>);
onTabSelected(routeNames[index]);
},
...(screenListeners ?? {}),
Expand Down
7 changes: 6 additions & 1 deletion src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ type RoomInviteNavigatorParamList = {

type MoneyRequestNavigatorParamList = {
[SCREENS.MONEY_REQUEST.ROOT]: undefined;
[SCREENS.MONEY_REQUEST.AMOUNT]: undefined;
[SCREENS.MONEY_REQUEST.AMOUNT]: {
iouType: ValueOf<typeof CONST.IOU.TYPE>;
reportID: string;
currency: string;
};
[SCREENS.MONEY_REQUEST.PARTICIPANTS]: {
iouType: string;
reportID: string;
Expand Down Expand Up @@ -405,6 +409,7 @@ type EnablePaymentsNavigatorParamList = {

type SplitDetailsNavigatorParamList = {
[SCREENS.SPLIT_DETAILS.ROOT]: {
reportID: string;
reportActionID: string;
};
[SCREENS.SPLIT_DETAILS.EDIT_REQUEST]: {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1798,7 +1798,7 @@ function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: Person
/**
* Build the IOUConfirmationOptions for showing participants
*/
function getIOUConfirmationOptionsFromParticipants(participants: Participant[], amountText: string): Participant[] {
function getIOUConfirmationOptionsFromParticipants(participants: Array<Participant | ReportUtils.OptionData>, amountText: string): Array<Participant | ReportUtils.OptionData> {
return participants.map((participant) => ({
...participant,
descriptiveText: amountText,
Expand Down
4 changes: 2 additions & 2 deletions src/libs/ReceiptUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ReceiptSVG from '@assets/images/receipt-svg.png';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type {Transaction} from '@src/types/onyx';
import type {ReceiptError} from '@src/types/onyx/Transaction';
import type {ReceiptError, ReceiptSource} from '@src/types/onyx/Transaction';
import * as FileUtils from './fileDownload/FileUtils';
import * as TransactionUtils from './TransactionUtils';

Expand All @@ -33,7 +33,7 @@ type FileNameAndExtension = {
* @param receiptPath
* @param receiptFileName
*/
function getThumbnailAndImageURIs(transaction: OnyxEntry<Transaction>, receiptPath: string | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI {
function getThumbnailAndImageURIs(transaction: OnyxEntry<Transaction>, receiptPath: ReceiptSource | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI {
if (TransactionUtils.isFetchingWaypointsFromServer(transaction)) {
return {thumbnail: null, image: ReceiptGeneric, isLocalFile: true};
}
Expand Down
2 changes: 1 addition & 1 deletion src/libs/TransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function hasEReceipt(transaction: Transaction | undefined | null): boolean {
return !!transaction?.hasEReceipt;
}

function hasReceipt(transaction: Transaction | undefined | null): boolean {
function hasReceipt(transaction: OnyxEntry<Transaction> | undefined): boolean {
return !!transaction?.receipt?.state || hasEReceipt(transaction);
}

Expand Down
29 changes: 15 additions & 14 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2373,9 +2373,9 @@ function startSplitBill(
* @param sessionAccountID - accountID of the current user
* @param sessionEmail - email of the current user
*/
function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportAction, updatedTransaction: OnyxTypes.Transaction, sessionAccountID: number, sessionEmail: string) {
function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportAction, updatedTransaction: OnyxEntry<OnyxTypes.Transaction>, sessionAccountID: number, sessionEmail: string) {
const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(sessionEmail);
const {transactionID} = updatedTransaction;
const transactionID = updatedTransaction?.transactionID ?? '';
const unmodifiedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];

// Save optimistic updated transaction and action
Expand Down Expand Up @@ -2436,8 +2436,9 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
},
];

const splitParticipants: Split[] = updatedTransaction.comment.splits ?? [];
const {modifiedAmount: amount, modifiedCurrency: currency} = updatedTransaction;
const splitParticipants: Split[] = updatedTransaction?.comment.splits ?? [];
const amount = updatedTransaction?.modifiedAmount;
const currency = updatedTransaction?.modifiedCurrency;

// Exclude the current user when calculating the split amount, `calculateAmount` takes it into account
const splitAmount = IOUUtils.calculateAmount(splitParticipants.length - 1, amount ?? 0, currency ?? '', false);
Expand Down Expand Up @@ -2494,17 +2495,17 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
isPolicyExpenseChat ? -splitAmount : splitAmount,
currency ?? '',
oneOnOneIOUReport?.reportID ?? '',
updatedTransaction.comment.comment,
updatedTransaction.modifiedCreated,
updatedTransaction?.comment.comment,
updatedTransaction?.modifiedCreated,
CONST.IOU.TYPE.SPLIT,
transactionID,
updatedTransaction.modifiedMerchant,
{...updatedTransaction.receipt, state: CONST.IOU.RECEIPT_STATE.OPEN},
updatedTransaction.filename,
updatedTransaction?.modifiedMerchant,
{...updatedTransaction?.receipt, state: CONST.IOU.RECEIPT_STATE.OPEN},
updatedTransaction?.filename,
undefined,
updatedTransaction.category,
updatedTransaction.tag,
updatedTransaction.billable,
updatedTransaction?.category,
updatedTransaction?.tag,
updatedTransaction?.billable,
);

const oneOnOneCreatedActionForChat = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmailForIOUSplit);
Expand All @@ -2513,7 +2514,7 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
splitAmount,
currency ?? '',
updatedTransaction.comment.comment ?? '',
updatedTransaction?.comment.comment ?? '',
currentUserEmailForIOUSplit,
[participant],
oneOnOneTransaction.transactionID,
Expand Down Expand Up @@ -4159,7 +4160,7 @@ function setUpDistanceTransaction() {
}

/** Navigates to the next IOU page based on where the IOU request was started */
function navigateToNextPage(iou: OnyxEntry<OnyxTypes.IOU>, iouType: string, report?: OnyxTypes.Report, path = '') {
function navigateToNextPage(iou: OnyxEntry<OnyxTypes.IOU>, iouType: string, report?: OnyxEntry<OnyxTypes.Report>, path = '') {
const moneyRequestID = `${iouType}${report?.reportID ?? ''}`;
const shouldReset = iou?.id !== moneyRequestID && !!report?.reportID;

Expand Down
4 changes: 3 additions & 1 deletion src/libs/actions/Tab.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

/**
* Sets the selected tab for a given tab ID
*/
function setSelectedTab(id: string, index: string) {
function setSelectedTab(id: string, index: ValueOf<typeof CONST.TAB_REQUEST>) {
Onyx.merge(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`, index);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import withWindowDimensions from '@components/withWindowDimensions';
import type {WindowDimensionsProps} from '@components/withWindowDimensions/types';
import compose from '@libs/compose';
import getComponentDisplayName from '@libs/getComponentDisplayName';
import type {FlagCommentNavigatorParamList} from '@libs/Navigation/types';
import type {FlagCommentNavigatorParamList, SplitDetailsNavigatorParamList} from '@libs/Navigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import * as Report from '@userActions/Report';
Expand Down Expand Up @@ -44,7 +44,9 @@ type OnyxProps = {
isLoadingReportData: OnyxEntry<boolean>;
};

type WithReportAndReportActionOrNotFoundProps = OnyxProps & WindowDimensionsProps & StackScreenProps<FlagCommentNavigatorParamList, typeof SCREENS.FLAG_COMMENT_ROOT>;
type WithReportAndReportActionOrNotFoundProps = OnyxProps &
WindowDimensionsProps &
StackScreenProps<FlagCommentNavigatorParamList & SplitDetailsNavigatorParamList, typeof SCREENS.FLAG_COMMENT_ROOT | typeof SCREENS.SPLIT_DETAILS.ROOT>;

export default function <TProps extends WithReportAndReportActionOrNotFoundProps, TRef>(
WrappedComponent: ComponentType<TProps & RefAttributes<TRef>>,
Expand Down
Loading
Loading