Skip to content

Commit 0754949

Browse files
authored
Merge pull request #58407 from Expensify/jasper-handleConciergeCategoryOptions
Render ConciergeCategoryOptions actions
2 parents 9fd974c + 7746cfe commit 0754949

File tree

6 files changed

+73
-4
lines changed

6 files changed

+73
-4
lines changed

src/CONST.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,7 @@ const CONST = {
12521252
UNHOLD: 'UNHOLD',
12531253
UNSHARE: 'UNSHARE', // OldDot Action
12541254
UPDATE_GROUP_CHAT_MEMBER_ROLE: 'UPDATEGROUPCHATMEMBERROLE',
1255+
CONCIERGE_CATEGORY_OPTIONS: 'CONCIERGECATEGORYOPTIONS',
12551256
POLICY_CHANGE_LOG: {
12561257
ADD_APPROVER_RULE: 'POLICYCHANGELOG_ADD_APPROVER_RULE',
12571258
ADD_BUDGET: 'POLICYCHANGELOG_ADD_BUDGET',

src/components/ReportActionItem/ActionableItemButtons.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ type ActionableItem = {
99
isPrimary?: boolean;
1010
key: string;
1111
onPress: () => void;
12-
text: TranslationPaths;
12+
text: string;
1313
isMediumSized?: boolean;
14+
shouldUseLocalization?: boolean;
1415
};
1516

1617
type ActionableItemButtonsProps = {
1718
items: ActionableItem[];
1819
layout?: 'horizontal' | 'vertical';
20+
shouldUseLocalization?: boolean;
1921
};
2022

2123
function ActionableItemButtons(props: ActionableItemButtonsProps) {
@@ -28,7 +30,7 @@ function ActionableItemButtons(props: ActionableItemButtonsProps) {
2830
<Button
2931
key={item.key}
3032
onPress={item.onPress}
31-
text={translate(item.text)}
33+
text={props.shouldUseLocalization ? translate(item.text as TranslationPaths) : item.text}
3234
small={!item.isMediumSized}
3335
medium={item.isMediumSized}
3436
success={item.isPrimary}

src/libs/ReportActionsUtils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,15 @@ function isResolvedActionableWhisper(reportAction: OnyxEntry<ReportAction>): boo
799799
return !!resolution;
800800
}
801801

802+
/**
803+
* Checks whether an action is concierge category options and resolved.
804+
*/
805+
function isResolvedConciergeCategoryOptions(reportAction: OnyxEntry<ReportAction>): boolean {
806+
const originalMessage = getOriginalMessage(reportAction);
807+
const selectedCategory = originalMessage && typeof originalMessage === 'object' && 'selectedCategory' in originalMessage ? originalMessage?.selectedCategory : null;
808+
return !!selectedCategory;
809+
}
810+
802811
/**
803812
* Checks if a reportAction is fit for display, meaning that it's not deprecated, is of a valid
804813
* and supported type, it's not deleted and also not closed.
@@ -852,6 +861,10 @@ function shouldReportActionBeVisible(reportAction: OnyxEntry<ReportAction>, key:
852861
return false;
853862
}
854863

864+
if (isConciergeCategoryOptions(reportAction) && isResolvedConciergeCategoryOptions(reportAction)) {
865+
return false;
866+
}
867+
855868
// All other actions are displayed except thread parents, deleted, or non-pending actions
856869
const isDeleted = isDeletedAction(reportAction);
857870
const isPending = !!reportAction.pendingAction;
@@ -1617,6 +1630,10 @@ function isActionableJoinRequestPendingReportAction(reportAction: OnyxEntry<Repo
16171630
return isActionableJoinRequest(reportAction) && getOriginalMessage(reportAction)?.choice === ('' as JoinWorkspaceResolution);
16181631
}
16191632

1633+
function isConciergeCategoryOptions(reportAction: OnyxEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.CONCIERGE_CATEGORY_OPTIONS> {
1634+
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.CONCIERGE_CATEGORY_OPTIONS);
1635+
}
1636+
16201637
function getActionableJoinRequestPendingReportAction(reportID: string): OnyxEntry<ReportAction> {
16211638
const findPendingRequest = Object.values(getAllReportActions(reportID)).find((reportActionItem) => isActionableJoinRequestPendingReportAction(reportActionItem));
16221639
return findPendingRequest;
@@ -2377,6 +2394,8 @@ export {
23772394
isActionableMentionWhisper,
23782395
isActionableReportMentionWhisper,
23792396
isActionableTrackExpense,
2397+
isConciergeCategoryOptions,
2398+
isResolvedConciergeCategoryOptions,
23802399
isAddCommentAction,
23812400
isApprovedOrSubmittedReportAction,
23822401
isChronosOOOListAction,

src/libs/actions/Report.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,29 @@ function addAttachment(reportID: string, file: FileObject, text = '') {
777777

778778
/** Add a single comment to a report */
779779
function addComment(reportID: string, text: string) {
780+
// If we are resolving a Concierge Category Options action on an expense report that only has a single transaction thread child report, we need to add the action to the transaction thread instead.
781+
// This is because we need it to be associated with the transaction thread and not the expense report.
782+
if (isExpenseReport(allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`])) {
783+
const reportActions = allReportActions?.[reportID];
784+
if (reportActions) {
785+
const moneyRequestPreviewActions = Object.values(reportActions).filter((action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
786+
if (moneyRequestPreviewActions.length === 1) {
787+
const transactionThreadReportID = moneyRequestPreviewActions.at(0)?.childReportID;
788+
if (transactionThreadReportID) {
789+
const transactionThreadReportActions = allReportActions?.[transactionThreadReportID];
790+
if (transactionThreadReportActions) {
791+
const conciergeCategoryOptionsAction = Object.values(transactionThreadReportActions).find(
792+
(action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.CONCIERGE_CATEGORY_OPTIONS,
793+
);
794+
if (conciergeCategoryOptionsAction && !ReportActionsUtils.isResolvedConciergeCategoryOptions(conciergeCategoryOptionsAction)) {
795+
addActions(transactionThreadReportID, text);
796+
return;
797+
}
798+
}
799+
}
800+
}
801+
}
802+
}
780803
addActions(reportID, text);
781804
}
782805

src/pages/home/report/PureReportActionItem.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import {
8888
isActionableTrackExpense,
8989
isActionOfType,
9090
isChronosOOOListAction,
91+
isConciergeCategoryOptions,
9192
isCreatedTaskReportAction,
9293
isDeletedAction,
9394
isDeletedParentAction as isDeletedParentActionUtils,
@@ -134,7 +135,7 @@ import {ReactionListContext} from '@pages/home/ReportScreenContext';
134135
import {openPersonalBankAccountSetupView} from '@userActions/BankAccounts';
135136
import {hideEmojiPicker, isActive} from '@userActions/EmojiPickerAction';
136137
import {acceptJoinRequest, declineJoinRequest} from '@userActions/Policy/Member';
137-
import {expandURLPreview} from '@userActions/Report';
138+
import {addComment, expandURLPreview} from '@userActions/Report';
138139
import type {IgnoreDirection} from '@userActions/ReportActions';
139140
import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session';
140141
import {isBlockedFromConcierge} from '@userActions/User';
@@ -634,6 +635,20 @@ function PureReportActionItem({
634635
];
635636
}
636637

638+
if (isConciergeCategoryOptions(action)) {
639+
const options = getOriginalMessage(action)?.options;
640+
if (!options) {
641+
return [];
642+
}
643+
return options.map((option, i) => ({
644+
text: `${i + 1} - ${option}`,
645+
key: `${action.reportActionID}-conciergeCategoryOptions-${option}`,
646+
onPress: () => {
647+
addComment(originalReportID, option);
648+
},
649+
}));
650+
}
651+
637652
if (!isActionableWhisper && (!isActionableJoinRequest(action) || getOriginalMessage(action)?.choice !== ('' as JoinWorkspaceResolution))) {
638653
return [];
639654
}
@@ -730,6 +745,7 @@ function PureReportActionItem({
730745
dismissTrackExpenseActionableWhisper,
731746
resolveActionableReportMentionWhisper,
732747
resolveActionableMentionWhisper,
748+
originalReportID,
733749
]);
734750

735751
/**
@@ -1049,7 +1065,8 @@ function PureReportActionItem({
10491065
{actionableItemButtons.length > 0 && (
10501066
<ActionableItemButtons
10511067
items={actionableItemButtons}
1052-
layout={isActionableTrackExpense(action) ? 'vertical' : 'horizontal'}
1068+
layout={isActionableTrackExpense(action) || isConciergeCategoryOptions(action) ? 'vertical' : 'horizontal'}
1069+
shouldUseLocalization={!isConciergeCategoryOptions(action)}
10531070
/>
10541071
)}
10551072
</View>

src/types/onyx/OriginalMessage.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,12 @@ type OriginalMessageDeletedTransaction = {
515515
currency?: string;
516516
};
517517

518+
/** Model of `concierge category options` report action */
519+
type OriginalMessageConciergeCategoryOptions = {
520+
/** The options we present to the user when confidence in the predicted category is low */
521+
options: string[];
522+
};
523+
518524
/** Model of `reimbursement queued` report action */
519525
type OriginalMessageReimbursementQueued = {
520526
/** How is the payment getting reimbursed */
@@ -806,6 +812,7 @@ type OriginalMessageMap = {
806812
[CONST.REPORT.ACTIONS.TYPE.CARD_ASSIGNED]: OriginalMessageCard;
807813
[CONST.REPORT.ACTIONS.TYPE.INTEGRATION_SYNC_FAILED]: OriginalMessageIntegrationSyncFailed;
808814
[CONST.REPORT.ACTIONS.TYPE.DELETED_TRANSACTION]: OriginalMessageDeletedTransaction;
815+
[CONST.REPORT.ACTIONS.TYPE.CONCIERGE_CATEGORY_OPTIONS]: OriginalMessageConciergeCategoryOptions;
809816
} & OldDotOriginalMessageMap & {
810817
[T in ValueOf<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG>]: OriginalMessagePolicyChangeLog;
811818
} & {

0 commit comments

Comments
 (0)