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

[Details Revamp] Allow Editing Report Title from Details Page #44671

Merged
5 changes: 5 additions & 0 deletions src/components/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ type MenuItemBaseProps = {
/** Text to display under the main item */
furtherDetails?: string;

/** Render custom content under the main item */
furtherDetailsComponent?: ReactElement;

/** The function that should be called when this component is LongPressed or right-clicked. */
onSecondaryInteraction?: (event: GestureResponderEvent | MouseEvent) => void;

Expand Down Expand Up @@ -338,6 +341,7 @@ function MenuItem(
iconRight = Expensicons.ArrowRight,
furtherDetailsIcon,
furtherDetails,
furtherDetailsComponent,
description,
helperText,
helperTextStyle,
Expand Down Expand Up @@ -702,6 +706,7 @@ function MenuItem(
</Text>
</View>
)}
{!!furtherDetailsComponent && <View style={[styles.flexRow, styles.alignItemsCenter]}>{furtherDetailsComponent}</View>}
{titleComponent}
</View>
</View>
Expand Down
7 changes: 5 additions & 2 deletions src/components/ReportActionItem/MoneyReportView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ function MoneyReportView({report, policy}: MoneyReportViewProps) {
<>
{ReportUtils.reportFieldsEnabled(report) &&
sortedPolicyReportFields.map((reportField) => {
const isTitleField = ReportUtils.isReportFieldOfTypeTitle(reportField);
const fieldValue = isTitleField ? report.reportName : reportField.value ?? reportField.defaultValue;
if (ReportUtils.isReportFieldOfTypeTitle(reportField)) {
return null;
}

const fieldValue = reportField.value ?? reportField.defaultValue;
const isFieldDisabled = ReportUtils.isReportFieldDisabled(report, reportField, policy);
const fieldKey = ReportUtils.getReportFieldKey(reportField.fieldID);

Expand Down
7 changes: 7 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6888,6 +6888,12 @@ function isNonAdminOrOwnerOfPolicyExpenseChat(report: OnyxInputOrEntry<Report>,
return isPolicyExpenseChat(report) && !(PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPolicyOwner(policy, currentUserAccountID ?? -1) || isReportOwner(report));
}

function isAdminOwnerApproverOrReportOwner(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>): boolean {
const isApprover = isMoneyRequestReport(report) && report?.managerID !== null && currentUserPersonalDetails?.accountID === report?.managerID;

return PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPolicyOwner(policy, currentUserAccountID ?? -1) || isReportOwner(report) || isApprover;
}

/**
* Whether the user can join a report
*/
Expand Down Expand Up @@ -7347,6 +7353,7 @@ export {
isCurrentUserInvoiceReceiver,
isDraftReport,
changeMoneyRequestHoldStatus,
isAdminOwnerApproverOrReportOwner,
createDraftWorkspaceAndNavigateToConfirmationScreen,
isChatUsedForOnboarding,
getChatUsedForOnboarding,
Expand Down
46 changes: 45 additions & 1 deletion src/pages/ReportDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {StackScreenProps} from '@react-navigation/stack';
import {Str} from 'expensify-common';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -537,6 +538,47 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
</OfflineWithFeedback>
);

const titleField = useMemo<OnyxTypes.PolicyReportField | undefined>((): OnyxTypes.PolicyReportField | undefined => {
const fields = ReportUtils.getAvailableReportFields(report, Object.values(policy?.fieldList ?? {}));
return fields.find((reportField) => ReportUtils.isReportFieldOfTypeTitle(reportField));
}, [report, policy?.fieldList]);
const fieldKey = ReportUtils.getReportFieldKey(titleField?.fieldID ?? '-1');
const isFieldDisabled = ReportUtils.isReportFieldDisabled(report, titleField, policy);

const shouldShowTitleField = caseID !== CASES.MONEY_REQUEST && !isFieldDisabled && ReportUtils.isAdminOwnerApproverOrReportOwner(report, policy);

const nameSectionFurtherDetailsContent = (
<ParentNavigationSubtitle
parentNavigationSubtitleData={parentNavigationSubtitleData}
parentReportID={report?.parentReportID}
parentReportActionID={report?.parentReportActionID}
pressableStyles={[styles.mt1, styles.mw100]}
/>
);

const nameSectionTitleField = titleField && (
<OfflineWithFeedback
pendingAction={report.pendingFields?.[fieldKey]}
errors={report.errorFields?.[fieldKey]}
errorRowStyles={styles.ph5}
key={`menuItem-${fieldKey}`}
onClose={() => Report.clearReportFieldErrors(report.reportID, titleField)}
>
<View style={[styles.flex1]}>
<MenuItemWithTopDescription
shouldShowRightIcon={!isFieldDisabled}
interactive={!isFieldDisabled}
title={reportName}
titleStyle={styles.newKansasLarge}
shouldCheckActionAllowedOnPress={false}
description={Str.UCFirst(titleField.name)}
onPress={() => Navigation.navigate(ROUTES.EDIT_REPORT_FIELD_REQUEST.getRoute(report.reportID, report.policyID ?? '-1', titleField.fieldID ?? '-1'))}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from this #44963, After editing the title, the user should be returned to the Details RHP instead of dismissing the RHP modal.

furtherDetailsComponent={nameSectionFurtherDetailsContent}
/>
</View>
</OfflineWithFeedback>
);

const navigateBackToAfterDelete = useRef<Route>();

const deleteTransaction = useCallback(() => {
Expand Down Expand Up @@ -565,9 +607,11 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
<ScrollView style={[styles.flex1]}>
<View style={[styles.reportDetailsTitleContainer, styles.pb0]}>
{renderedAvatar}
{isExpenseReport && nameSectionExpenseIOU}
{isExpenseReport && !shouldShowTitleField && nameSectionExpenseIOU}
</View>

{isExpenseReport && shouldShowTitleField && nameSectionTitleField}

grgia marked this conversation as resolved.
Show resolved Hide resolved
{!isExpenseReport && nameSectionGroupWorkspace}

{shouldShowReportDescription && (
Expand Down
Loading