Skip to content

Commit

Permalink
Merge pull request Expensify#34564 from VickyStash/ts-migration/repor…
Browse files Browse the repository at this point in the history
…tActionItemMoneyRequest-component

[TS migration] Migrate 'ReportActionItemMoneyRequest' component to TypeScript
  • Loading branch information
aldo-expensify authored Feb 2, 2024
2 parents e5f7ffc + d3f64c9 commit de633ac
Show file tree
Hide file tree
Showing 16 changed files with 340 additions and 385 deletions.
3 changes: 2 additions & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.DOWNLOAD]: OnyxTypes.Download;
[ONYXKEYS.COLLECTION.POLICY]: OnyxTypes.Policy;
[ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy;
[ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory;
[ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories;
[ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags;
[ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember;
Expand All @@ -479,6 +479,7 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup;
[ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.TRANSACTION_DRAFT]: OnyxTypes.Transaction;
[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolations;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags;
[ONYXKEYS.COLLECTION.SELECTED_TAB]: string;
[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolation[];
Expand Down
5 changes: 2 additions & 3 deletions src/components/DotIndicatorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import useThemeStyles from '@hooks/useThemeStyles';
import fileDownload from '@libs/fileDownload';
import * as Localize from '@libs/Localize';
import CONST from '@src/CONST';
import type {ReceiptError} from '@src/types/onyx/Transaction';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import {PressableWithoutFeedback} from './Pressable';
import Text from './Text';

type ReceiptError = {error?: string; source: string; filename: string};

type DotIndicatorMessageProps = {
/**
* In most cases this should just be errors from onxyData
Expand All @@ -23,7 +22,7 @@ type DotIndicatorMessageProps = {
* timestamp: 'message',
* }
*/
messages: Record<string, Localize.MaybePhraseKey>;
messages: Record<string, Localize.MaybePhraseKey | ReceiptError>;

/** The type of message, 'error' shows a red dot, 'success' shows a green dot */
type: 'error' | 'success';
Expand Down
3 changes: 2 additions & 1 deletion src/components/MessagesRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import type * as Localize from '@libs/Localize';
import CONST from '@src/CONST';
import type {ReceiptError} from '@src/types/onyx/Transaction';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import DotIndicatorMessage from './DotIndicatorMessage';
import Icon from './Icon';
Expand All @@ -15,7 +16,7 @@ import Tooltip from './Tooltip';

type MessagesRowProps = {
/** The messages to display */
messages: Record<string, Localize.MaybePhraseKey>;
messages: Record<string, Localize.MaybePhraseKey | ReceiptError>;

/** The type of message, 'error' shows a red dot, 'success' shows a green dot */
type: 'error' | 'success';
Expand Down
5 changes: 3 additions & 2 deletions src/components/OfflineWithFeedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import mapChildrenFlat from '@libs/mapChildrenFlat';
import shouldRenderOffscreen from '@libs/shouldRenderOffscreen';
import CONST from '@src/CONST';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import type {ReceiptError, ReceiptErrors} from '@src/types/onyx/Transaction';
import type ChildrenProps from '@src/types/utils/ChildrenProps';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import MessagesRow from './MessagesRow';
Expand All @@ -26,7 +27,7 @@ type OfflineWithFeedbackProps = ChildrenProps & {
shouldHideOnDelete?: boolean;

/** The errors to display */
errors?: OnyxCommon.Errors | null;
errors?: OnyxCommon.Errors | ReceiptErrors | null;

/** Whether we should show the error messages */
shouldShowErrorMessages?: boolean;
Expand Down Expand Up @@ -84,7 +85,7 @@ function OfflineWithFeedback({

const hasErrors = !isEmptyObject(errors ?? {});
// Some errors have a null message. This is used to apply opacity only and to avoid showing redundant messages.
const errorMessages = omitBy(errors, (e) => e === null);
const errorMessages = omitBy(errors, (e: string | ReceiptError) => e === null);
const hasErrorMessages = !isEmptyObject(errorMessages);
const isOfflinePendingAction = !!isOffline && !!pendingAction;
const isUpdateOrDeleteError = hasErrors && (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,66 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import networkPropTypes from '@components/networkPropTypes';
import {withNetwork} from '@components/OnyxProvider';
import refPropTypes from '@components/refPropTypes';
import type {OnyxEntry} from 'react-native-onyx';
import RenderHTML from '@components/RenderHTML';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import MoneyRequestPreview from './MoneyRequestPreview';

const propTypes = {
type MoneyRequestActionOnyxProps = {
/** Chat report associated with iouReport */
chatReport: OnyxEntry<OnyxTypes.Report>;

/** IOU report data object */
iouReport: OnyxEntry<OnyxTypes.Report>;

/** Report actions for this report */
reportActions: OnyxEntry<OnyxTypes.ReportActions>;
};

type MoneyRequestActionProps = MoneyRequestActionOnyxProps & {
/** All the data of the action */
action: PropTypes.shape(reportActionPropTypes).isRequired,
action: OnyxTypes.ReportAction;

/** The ID of the associated chatReport */
chatReportID: PropTypes.string.isRequired,
chatReportID: string;

/** The ID of the associated request report */
requestReportID: PropTypes.string.isRequired,
requestReportID: string;

/** The ID of the current report */
reportID: PropTypes.string.isRequired,
reportID: string;

/** Is this IOUACTION the most recent? */
isMostRecentIOUReportAction: PropTypes.bool.isRequired,
isMostRecentIOUReportAction: boolean;

/** Popover context menu anchor, used for showing context menu */
contextMenuAnchor: refPropTypes,
contextMenuAnchor?: ContextMenuAnchor;

/** Callback for updating context menu active state, used for showing context menu */
checkIfContextMenuActive: PropTypes.func,

/* Onyx Props */
/** chatReport associated with iouReport */
chatReport: reportPropTypes,

/** IOU report data object */
iouReport: iouReportPropTypes,

/** Array of report actions for this report */
reportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)),
checkIfContextMenuActive?: () => void;

/** Whether the IOU is hovered so we can modify its style */
isHovered: PropTypes.bool,

network: networkPropTypes.isRequired,
isHovered?: boolean;

/** Whether a message is a whisper */
isWhisper: PropTypes.bool,
isWhisper?: boolean;

/** Styles to be assigned to Container */
// eslint-disable-next-line react/forbid-prop-types
style: PropTypes.arrayOf(PropTypes.object),
};

const defaultProps = {
contextMenuAnchor: undefined,
checkIfContextMenuActive: () => {},
chatReport: {},
iouReport: {},
reportActions: {},
isHovered: false,
style: [],
isWhisper: false,
style?: StyleProp<ViewStyle>;
};

function MoneyRequestAction({
Expand All @@ -87,31 +70,32 @@ function MoneyRequestAction({
reportID,
isMostRecentIOUReportAction,
contextMenuAnchor,
checkIfContextMenuActive,
checkIfContextMenuActive = () => {},
chatReport,
iouReport,
reportActions,
isHovered,
network,
isHovered = false,
style,
isWhisper,
}) {
isWhisper = false,
}: MoneyRequestActionProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const isSplitBillAction = lodashGet(action, 'originalMessage.type', '') === CONST.IOU.REPORT_ACTION_TYPE.SPLIT;
const {isOffline} = useNetwork();

const isSplitBillAction = action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && action.originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT;

const onMoneyRequestPreviewPressed = () => {
if (isSplitBillAction) {
const reportActionID = lodashGet(action, 'reportActionID', '0');
const reportActionID = action.reportActionID ?? '0';
Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(chatReportID, reportActionID));
return;
}

// If the childReportID is not present, we need to create a new thread
const childReportID = lodashGet(action, 'childReportID', 0);
const childReportID = action?.childReportID ?? '0';
if (!childReportID) {
const thread = ReportUtils.buildTransactionThread(action, requestReportID);
const userLogins = PersonalDetailsUtils.getLoginsByAccountIDs(thread.participantAccountIDs);
const userLogins = PersonalDetailsUtils.getLoginsByAccountIDs(thread.participantAccountIDs ?? []);
Report.openReport(thread.reportID, userLogins, thread, action.reportActionID);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(thread.reportID));
return;
Expand All @@ -124,12 +108,12 @@ function MoneyRequestAction({
const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(action);
const isReversedTransaction = ReportActionsUtils.isReversedTransaction(action);
if (
!_.isEmpty(iouReport) &&
!_.isEmpty(reportActions) &&
chatReport.iouReportID &&
!isEmptyObject(iouReport) &&
!isEmptyObject(reportActions) &&
chatReport?.iouReportID &&
isMostRecentIOUReportAction &&
action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD &&
network.isOffline
isOffline
) {
shouldShowPendingConversionMessage = IOUUtils.isIOUReportPendingCurrencyConversion(iouReport);
}
Expand All @@ -147,29 +131,24 @@ function MoneyRequestAction({
checkIfContextMenuActive={checkIfContextMenuActive}
shouldShowPendingConversionMessage={shouldShowPendingConversionMessage}
onPreviewPressed={onMoneyRequestPreviewPressed}
containerStyles={[styles.cursorPointer, isHovered ? styles.reportPreviewBoxHoverBorder : undefined, ...style]}
containerStyles={[styles.cursorPointer, isHovered ? styles.reportPreviewBoxHoverBorder : undefined, style]}
isHovered={isHovered}
isWhisper={isWhisper}
/>
);
}

MoneyRequestAction.propTypes = propTypes;
MoneyRequestAction.defaultProps = defaultProps;
MoneyRequestAction.displayName = 'MoneyRequestAction';

export default compose(
withOnyx({
chatReport: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
},
iouReport: {
key: ({requestReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${requestReportID}`,
},
reportActions: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
canEvict: false,
},
}),
withNetwork(),
)(MoneyRequestAction);
export default withOnyx<MoneyRequestActionProps, MoneyRequestActionOnyxProps>({
chatReport: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
},
iouReport: {
key: ({requestReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${requestReportID}`,
},
reportActions: {
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`,
canEvict: false,
},
})(MoneyRequestAction);
Loading

0 comments on commit de633ac

Please sign in to comment.