Skip to content

Commit ee9574f

Browse files
committed
feat: hold modal for iou reports
1 parent 763218c commit ee9574f

17 files changed

Lines changed: 82 additions & 13 deletions

src/components/HoldMenuSectionList.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,23 @@ type HoldMenuSection = {
2121
titleTranslationKey: TranslationPaths;
2222
};
2323

24-
function HoldMenuSectionList() {
24+
type HoldMenuSectionListProps = {
25+
/** Whether the expense is from a DM (direct message) report */
26+
isDM?: boolean;
27+
};
28+
29+
function HoldMenuSectionList({isDM}: HoldMenuSectionListProps) {
2530
const {translate} = useLocalize();
2631
const styles = useThemeStyles();
2732
const illustrations = useMemoizedLazyIllustrations(['RealtimeReport', 'Stopwatch']);
2833
const holdMenuSections: HoldMenuSection[] = [
2934
{
3035
icon: illustrations.Stopwatch,
31-
titleTranslationKey: 'iou.holdIsLeftBehind',
36+
titleTranslationKey: isDM ? 'iou.holdIsLeftBehindDM' : 'iou.holdIsLeftBehind',
3237
},
3338
{
3439
icon: illustrations.RealtimeReport,
35-
titleTranslationKey: 'iou.unholdWhenReady',
40+
titleTranslationKey: isDM ? 'iou.unholdWhenReadyDM' : 'iou.unholdWhenReady',
3641
},
3742
];
3843

src/components/HoldSubmitterEducationalModal.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ type HoldSubmitterEducationalModalProps = {
1818

1919
/** Method to trigger when pressing confirm button */
2020
onConfirm: () => void;
21+
22+
/** Whether the expense is from a DM (direct message) report */
23+
isDM?: boolean;
2124
};
2225

23-
function HoldSubmitterEducationalModal({onClose, onConfirm}: HoldSubmitterEducationalModalProps) {
26+
function HoldSubmitterEducationalModal({onClose, onConfirm, isDM}: HoldSubmitterEducationalModalProps) {
2427
const {translate} = useLocalize();
2528
const styles = useThemeStyles();
2629
const illustrations = useMemoizedLazyIllustrations(['HoldExpense']);
@@ -30,7 +33,7 @@ function HoldSubmitterEducationalModal({onClose, onConfirm}: HoldSubmitterEducat
3033
return (
3134
<FeatureTrainingModal
3235
title={translate('iou.holdEducationalTitle')}
33-
description={translate('iou.whatIsHoldExplain')}
36+
description={translate(isDM ? 'iou.whatIsHoldExplainDM' : 'iou.whatIsHoldExplain')}
3437
confirmText={translate('common.buttonConfirm')}
3538
image={illustrations.HoldExpense}
3639
contentFitImage="cover"
@@ -44,7 +47,7 @@ function HoldSubmitterEducationalModal({onClose, onConfirm}: HoldSubmitterEducat
4447
shouldCloseOnConfirm={false}
4548
shouldUseScrollView
4649
>
47-
<HoldMenuSectionList />
50+
<HoldMenuSectionList isDM={isDM} />
4851
</FeatureTrainingModal>
4952
);
5053
}

src/components/MoneyReportHeaderEducationalModals.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import useOnyx from '@hooks/useOnyx';
55
import {setNameValuePair} from '@libs/actions/User';
66
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
77
import Navigation from '@libs/Navigation/Navigation';
8-
import {changeMoneyRequestHoldStatus, rejectMoneyRequestReason} from '@libs/ReportUtils';
8+
import {changeMoneyRequestHoldStatus, isDM, rejectMoneyRequestReason} from '@libs/ReportUtils';
99

1010
import {dismissRejectUseExplanation} from '@userActions/IOU/RejectMoneyRequest';
1111

@@ -50,6 +50,8 @@ function MoneyReportHeaderEducationalModals({reportID, ref}: MoneyReportHeaderEd
5050

5151
const {login: currentUserLogin, accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
5252

53+
const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
54+
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(moneyRequestReport?.chatReportID)}`);
5355
const {iouTransactionID, requestParentReportAction} = useMoneyReportTransactionThread();
5456
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(iouTransactionID)}`);
5557
const [transactionViolations] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${getNonEmptyStringOnyxID(iouTransactionID)}`);
@@ -109,6 +111,7 @@ function MoneyReportHeaderEducationalModals({reportID, ref}: MoneyReportHeaderEd
109111
<HoldSubmitterEducationalModal
110112
onClose={dismissModalAndUpdateUseHold}
111113
onConfirm={dismissModalAndUpdateUseHold}
114+
isDM={isDM(chatReport)}
112115
/>
113116
)}
114117
</>

src/components/MoneyRequestHeaderSecondaryActions.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,11 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
338338
return;
339339
}
340340

341-
const isDismissed = isReportSubmitter ? dismissedHoldUseExplanation : dismissedRejectUseExplanation;
342-
if (isDismissed || isParentChatReportDM) {
341+
const shouldShowHoldEducationalModal = isReportSubmitter || isParentChatReportDM;
342+
const isDismissed = shouldShowHoldEducationalModal ? dismissedHoldUseExplanation : dismissedRejectUseExplanation;
343+
if (isDismissed) {
343344
changeMoneyRequestHoldStatus(parentReportAction, transaction, isOffline, currentUserLogin ?? '', accountID, rawTransactionViolations, isTrackIntentUser);
344-
} else if (isReportSubmitter) {
345+
} else if (shouldShowHoldEducationalModal) {
345346
setIsHoldEducationalModalVisible(true);
346347
} else {
347348
setRejectModalAction(CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.HOLD);
@@ -605,6 +606,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
605606
<HoldSubmitterEducationalModal
606607
onClose={dismissModalAndUpdateUseHold}
607608
onConfirm={dismissModalAndUpdateUseHold}
609+
isDM={isParentChatReportDM}
608610
/>
609611
)}
610612
</>

src/components/Search/SearchBulkActionsButton.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) {
7272
isOfflineModalVisible,
7373
isDownloadErrorModalVisible,
7474
isHoldEducationalModalVisible,
75+
areAllTransactionsFromDMReports,
7576
rejectModalAction,
7677
emptyReportsCount,
7778
handleOfflineModalClose,
@@ -292,6 +293,7 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) {
292293
<HoldSubmitterEducationalModal
293294
onClose={dismissModalAndUpdateUseHold}
294295
onConfirm={dismissModalAndUpdateUseHold}
296+
isDM={areAllTransactionsFromDMReports}
295297
/>
296298
)}
297299
{exportDownloadStatusModal}

src/hooks/useHoldRejectActions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,12 @@ function useHoldRejectActions({reportID, onHoldEducationalOpen, onRejectModalOpe
7474
return;
7575
}
7676

77-
const isDismissed = isReportSubmitter ? dismissedHoldUseExplanation : dismissedRejectUseExplanation;
77+
const shouldShowHoldEducationalModal = isReportSubmitter || isChatReportDM;
78+
const isDismissed = shouldShowHoldEducationalModal ? dismissedHoldUseExplanation : dismissedRejectUseExplanation;
7879

79-
if (isDismissed || isChatReportDM) {
80+
if (isDismissed) {
8081
changeMoneyRequestHoldStatus(requestParentReportAction, transaction, isOffline, currentUserLogin ?? '', currentUserAccountID, transactionViolations, isTrackIntentUser);
81-
} else if (isReportSubmitter) {
82+
} else if (shouldShowHoldEducationalModal) {
8283
onHoldEducationalOpen();
8384
} else {
8485
onRejectModalOpen(CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.HOLD);

src/hooks/useSearchBulkActions.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,28 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
13331333
);
13341334
}, [selectedTransactionReportIDs, currentUserPersonalDetails?.accountID, currentSearchResults?.data, allReports]);
13351335

1336+
const areAllTransactionsFromDMReports = useMemo(() => {
1337+
const searchData = currentSearchResults?.data;
1338+
const reports: Report[] = searchData
1339+
? Object.keys(searchData)
1340+
.filter((key) => key.startsWith(ONYXKEYS.COLLECTION.REPORT))
1341+
.map((key) => searchData[key as keyof typeof searchData] as Report)
1342+
.filter((report): report is Report => report != null && 'reportID' in report)
1343+
: [];
1344+
1345+
return (
1346+
selectedTransactionReportIDs.length > 0 &&
1347+
selectedTransactionReportIDs.every((id) => {
1348+
const iouReport = getReportOrDraftReport(id, reports, undefined, undefined, allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]);
1349+
if (!iouReport?.chatReportID) {
1350+
return false;
1351+
}
1352+
const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`];
1353+
return isDM(chatReport);
1354+
})
1355+
);
1356+
}, [selectedTransactionReportIDs, currentSearchResults?.data, allReports]);
1357+
13361358
const duplicateHandlerRef = useRef<() => void>(() => {});
13371359
const setDuplicateHandler = useCallback((handler: () => void) => {
13381360
duplicateHandlerRef.current = handler;
@@ -2286,6 +2308,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
22862308
isOfflineModalVisible,
22872309
isDownloadErrorModalVisible,
22882310
isHoldEducationalModalVisible,
2311+
areAllTransactionsFromDMReports,
22892312
rejectModalAction,
22902313
emptyReportsCount,
22912314
handleOfflineModalClose,

src/languages/de.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,8 +1608,11 @@ const translations: TranslationDeepObject<typeof en> = {
16081608
approveOnly: 'Nur genehmigen',
16091609
holdEducationalTitle: 'Soll diese Ausgabe zurückgestellt werden?',
16101610
whatIsHoldExplain: 'Hold ist wie ein „Pause“-Knopf für eine Ausgabe, bis du bereit bist, sie einzureichen.',
1611+
whatIsHoldExplainDM: 'Hold ist wie ein „Pause“-Knopf für eine Ausgabe, bis du bereit bist, sie zu senden.',
16111612
holdIsLeftBehind: 'Zurückgehaltene Ausgaben werden ausgelassen, selbst wenn du einen gesamten Bericht einreichst.',
1613+
holdIsLeftBehindDM: 'Zurückgehaltene Ausgaben werden erst gesendet, wenn du die Zurückstellung aufhebst.',
16121614
unholdWhenReady: 'Gib Ausgaben wieder frei, wenn du bereit bist, sie einzureichen.',
1615+
unholdWhenReadyDM: 'Hebe die Zurückstellung auf, wenn du bereit bist, die Ausgaben zu senden.',
16131616
changePolicyEducational: {
16141617
title: 'Du hast diesen Bericht verschoben!',
16151618
description: 'Überprüfe diese Punkte sorgfältig, da sie sich beim Verschieben von Berichten in einen neuen Workspace häufig ändern.',

src/languages/en.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,8 +1676,11 @@ const translations = {
16761676
approveOnly: 'Approve only',
16771677
holdEducationalTitle: 'Should you hold this expense?',
16781678
whatIsHoldExplain: "Hold is like hitting “pause” on an expense until you're ready to submit it.",
1679+
whatIsHoldExplainDM: "Hold is like hitting 'pause' on an expense until you're ready to send it.",
16791680
holdIsLeftBehind: 'Held expenses are left behind even if you submit an entire report.',
1681+
holdIsLeftBehindDM: "Held expenses won't be sent until you remove the hold.",
16801682
unholdWhenReady: "Unhold expenses when you're ready to submit them.",
1683+
unholdWhenReadyDM: "Unhold expenses when you're ready to send them.",
16811684
changePolicyEducational: {
16821685
title: 'You moved this report!',
16831686
description: 'Double-check these items, which tend to change when moving reports to a new workspace.',

src/languages/es.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,8 +1567,11 @@ const translations: TranslationDeepObject<typeof en> = {
15671567
unhold: 'Desbloquear',
15681568
holdEducationalTitle: '¿Deberías retener este gasto?',
15691569
whatIsHoldExplain: 'Retener es como presionar "pausa" en un gasto hasta que estés listo para enviarlo.',
1570+
whatIsHoldExplainDM: 'Retener es como presionar "pausa" en un gasto hasta que estés listo para enviarlo.',
15701571
holdIsLeftBehind: 'Los gastos retenidos se quedan fuera incluso si envías un informe completo.',
1572+
holdIsLeftBehindDM: 'Los gastos retenidos no se enviarán hasta que los desbloquees.',
15711573
unholdWhenReady: 'Desbloquea los gastos cuando estés listo para enviarlos.',
1574+
unholdWhenReadyDM: 'Desbloquea los gastos cuando estés listo para enviarlos.',
15721575
changePolicyEducational: {
15731576
title: '¡Has movido este informe!',
15741577
description: 'Revisa cuidadosamente estos elementos, que tienden a cambiar al trasladar informes a un nuevo espacio de trabajo.',

0 commit comments

Comments
 (0)