Show submit button with error modal for pending card transactions#87750
Show submit button with error modal for pending card transactions#87750
Conversation
…d transactions Instead of hiding the submit button when all transactions on a report are pending Expensify Card transactions, show the button and display an error modal when clicked explaining why submission is blocked. Also updates the status bar message to clearly communicate the submission restriction. Co-authored-by: Sobit Neupane <sobitneupane@users.noreply.github.com>
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index a9ebd083..f9258b25 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1286,7 +1286,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'Nur du kannst diesen Beleg sehen, während er gescannt wird. Schau später noch einmal vorbei oder gib die Details jetzt ein.',
receiptScanningFailed: 'Belegerkennung fehlgeschlagen. Bitte geben Sie die Details manuell ein.',
transactionPendingDescription: 'Transaktion ausstehend. Die Buchung kann ein paar Tage dauern.',
- allTransactionsPendingNextStep: 'Alle Transaktionen sind ausstehend. Du kannst diesen Bericht erst einreichen, wenn sie gebucht sind. Dies kann ein paar Tage dauern.',
+ allTransactionsPendingNextStep: 'Alle Transaktionen sind ausstehend. Sie können diesen Bericht erst einreichen, wenn sie gebucht wurden. Dies kann ein paar Tage dauern.',
companyInfo: 'Unternehmensinfos',
companyInfoDescription: 'Wir benötigen noch ein paar weitere Angaben, bevor du deine erste Rechnung senden kannst.',
yourCompanyName: 'Ihr Firmenname',
@@ -1475,7 +1475,7 @@ const translations: TranslationDeepObject<typeof en> = {
dateRangeExceedsMaxDays: `Der Datumsbereich darf ${CONST.IOU.SPLITS_LIMIT} Tage nicht überschreiten.`,
stitchOdometerImagesFailed: 'Kilometerzählerbilder konnten nicht zusammengeführt werden. Bitte versuchen Sie es später noch einmal.',
unableToSubmitReport: 'Bericht kann nicht eingereicht werden',
- allTransactionsPendingDescription: 'Du kannst diesen Bericht nicht einreichen, da alle Transaktionen ausstehend sind. Die Buchung kann einige Tage dauern.',
+ allTransactionsPendingDescription: 'Sie können diesen Bericht nicht einreichen, weil alle Transaktionen ausstehend sind. Es kann ein paar Tage dauern, bis sie verbucht werden.',
nonReimbursablePayment: 'Kann nicht über Expensify bezahlt werden',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index fc7fa764..edd4b410 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1291,7 +1291,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptScanningFailed: 'L’analyse du reçu a échoué. Veuillez saisir les détails manuellement.',
transactionPendingDescription: "Transaction en attente. L'inscription peut prendre quelques jours.",
allTransactionsPendingNextStep:
- "Toutes les transactions sont en attente. Vous ne pouvez pas soumettre ce rapport tant qu'elles ne sont pas enregistrées. Cela peut prendre quelques jours.",
+ 'Toutes les transactions sont en attente. Vous ne pouvez pas soumettre cette note de frais tant qu’elles ne sont pas comptabilisées. Cela peut prendre quelques jours.',
companyInfo: 'Informations sur l’entreprise',
companyInfoDescription: 'Nous avons besoin de quelques informations supplémentaires avant que vous puissiez envoyer votre première facture.',
yourCompanyName: 'Nom de votre entreprise',
@@ -1478,8 +1478,9 @@ const translations: TranslationDeepObject<typeof en> = {
manySplitsProvided: `Le nombre maximal de répartitions autorisées est de ${CONST.IOU.SPLITS_LIMIT}.`,
dateRangeExceedsMaxDays: `La plage de dates ne peut pas dépasser ${CONST.IOU.SPLITS_LIMIT} jours.`,
stitchOdometerImagesFailed: 'Échec de la combinaison des images de l’odomètre. Veuillez réessayer plus tard.',
- unableToSubmitReport: 'Impossible de soumettre le rapport',
- allTransactionsPendingDescription: 'Vous ne pouvez pas soumettre ce rapport car toutes les transactions sont en attente. Leur enregistrement peut prendre quelques jours.',
+ unableToSubmitReport: 'Impossible de soumettre la note de frais',
+ allTransactionsPendingDescription:
+ 'Vous ne pouvez pas soumettre cette note de frais, car toutes les transactions sont en attente. Leur comptabilisation peut prendre quelques jours.',
nonReimbursablePayment: 'Impossible de payer via Expensify',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 503162db..73539e60 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1285,7 +1285,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'Solo tu puoi vedere questa ricevuta mentre viene scansionata. Controlla più tardi o inserisci i dettagli ora.',
receiptScanningFailed: 'Scansione della ricevuta non riuscita. Inserisci i dettagli manualmente.',
transactionPendingDescription: 'Transazione in sospeso. Potrebbero essere necessari alcuni giorni prima che venga registrata.',
- allTransactionsPendingNextStep: 'Tutte le transazioni sono in sospeso. Non puoi inviare questo report finché non vengono registrate. Potrebbero essere necessari alcuni giorni.',
+ allTransactionsPendingNextStep: 'Tutte le transazioni sono in sospeso. Non puoi inviare questo report finché non vengono contabilizzate. Questo potrebbe richiedere alcuni giorni.',
companyInfo: 'Informazioni azienda',
companyInfoDescription: 'Ci servono ancora alcuni dettagli prima che tu possa inviare la tua prima fattura.',
yourCompanyName: 'Nome dell’azienda',
@@ -1472,7 +1472,8 @@ const translations: TranslationDeepObject<typeof en> = {
dateRangeExceedsMaxDays: `L’intervallo di date non può superare ${CONST.IOU.SPLITS_LIMIT} giorni.`,
stitchOdometerImagesFailed: 'Impossibile combinare le immagini del contachilometri. Riprova più tardi.',
unableToSubmitReport: 'Impossibile inviare il report',
- allTransactionsPendingDescription: 'Non puoi inviare questo report perché tutte le transazioni sono in sospeso. Potrebbero essere necessari alcuni giorni per la registrazione.',
+ allTransactionsPendingDescription:
+ 'Non puoi inviare questo report perché tutte le transazioni sono in sospeso. Potrebbero volerci alcuni giorni prima che vengano contabilizzate.',
nonReimbursablePayment: 'Impossibile pagare tramite Expensify',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 7f9577f9..23fde1a8 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1268,7 +1268,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'スキャン中のレシートは、あなただけが見ることができます。後でまた確認するか、今すぐ詳細を入力してください。',
receiptScanningFailed: 'レシートのスキャンに失敗しました。詳細を手入力してください。',
transactionPendingDescription: '取引は保留中です。記帳されるまで数日かかる場合があります。',
- allTransactionsPendingNextStep: 'すべての取引が保留中です。記帳されるまでこのレポートを提出できません。数日かかる場合があります。',
+ allTransactionsPendingNextStep: 'すべての取引が保留中です。記帳されるまでこのレポートを提出することはできません。処理には数日かかる場合があります。',
companyInfo: '会社情報',
companyInfoDescription: '最初の請求書を送信する前に、いくつか追加の情報が必要です。',
yourCompanyName: '会社名',
@@ -1453,8 +1453,8 @@ const translations: TranslationDeepObject<typeof en> = {
manySplitsProvided: `分割できる最大数は${CONST.IOU.SPLITS_LIMIT}件です。`,
dateRangeExceedsMaxDays: `日付範囲は${CONST.IOU.SPLITS_LIMIT}日を超えることはできません。`,
stitchOdometerImagesFailed: '走行距離計の画像を結合できませんでした。後でもう一度お試しください。',
- unableToSubmitReport: 'レポートを提出できません',
- allTransactionsPendingDescription: 'すべての取引が保留中のため、このレポートを提出できません。記帳されるまで数日かかる場合があります。',
+ unableToSubmitReport: 'レポートを送信できません',
+ allTransactionsPendingDescription: 'すべての取引が保留中のため、このレポートを提出できません。取引の反映までに数日かかる場合があります。',
nonReimbursablePayment: 'Expensify経由では支払えません',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 5badbfff..1eef3c0d 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1284,7 +1284,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'Alleen jij kunt deze bon zien terwijl hij wordt gescand. Kom later terug of voer de gegevens nu in.',
receiptScanningFailed: 'Bon scannen mislukt. Voer de gegevens handmatig in.',
transactionPendingDescription: 'Transactie in behandeling. Het kan een paar dagen duren voordat deze wordt verwerkt.',
- allTransactionsPendingNextStep: 'Alle transacties zijn in behandeling. Je kunt dit rapport pas indienen als ze zijn verwerkt. Dit kan een paar dagen duren.',
+ allTransactionsPendingNextStep: 'Alle transacties zijn in behandeling. Je kunt dit rapport pas indienen zodra ze zijn geboekt. Dit kan een paar dagen duren.',
companyInfo: 'Bedrijfsgegevens',
companyInfoDescription: 'We hebben nog een paar gegevens nodig voordat je je eerste factuur kunt versturen.',
yourCompanyName: 'Naam van je bedrijf',
@@ -1469,8 +1469,8 @@ const translations: TranslationDeepObject<typeof en> = {
manySplitsProvided: `Het maximale aantal toegestane splitsingen is ${CONST.IOU.SPLITS_LIMIT}.`,
dateRangeExceedsMaxDays: `Het datumbereik mag niet meer dan ${CONST.IOU.SPLITS_LIMIT} dagen zijn.`,
stitchOdometerImagesFailed: 'Odometerafbeeldingen combineren mislukt. Probeer het later opnieuw.',
- unableToSubmitReport: 'Kan rapport niet indienen',
- allTransactionsPendingDescription: 'Je kunt dit rapport niet indienen omdat alle transacties in behandeling zijn. Het kan een paar dagen duren voordat ze worden verwerkt.',
+ unableToSubmitReport: 'Rapport kan niet worden ingediend',
+ allTransactionsPendingDescription: 'Je kunt dit rapport niet indienen omdat alle transacties in behandeling zijn. Het kan een paar dagen duren voordat ze zijn geboekt.',
nonReimbursablePayment: 'Kan niet via Expensify worden betaald',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 23e944bc..e546a31a 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1283,7 +1283,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'Tylko ty widzisz ten paragon podczas skanowania. Sprawdź ponownie później lub wprowadź szczegóły teraz.',
receiptScanningFailed: 'Skanowanie paragonu nie powiodło się. Wprowadź dane ręcznie.',
transactionPendingDescription: 'Transakcja w toku. Zaksięgowanie może potrwać kilka dni.',
- allTransactionsPendingNextStep: 'Wszystkie transakcje są w toku. Nie możesz wysłać tego raportu, dopóki nie zostaną zaksięgowane. Może to potrwać kilka dni.',
+ allTransactionsPendingNextStep: 'Wszystkie transakcje są w toku. Nie możesz wysłać tego raportu, dopóki nie zostaną zaksięgowane. To może potrwać kilka dni.',
companyInfo: 'Informacje o firmie',
companyInfoDescription: 'Potrzebujemy jeszcze kilku informacji, zanim będziesz mógł wysłać swoją pierwszą fakturę.',
yourCompanyName: 'Nazwa Twojej firmy',
@@ -1468,7 +1468,7 @@ const translations: TranslationDeepObject<typeof en> = {
dateRangeExceedsMaxDays: `Zakres dat nie może przekraczać ${CONST.IOU.SPLITS_LIMIT} dni.`,
stitchOdometerImagesFailed: 'Nie udało się połączyć zdjęć licznika kilometrów. Spróbuj ponownie później.',
unableToSubmitReport: 'Nie można wysłać raportu',
- allTransactionsPendingDescription: 'Nie możesz wysłać tego raportu, ponieważ wszystkie transakcje są w toku. Zaksięgowanie może potrwać kilka dni.',
+ allTransactionsPendingDescription: 'Nie możesz przesłać tego raportu, ponieważ wszystkie transakcje są w toku. Ich zaksięgowanie może zająć kilka dni.',
nonReimbursablePayment: 'Nie można zapłacić przez Expensify',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 7651e444..4347a95a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1283,7 +1283,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: 'Só você pode ver este recibo enquanto ele está sendo digitalizado. Volte mais tarde ou insira os detalhes agora.',
receiptScanningFailed: 'Falha ao escanear o recibo. Insira os detalhes manualmente.',
transactionPendingDescription: 'Transação pendente. Pode levar alguns dias para ser lançada.',
- allTransactionsPendingNextStep: 'Todas as transações estão pendentes. Você não pode enviar este relatório até que sejam lançadas. Isso pode levar alguns dias.',
+ allTransactionsPendingNextStep: 'Todas as transações estão pendentes. Você não pode enviar este relatório até que elas sejam lançadas. Isso pode levar alguns dias.',
companyInfo: 'Informações da empresa',
companyInfoDescription: 'Precisamos de mais alguns detalhes antes que você possa enviar sua primeira fatura.',
yourCompanyName: 'Nome da sua empresa',
@@ -1466,8 +1466,8 @@ const translations: TranslationDeepObject<typeof en> = {
manySplitsProvided: `O número máximo de divisões permitido é ${CONST.IOU.SPLITS_LIMIT}.`,
dateRangeExceedsMaxDays: `O intervalo de datas não pode exceder ${CONST.IOU.SPLITS_LIMIT} dias.`,
stitchOdometerImagesFailed: 'Falha ao combinar imagens do hodômetro. Tente novamente mais tarde.',
- unableToSubmitReport: 'Não é possível enviar o relatório',
- allTransactionsPendingDescription: 'Você não pode enviar este relatório porque todas as transações estão pendentes. Pode levar alguns dias para serem lançadas.',
+ unableToSubmitReport: 'Não foi possível enviar o relatório',
+ allTransactionsPendingDescription: 'Você não pode enviar este relatório porque todas as transações estão pendentes. Elas podem levar alguns dias para serem lançadas.',
nonReimbursablePayment: 'Não é possível pagar via Expensify',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index b34e3200..1533c383 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1244,7 +1244,7 @@ const translations: TranslationDeepObject<typeof en> = {
receiptStatusText: '扫描期间只有你自己能看到这张收据。稍后再来查看,或立即输入详细信息。',
receiptScanningFailed: '收据扫描失败。请手动输入详细信息。',
transactionPendingDescription: '交易待处理。入账可能需要几天时间。',
- allTransactionsPendingNextStep: '所有交易均待处理。在入账之前,您无法提交此报告。这可能需要几天时间。',
+ allTransactionsPendingNextStep: '所有交易都在待处理状态。在入账之前,你无法提交此报表。这可能需要几天时间。',
companyInfo: '公司信息',
companyInfoDescription: '在您发送第一张发票之前,我们还需要一些详细信息。',
yourCompanyName: '您的公司名称',
@@ -1426,8 +1426,8 @@ const translations: TranslationDeepObject<typeof en> = {
manySplitsProvided: `允许的最大拆分数为 ${CONST.IOU.SPLITS_LIMIT}。`,
dateRangeExceedsMaxDays: `日期范围不能超过 ${CONST.IOU.SPLITS_LIMIT} 天。`,
stitchOdometerImagesFailed: '合并里程表图片失败。请稍后重试。',
- unableToSubmitReport: '无法提交报告',
- allTransactionsPendingDescription: '您无法提交此报告,因为所有交易均待处理。入账可能需要几天时间。',
+ unableToSubmitReport: '无法提交报表',
+ allTransactionsPendingDescription: '您无法提交此报表,因为所有交易都在待处理状态。它们可能需要几天时间才能入账。',
nonReimbursablePayment: '无法通过 Expensify 付款',
nonReimbursablePaymentDescription: (isMultiple?: boolean) =>
isMultiple ? '一个或多个所选报告没有可报销的费用。请再次检查费用,或手动将其标记为已支付。' : '该报告没有可报销的费用。请再次检查费用,或手动将其标记为已支付。',
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
The PR now shows the submit button for reports with only pending transactions (displaying an error modal on click), so the test should expect SUBMIT to be included in secondary actions. Co-authored-by: Sobit Neupane <sobitneupane@users.noreply.github.com>
|
Fixed the failing check: updated |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
Explanation of Change
When a report contains only pending Expensify Card transactions, the submit button was completely hidden across all action surfaces (report header, secondary dropdown, report preview card, and search page). This left users with no indication of why they couldn't submit.
This PR:
ReportPrimaryActionUtils,ReportSecondaryActionUtils,ReportPreviewActionUtils, andIOU/index.ts(canSubmitReport).MoneyReportHeaderandSubmitActionButton(report preview) explaining that submission is blocked because all transactions are pending.This matches OldDot behavior where the submit button is visible but clicking it shows an explanatory error.
Fixed Issues
$ #86491
PROPOSAL: #86491 (comment)
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Checks run
Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari