Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f9453dd
add nextStep field to Report type
s77rt Oct 4, 2025
4cbaf67
update comment
s77rt Oct 4, 2025
16b9af1
export type ReportNextStep
s77rt Oct 4, 2025
917e0c4
deprecate ReportNextStep old format
s77rt Oct 4, 2025
adb45d5
pass nextStep (new format) to MoneyReportHeaderStatusBar
s77rt Oct 5, 2025
3f37b79
add nextstep messages
s77rt Oct 5, 2025
7ab6aee
add buildMessage()
s77rt Oct 5, 2025
b874870
lint
s77rt Oct 5, 2025
44d2c3d
merge main
s77rt Oct 7, 2025
5373d7a
lint
s77rt Oct 7, 2025
7033ee9
actorAccountID is optional
s77rt Oct 7, 2025
7a384a0
deprecate old NextStep util functions
s77rt Oct 7, 2025
f1a0fbb
better deprecation message
s77rt Oct 7, 2025
2170fb8
implement buildOptimisticNextStep
s77rt Oct 7, 2025
76f2eac
optimistically set report.nextStep
s77rt Oct 7, 2025
4b7b440
lint
s77rt Oct 7, 2025
5f0dfe7
better custom date handling
s77rt Oct 7, 2025
8b0b598
handle optimistic custom offset eta
s77rt Oct 7, 2025
f271005
fix dependency cycle
s77rt Oct 7, 2025
453a225
lint + spell
s77rt Oct 7, 2025
cd34fb5
fix translation
s77rt Oct 7, 2025
63be1af
lint
s77rt Oct 7, 2025
59e5db4
merge main
s77rt Oct 27, 2025
bc1f676
fix types
s77rt Oct 27, 2025
364fddc
lint
s77rt Oct 27, 2025
6360eca
spell check
s77rt Oct 27, 2025
ec8e8c2
add nextStep to WhitelistedReport
s77rt Oct 27, 2025
5e0230f
fix lint
s77rt Oct 27, 2025
ca39615
fix test
s77rt Oct 27, 2025
af2b87f
lint
s77rt Oct 27, 2025
02ce676
add missed optimistic changes
s77rt Oct 28, 2025
5630e6d
merge main
s77rt Oct 28, 2025
aa39db3
merge main
s77rt Oct 29, 2025
cfebf74
Merge branch 'main' into report-nextstep
s77rt Oct 29, 2025
8781278
add translations
s77rt Oct 29, 2025
4e166b6
lint
s77rt Oct 29, 2025
1a3cc74
Merge branch 'main' into report-nextstep
s77rt Oct 31, 2025
e843b0c
update test
s77rt Oct 31, 2025
e91e374
Merge branch 'main' into report-nextstep
s77rt Oct 31, 2025
fba394c
fix test
s77rt Oct 31, 2025
682e58d
merge main
s77rt Nov 9, 2025
bead5f9
fix tests
s77rt Nov 9, 2025
c44e3cb
merge main
s77rt Nov 11, 2025
eeca03e
Merge branch 'main' into report-nextstep
s77rt Nov 11, 2025
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
29 changes: 29 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1517,11 +1517,40 @@ const CONST = {
},
EXPORT_TEMPLATE: 'exportTemplate',
NEXT_STEP: {
MESSAGE_KEY: {
WAITING_TO_ADD_TRANSACTIONS: 'waitingToAddTransactions',
NO_FURTHER_ACTION: 'noFurtherAction',
WAITING_FOR_SUBMITTER_ACCOUNT: 'waitingForSubmitterAccount',
WAITING_FOR_AUTOMATIC_SUBMIT: 'waitingForAutomaticSubmit',
WAITING_TO_FIX_ISSUES: 'waitingToFixIssues',
WAITING_TO_APPROVE: 'waitingToApprove',
WAITING_TO_PAY: 'waitingToPay',
WAITING_FOR_POLICY_BANK_ACCOUNT: 'waitingForPolicyBankAccount',
WAITING_FOR_PAYMENT: 'waitingForPayment',
},
ICONS: {
HOURGLASS: 'hourglass',
CHECKMARK: 'checkmark',
STOPWATCH: 'stopwatch',
},
ETA_KEY: {
SHORTLY: 'shortly',
TODAY: 'today',
END_OF_WEEK: 'endOfWeek',
SEMI_MONTHLY: 'semiMonthly',
LAST_BUSINESS_DAY_OF_MONTH: 'lastBusinessDayOfMonth',
LAST_DAY_OF_MONTH: 'lastDayOfMonth',
END_OF_TRIP: 'endOfTrip',
},
ACTOR_TYPE: {
CURRENT_USER: 'currentUser',
OTHER_USER: 'otherUser',
UNSPECIFIED_ADMIN: 'unspecifiedAdmin',
},
ETA_TYPE: {
KEY: 'key',
DATE_TIME: 'dateTime',
},
},
UNREPORTED_EXPENSES_PAGE_SIZE: 50,
COMPOSER: {
Expand Down
2 changes: 1 addition & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ type OnyxCollectionValuesMapping = {
[ONYXKEYS.COLLECTION.SELECTED_DISTANCE_REQUEST_TAB]: OnyxTypes.SelectedTabRequest;
[ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string;
[ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDF_FILENAME]: string;
[ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep;
[ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStepDeprecated;
[ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER]: OnyxTypes.PolicyJoinMember;
[ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS]: OnyxTypes.PolicyConnectionSyncProgress;
[ONYXKEYS.COLLECTION.SNAPSHOT]: OnyxTypes.SearchResults;
Expand Down
6 changes: 3 additions & 3 deletions src/components/MoneyReportHeaderStatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {parseMessage} from '@libs/NextStepUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type ReportNextStep from '@src/types/onyx/ReportNextStep';
import type ReportNextStepDeprecated from '@src/types/onyx/ReportNextStepDeprecated';
import type IconAsset from '@src/types/utils/IconAsset';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import RenderHTML from './RenderHTML';

type MoneyReportHeaderStatusBarProps = {
/** The next step for the report */
nextStep: ReportNextStep | undefined;
/** The next step for the report (deprecated old format) */
nextStep: ReportNextStepDeprecated | undefined;
};

type IconName = ValueOf<typeof CONST.NEXT_STEP.ICONS>;
Expand Down
104 changes: 104 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ import type {
MovedTransactionParams,
NeedCategoryForExportToIntegrationParams,
NewWorkspaceNameParams,
NextStepParams,
NoLongerHaveAccessParams,
NotAllowedExtensionParams,
NotYouParams,
Expand Down Expand Up @@ -7411,6 +7412,109 @@ ${amount} für ${merchant} - ${date}`,
subtitle: `Wir konnten nicht alle Ihre Daten laden. Wir wurden benachrichtigt und untersuchen das Problem. Wenn das weiterhin besteht, wenden Sie sich bitte an`,
refreshAndTryAgain: 'Aktualisieren und erneut versuchen',
},
nextStep: {
message: {
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Warte darauf, dass <strong>du</strong> Ausgaben hinzufügst.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten darauf, dass <strong>${actor}</strong> Ausgaben hinzufügt.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten auf einen Admin, der Ausgaben hinzufügt.`;
}
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Keine weiteren Maßnahmen erforderlich!`,
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Es wird darauf gewartet, dass <strong>Sie</strong> ein Bankkonto hinzufügen.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten darauf, dass <strong>${actor}</strong> ein Bankkonto hinzufügt.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten, bis ein Admin ein Bankkonto hinzufügt.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
let formattedETA = '';
if (eta) {
formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `am ${eta}` : ` ${eta}`;
}
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Warten, bis <strong>Ihre</strong> Ausgaben automatisch eingereicht werden${formattedETA}.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten auf die automatische Einreichung der Ausgaben von <strong>${actor}</strong>${formattedETA}.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten darauf, dass die Ausgaben eines Administrators automatisch eingereicht werden${formattedETA}.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Warten darauf, dass <strong>Sie</strong> die Problem(e) beheben.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten auf <strong>${actor}</strong>, um das/die Problem(e) zu beheben.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten auf einen Admin, um das/die Problem(e) zu beheben.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Es wird darauf gewartet, dass <strong>du</strong> Ausgaben genehmigst.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten auf die Genehmigung der Ausgaben durch <strong>${actor}</strong>.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten darauf, dass ein Admin die Ausgaben genehmigt.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Warten darauf, dass <strong>Sie</strong> Ausgaben begleichen.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten darauf, dass <strong>${actor}</strong> die Ausgaben bezahlt.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten, bis ein Administrator die Ausgaben bezahlt.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Warten darauf, dass <strong>du</strong> die Einrichtung eines Geschäftskontos abschließt.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Warten darauf, dass <strong>${actor}</strong> die Einrichtung eines Firmenbankkontos abschließt.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Warten darauf, dass ein Admin die Einrichtung eines Firmenbankkontos abschließt.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
let formattedETA = '';
if (eta) {
formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `bis ${eta}` : ` ${eta}`;
}
return `Warten auf Abschluss der Zahlung${formattedETA}.`;
},
},
eta: {
[CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'in Kürze',
[CONST.NEXT_STEP.ETA_KEY.TODAY]: 'später heute',
[CONST.NEXT_STEP.ETA_KEY.END_OF_WEEK]: 'am Sonntag',
[CONST.NEXT_STEP.ETA_KEY.SEMI_MONTHLY]: 'am 1. und 16. jedes Monats',
[CONST.NEXT_STEP.ETA_KEY.LAST_BUSINESS_DAY_OF_MONTH]: 'am letzten Werktag des Monats',
[CONST.NEXT_STEP.ETA_KEY.LAST_DAY_OF_MONTH]: 'am letzten Tag des Monats',
[CONST.NEXT_STEP.ETA_KEY.END_OF_TRIP]: 'am Ende Ihrer Reise',
},
},
domain: {
notVerified: 'Nicht verifiziert',
retry: 'Erneut versuchen',
Expand Down
113 changes: 113 additions & 0 deletions src/languages/en.ts

@eh2077 eh2077 Oct 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we can add other languages together in this PR.

Edited: it seems bot can automatically generate translations, see slack

Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ import type {
MovedTransactionParams,
NeedCategoryForExportToIntegrationParams,
NewWorkspaceNameParams,
NextStepParams,
NoLongerHaveAccessParams,
NotAllowedExtensionParams,
NotYouParams,
Expand Down Expand Up @@ -1552,6 +1553,118 @@ const translations = {
modal: {
backdropLabel: 'Modal Backdrop',
},
nextStep: {
message: {
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to add expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to add expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to add expenses.`;
}
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `No further action required!`,
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to add a bank account.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to add a bank account.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to add a bank account.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
let formattedETA = '';
if (eta) {
formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? ` on ${eta}` : ` ${eta}`;
}

// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>your</strong> expenses to automatically submit${formattedETA}.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}'s</strong> expenses to automatically submit${formattedETA}.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin's expenses to automatically submit${formattedETA}.`;
Comment on lines +1593 to +1598

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@jamesdeanexpensify since you've been working on these lately - is this the message we want in ND? Or should it just be Waiting for expenses... instead of your/actor's

}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to fix the issue(s).`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to fix the issue(s).`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to fix the issue(s).`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to approve expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to approve expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to approve expenses.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to pay expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to pay expenses.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to pay expenses.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
// Disabling the default-case lint rule here is actually safer as this forces us to make the switch cases exhaustive
// eslint-disable-next-line default-case
switch (actorType) {
case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
return `Waiting for <strong>you</strong> to finish setting up a business bank account.`;
case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
return `Waiting for <strong>${actor}</strong> to finish setting up a business bank account.`;
case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
return `Waiting for an admin to finish setting up a business bank account.`;
}
},
[CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
let formattedETA = '';
if (eta) {
formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? ` by ${eta}` : ` ${eta}`;
}

return `Waiting for payment to complete${formattedETA}.`;
},
},
eta: {
[CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'shortly',
[CONST.NEXT_STEP.ETA_KEY.TODAY]: 'later today',
[CONST.NEXT_STEP.ETA_KEY.END_OF_WEEK]: 'on Sunday',
[CONST.NEXT_STEP.ETA_KEY.SEMI_MONTHLY]: 'on the 1st and 16th of each month',
[CONST.NEXT_STEP.ETA_KEY.LAST_BUSINESS_DAY_OF_MONTH]: 'on the last business day of the month',
[CONST.NEXT_STEP.ETA_KEY.LAST_DAY_OF_MONTH]: 'on the last day of the month',
[CONST.NEXT_STEP.ETA_KEY.END_OF_TRIP]: 'at the end of your trip',
},
},
profilePage: {
profile: 'Profile',
preferredPronouns: 'Preferred pronouns',
Expand Down
Loading
Loading