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 'MoneyReportHeader.js' component to TypeScript #33570

Merged
merged 29 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
674e24d
rename file
KrAbhas Dec 25, 2023
883eaae
add types, remove compose, refactor HOC
KrAbhas Dec 25, 2023
b5f1a17
refactor types for intersection
KrAbhas Dec 25, 2023
89ed621
improve optional and nullish chaining
KrAbhas Dec 25, 2023
73d0421
merge main to branch
KrAbhas Dec 28, 2023
35ff0a9
resolve conflict from main
KrAbhas Dec 28, 2023
90f7963
add ts-expect-error with issue nos
KrAbhas Dec 28, 2023
fcf8873
remove underscore
KrAbhas Dec 28, 2023
b873919
write prettier changes
KrAbhas Dec 28, 2023
7938b48
remove nullish coalescing to replace ||
KrAbhas Dec 28, 2023
d267f1b
improve ts-expect-error comments
KrAbhas Dec 28, 2023
007def1
define and use PaymentType
KrAbhas Dec 28, 2023
3fac3e9
keep Session and import all types as OnyxTypes
KrAbhas Dec 28, 2023
904b910
Merge branch 'main' into ts_mig_MoneyReportHeader
KrAbhas Dec 29, 2023
a836394
Merge branch 'main' into ts_mig_MoneyReportHeader
KrAbhas Jan 3, 2024
d0604ff
resolve ts lint error from latest master pull
KrAbhas Jan 3, 2024
eadb576
match types between MenuItem and ThreedotMenuItem
KrAbhas Jan 5, 2024
f19a692
match array type for threedotmenuitem
KrAbhas Jan 5, 2024
c135fdc
merge main to branch and resolve HeaderUtils conflict
KrAbhas Jan 5, 2024
95f02ab
resolve lint error for type import
KrAbhas Jan 5, 2024
9d10263
resolve lint error for top-level type import
KrAbhas Jan 5, 2024
cb57d63
resolve lint error: OnyxEntry as type
KrAbhas Jan 5, 2024
2024316
merge main to branch and resolve conflict
KrAbhas Jan 6, 2024
b2e045e
remove MenuItem in favor of ThreeDotsMenuItem
KrAbhas Jan 9, 2024
11dbb77
Merge branch 'main' into ts_mig_MoneyReportHeader
KrAbhas Jan 9, 2024
11b97e8
run prettier
KrAbhas Jan 10, 2024
97e9c35
Merge branch 'main' into ts_mig_MoneyReportHeader
KrAbhas Jan 10, 2024
5bae0f9
merge main to branch and resolve conflicts
KrAbhas Jan 16, 2024
e5a8893
Merge branch 'main' into ts_mig_MoneyReportHeader
KrAbhas Jan 17, 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
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
Loading