Skip to content

Commit

Permalink
Merge pull request #33570 from KrAbhas/ts_mig_MoneyReportHeader
Browse files Browse the repository at this point in the history
[TS migration] Migrate 'MoneyReportHeader.js' component to TypeScript
  • Loading branch information
rlinoz authored Jan 17, 2024
2 parents d4c28a4 + e5a8893 commit 6034b10
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 89 deletions.
5 changes: 3 additions & 2 deletions src/components/HeaderWithBackButton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {PersonalDetails, Policy, Report} from '@src/types/onyx';
import type ChildrenProps from '@src/types/utils/ChildrenProps';
import type IconAsset from '@src/types/utils/IconAsset';

type ThreeDotsMenuItems = {
type ThreeDotsMenuItem = {
/** An icon element displayed on the left side */
icon?: IconAsset;

Expand Down Expand Up @@ -62,7 +62,7 @@ type HeaderWithBackButtonProps = Partial<ChildrenProps> & {
shouldDisableThreeDotsButton?: boolean;

/** List of menu items for more(three dots) menu */
threeDotsMenuItems?: ThreeDotsMenuItems[];
threeDotsMenuItems?: ThreeDotsMenuItem[];

/** The anchor position of the menu */
threeDotsAnchorPosition?: AnchorPosition;
Expand Down Expand Up @@ -110,4 +110,5 @@ type HeaderWithBackButtonProps = Partial<ChildrenProps> & {
shouldEnableDetailPageNavigation?: boolean;
};

export type {ThreeDotsMenuItem};
export default HeaderWithBackButtonProps;
Original file line number Diff line number Diff line change
@@ -1,96 +1,66 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React, {useCallback, useMemo, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import GoogleMeetIcon from '@assets/images/google-meet.svg';
import ZoomIcon from '@assets/images/zoom-icon.svg';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as HeaderUtils from '@libs/HeaderUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import nextStepPropTypes from '@pages/nextStepPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
import * as IOU from '@userActions/IOU';
import * as Link from '@userActions/Link';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type DeepValueOf from '@src/types/utils/DeepValueOf';
import Button from './Button';
import ConfirmModal from './ConfirmModal';
import HeaderWithBackButton from './HeaderWithBackButton';
import * as Expensicons from './Icon/Expensicons';
import MoneyReportHeaderStatusBar from './MoneyReportHeaderStatusBar';
import participantPropTypes from './participantPropTypes';
import SettlementButton from './SettlementButton';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';

const propTypes = {
/** The report currently being looked at */
report: iouReportPropTypes.isRequired,

/** The policy tied to the money request report */
policy: PropTypes.shape({
/** Name of the policy */
name: PropTypes.string,

/** Type of the policy */
type: PropTypes.string,

/** The role of the current user in the policy */
role: PropTypes.string,

/** Whether Scheduled Submit is turned on for this policy */
isHarvestingEnabled: PropTypes.bool,
}),
type PaymentType = DeepValueOf<typeof CONST.IOU.PAYMENT_TYPE>;

type MoneyReportHeaderOnyxProps = {
/** The chat report this report is linked to */
chatReport: reportPropTypes,
chatReport: OnyxEntry<OnyxTypes.Report>;

/** The next step for the report */
nextStep: nextStepPropTypes,

/** Personal details so we can get the ones for the report participants */
personalDetails: PropTypes.objectOf(participantPropTypes).isRequired,
nextStep: OnyxEntry<OnyxTypes.ReportNextStep>;

/** Session info for the currently logged in user. */
session: PropTypes.shape({
/** Currently logged in user email */
email: PropTypes.string,
}),

...windowDimensionsPropTypes,
session: OnyxEntry<OnyxTypes.Session>;
};

const defaultProps = {
chatReport: {},
nextStep: {},
session: {
email: null,
},
policy: {
isHarvestingEnabled: false,
},
type MoneyReportHeaderProps = MoneyReportHeaderOnyxProps & {
/** The report currently being looked at */
report: OnyxTypes.Report;

/** The policy tied to the money request report */
policy: OnyxTypes.Policy;

/** Personal details so we can get the ones for the report participants */
personalDetails: OnyxTypes.PersonalDetailsList;
};

function MoneyReportHeader({session, personalDetails, policy, chatReport, nextStep, report: moneyRequestReport, isSmallScreenWidth}) {
function MoneyReportHeader({session, personalDetails, policy, chatReport, nextStep, report: moneyRequestReport}: MoneyReportHeaderProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {windowWidth} = useWindowDimensions();
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();
const reimbursableTotal = ReportUtils.getMoneyRequestReimbursableTotal(moneyRequestReport);
const isApproved = ReportUtils.isReportApproved(moneyRequestReport);
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const policyType = lodashGet(policy, 'type');
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && lodashGet(policy, 'role') === CONST.POLICY.ROLE.ADMIN;
const policyType = policy?.type;
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && policy?.role === CONST.POLICY.ROLE.ADMIN;
const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicy(moneyRequestReport);
const isManager = ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID;
const isManager = ReportUtils.isMoneyRequestReport(moneyRequestReport) && session?.accountID === moneyRequestReport.managerID;
const isPayer = isPaidGroupPolicy
? // In a group policy, the admin approver can pay the report directly by skipping the approval step
isPolicyAdmin && (isApproved || isManager)
Expand All @@ -99,6 +69,7 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false);

const cancelPayment = useCallback(() => {
// @ts-expect-error TODO: Remove this once IOU (https://github.com/Expensify/App/issues/24926) is migrated to TypeScript.
IOU.cancelPayment(moneyRequestReport, chatReport);
setIsConfirmModalVisible(false);
}, [moneyRequestReport, chatReport]);
Expand All @@ -116,16 +87,16 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton;
const shouldShowSubmitButton = isDraft && reimbursableTotal !== 0;
const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE;
const shouldShowNextStep = isFromPaidPolicy && nextStep && !_.isEmpty(nextStep.message);
const shouldShowNextStep = isFromPaidPolicy && !!nextStep?.message?.length;
const shouldShowAnyButton = shouldShowSettlementButton || shouldShowApproveButton || shouldShowSubmitButton || shouldShowNextStep;
const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport);
const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableTotal, moneyRequestReport.currency);
const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && isSmallScreenWidth);

// The submit button should be success green colour only if the user is submitter and the policy does not have Scheduled Submit turned on
const isWaitingForSubmissionFromCurrentUser = useMemo(
() => chatReport.isOwnPolicyExpenseChat && !policy.isHarvestingEnabled,
[chatReport.isOwnPolicyExpenseChat, policy.isHarvestingEnabled],
() => chatReport?.isOwnPolicyExpenseChat && !policy.isHarvestingEnabled,
[chatReport?.isOwnPolicyExpenseChat, policy.isHarvestingEnabled],
);

const threeDotsMenuItems = [HeaderUtils.getPinMenuItem(moneyRequestReport)];
Expand Down Expand Up @@ -173,11 +144,13 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
{shouldShowSettlementButton && !isSmallScreenWidth && (
<View style={styles.pv2}>
<SettlementButton
// @ts-expect-error TODO: Remove this once SettlementButton (https://github.com/Expensify/App/issues/25100) is migrated to TypeScript.
currency={moneyRequestReport.currency}
policyID={moneyRequestReport.policyID}
chatReportID={chatReport.reportID}
chatReportID={chatReport?.reportID}
iouReport={moneyRequestReport}
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
// @ts-expect-error TODO: Remove this once IOU (https://github.com/Expensify/App/issues/24926) is migrated to TypeScript.
onPress={(paymentType: PaymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
Expand All @@ -203,11 +176,13 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
{shouldShowSettlementButton && isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2]}>
<SettlementButton
// @ts-expect-error TODO: Remove this once SettlementButton (https://github.com/Expensify/App/issues/25100) is migrated to TypeScript.
currency={moneyRequestReport.currency}
policyID={moneyRequestReport.policyID}
chatReportID={moneyRequestReport.chatReportID}
iouReport={moneyRequestReport}
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
// @ts-expect-error TODO: Remove this once IOU (https://github.com/Expensify/App/issues/24926) is migrated to TypeScript.
onPress={(paymentType: PaymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
addBankAccountRoute={bankAccountRoute}
shouldHidePaymentOptions={!shouldShowPayButton}
Expand Down Expand Up @@ -248,20 +223,15 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt
}

MoneyReportHeader.displayName = 'MoneyReportHeader';
MoneyReportHeader.propTypes = propTypes;
MoneyReportHeader.defaultProps = defaultProps;

export default compose(
withWindowDimensions,
withOnyx({
chatReport: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`,
},
nextStep: {
key: ({report}) => `${ONYXKEYS.COLLECTION.NEXT_STEP}${report.reportID}`,
},
session: {
key: ONYXKEYS.SESSION,
},
}),
)(MoneyReportHeader);
export default withOnyx<MoneyReportHeaderProps, MoneyReportHeaderOnyxProps>({
chatReport: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`,
},
nextStep: {
key: ({report}) => `${ONYXKEYS.COLLECTION.NEXT_STEP}${report.reportID}`,
},
session: {
key: ONYXKEYS.SESSION,
},
})(MoneyReportHeader);
15 changes: 2 additions & 13 deletions src/libs/HeaderUtils.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import type {OnyxEntry} from 'react-native-onyx';
import type {ThreeDotsMenuItem} from '@components/HeaderWithBackButton/types';
import * as Expensicons from '@components/Icon/Expensicons';
import type OnyxReport from '@src/types/onyx/Report';
import type IconAsset from '@src/types/utils/IconAsset';
import * as Report from './actions/Report';
import * as Session from './actions/Session';
import * as Localize from './Localize';

type MenuItem = {
icon: string | IconAsset;
text: string;
onSelected: () => void;
};

function getPinMenuItem(report: OnyxEntry<OnyxReport>): MenuItem | undefined {
if (!report) {
return;
}

function getPinMenuItem(report: OnyxReport): ThreeDotsMenuItem {
const isPinned = !!report.isPinned;

return {
Expand Down

0 comments on commit 6034b10

Please sign in to comment.