[HOLD] Show error when card limit is $0 during physical card ordering#87410
[HOLD] Show error when card limit is $0 during physical card ordering#87410Beamanator wants to merge 1 commit intomainfrom
Conversation
…onalDetailsAndShipExpensifyCards When Auth returns a 400 for an invalid card limit, the app now surfaces a meaningful error message via failureData writing to ONYXKEYS.PRIVATE_PERSONAL_DETAILS.errors, which MissingPersonalDetailsMagicCodePage already displays as a validateError. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@ahmedGaber93 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
🦜 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 fc74a72e..cafe2ceb 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2413,7 +2413,8 @@ ${amount} für ${merchant} – ${date}`,
changeYourPin: 'Geben Sie eine neue PIN für Ihre Karte ein.',
confirmYourChangedPin: 'Bestätigen Sie Ihre neue PIN.',
pinMustBeFourDigits: 'Die PIN muss genau 4 Ziffern lang sein.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit:
+ 'Ihr Kartenlimit beträgt 0 $. Bitte bitten Sie Ihre Workspace-Administratorin bzw. Ihren Workspace-Administrator, ein Limit größer als 0 festzulegen, und versuchen Sie es dann erneut.',
invalidPin: 'Bitte wählen Sie eine sicherere PIN.',
pinMismatch: 'PINs stimmen nicht überein. Bitte versuchen Sie es erneut.',
revealPin: 'PIN anzeigen',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 45d89479..fe81b041 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2420,7 +2420,7 @@ ${amount} pour ${merchant} - ${date}`,
changeYourPin: 'Saisissez un nouveau code PIN pour votre carte.',
confirmYourChangedPin: 'Confirmez votre nouveau code PIN.',
pinMustBeFourDigits: 'Le code PIN doit comporter exactement 4 chiffres.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'Votre limite de carte est de 0 $. Veuillez demander à l’administrateur de votre espace de travail de définir une limite de dépense non nulle, puis réessayez.',
invalidPin: 'Veuillez choisir un code PIN plus sécurisé.',
pinMismatch: 'Les codes PIN ne correspondent pas. Veuillez réessayer.',
revealPin: 'Afficher le code PIN',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index d77cbed5..00a42cd3 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1096,15 +1096,12 @@ const translations: TranslationDeepObject<typeof en> = {
if (!added && !updated) {
return 'Nessuna categoria è stata aggiunta o aggiornata.';
}
-
if (added && updated) {
return `${added} ${added === 1 ? 'categoria aggiunta' : 'categorie aggiunte'}, ${updated} ${updated === 1 ? 'categoria aggiornata' : 'categorie aggiornate'}.`;
}
-
if (added) {
return added === 1 ? 'È stata aggiunta 1 categoria.' : `Sono state aggiunte ${added} categorie.`;
}
-
return updated === 1 ? 'È stata aggiornata 1 categoria.' : `Sono state aggiornate ${updated} categorie.`;
},
importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
@@ -2413,7 +2410,7 @@ ${amount} per ${merchant} - ${date}`,
changeYourPin: 'Inserisci un nuovo PIN per la tua carta.',
confirmYourChangedPin: 'Conferma il tuo nuovo PIN.',
pinMustBeFourDigits: 'Il PIN deve essere composto da esattamente 4 cifre.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'Il limite della tua carta è 0 $. Chiedi all’amministratore dello spazio di lavoro di impostare un limite di spesa diverso da zero, quindi riprova.',
invalidPin: 'Scegli un PIN più sicuro.',
pinMismatch: 'I PIN non corrispondono. Riprova.',
revealPin: 'Mostra PIN',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index f8e8ee49..6cd4223d 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1079,15 +1079,12 @@ const translations: TranslationDeepObject<typeof en> = {
if (!added && !updated) {
return 'カテゴリーは追加も更新もされていません。';
}
-
if (added && updated) {
return `${added}件のカテゴリーを追加し、${updated}件のカテゴリーを更新しました。`;
}
-
if (added) {
return added === 1 ? 'カテゴリーを1件追加しました。' : `${added}件のカテゴリーを追加しました。`;
}
-
return updated === 1 ? 'カテゴリーを1件更新しました。' : `${updated}件のカテゴリーを更新しました。`;
},
importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
@@ -2388,7 +2385,7 @@ ${date} の ${merchant} への ${amount}`,
changeYourPin: 'カードの新しい暗証番号を入力してください。',
confirmYourChangedPin: '新しい暗証番号を確認してください。',
pinMustBeFourDigits: 'PIN は 4 桁で入力してください。',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'お客さまのカード利用限度額は $0 です。ワークスペース管理者に、0 より大きい利用限度額の設定を依頼してから、もう一度お試しください。',
invalidPin: 'より安全な暗証番号を選択してください。',
pinMismatch: 'PIN が一致しません。もう一度お試しください。',
revealPin: 'PIN を表示',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index db9456f8..18027fe4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1095,15 +1095,12 @@ const translations: TranslationDeepObject<typeof en> = {
if (!added && !updated) {
return 'Er zijn geen categorieën toegevoegd of bijgewerkt.';
}
-
if (added && updated) {
return `${added} ${added === 1 ? 'categorie' : 'categorieën'} toegevoegd, ${updated} ${updated === 1 ? 'categorie' : 'categorieën'} bijgewerkt.`;
}
-
if (added) {
return added === 1 ? '1 categorie is toegevoegd.' : `${added} categorieën zijn toegevoegd.`;
}
-
return updated === 1 ? '1 categorie is bijgewerkt.' : `${updated} categorieën zijn bijgewerkt.`;
},
importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
@@ -2411,7 +2408,7 @@ ${amount} voor ${merchant} - ${date}`,
changeYourPin: 'Voer een nieuwe pincode in voor je kaart.',
confirmYourChangedPin: 'Bevestig je nieuwe pincode.',
pinMustBeFourDigits: 'Pincode moet precies 4 cijfers bevatten.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'Je kaartlimiet is $0. Vraag je workspace-beheerder om een bestedingslimiet hoger dan nul in te stellen en probeer het daarna opnieuw.',
invalidPin: 'Kies alsjeblieft een veiligere pincode.',
pinMismatch: 'Pincodes komen niet overeen. Probeer het opnieuw.',
revealPin: 'Pincode weergeven',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 258e3a6c..b521f45f 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1096,15 +1096,12 @@ const translations: TranslationDeepObject<typeof en> = {
if (!added && !updated) {
return 'Nie dodano ani nie zaktualizowano żadnych kategorii.';
}
-
if (added && updated) {
return `Dodano ${added} ${added === 1 ? 'kategorię' : 'kategorie'}, zaktualizowano ${updated} ${updated === 1 ? 'kategorię' : 'kategorie'}.`;
}
-
if (added) {
return added === 1 ? 'Dodano 1 kategorię.' : `Dodano ${added} kategorie.`;
}
-
return updated === 1 ? 'Zaktualizowano 1 kategorię.' : `Zaktualizowano ${updated} kategorie.`;
},
importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) => (transactions > 1 ? `Dodano ${transactions} transakcji.` : 'Dodano 1 transakcję.'),
@@ -2406,7 +2403,7 @@ ${amount} dla ${merchant} - ${date}`,
changeYourPin: 'Wprowadź nowy PIN do swojej karty.',
confirmYourChangedPin: 'Potwierdź swój nowy PIN.',
pinMustBeFourDigits: 'PIN musi mieć dokładnie 4 cyfry.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'Limit twojej karty wynosi 0 USD. Poproś administratora przestrzeni roboczej o ustawienie niezerowego limitu wydatków, a następnie spróbuj ponownie.',
invalidPin: 'Wybierz proszę bardziej bezpieczny PIN.',
pinMismatch: 'Kody PIN nie są takie same. Spróbuj ponownie.',
revealPin: 'Pokaż PIN',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index df29e99a..24d8cd6a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1094,15 +1094,12 @@ const translations: TranslationDeepObject<typeof en> = {
if (!added && !updated) {
return 'Nenhuma categoria foi adicionada ou atualizada.';
}
-
if (added && updated) {
return `${added} ${added === 1 ? 'categoria' : 'categorias'} adicionada${added === 1 ? '' : 's'}, ${updated} ${updated === 1 ? 'categoria' : 'categorias'} atualizada${updated === 1 ? '' : 's'}.`;
}
-
if (added) {
return added === 1 ? '1 categoria foi adicionada.' : `${added} categorias foram adicionadas.`;
}
-
return updated === 1 ? '1 categoria foi atualizada.' : `${updated} categorias foram atualizadas.`;
},
importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
@@ -2404,7 +2401,7 @@ ${amount} para ${merchant} - ${date}`,
changeYourPin: 'Digite um novo PIN para o seu cartão.',
confirmYourChangedPin: 'Confirme seu novo PIN.',
pinMustBeFourDigits: 'O PIN deve ter exatamente 4 dígitos.',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: 'O limite do seu cartão é de US$ 0. Peça ao administrador do seu workspace para definir um limite de gastos diferente de zero e tente novamente.',
invalidPin: 'Escolha um PIN mais seguro.',
pinMismatch: 'Os PINs não coincidem. Tente novamente.',
revealPin: 'Revelar PIN',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index b14a0109..44344e85 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2336,7 +2336,7 @@ ${amount},商户:${merchant} - 日期:${date}`,
changeYourPin: '为您的银行卡输入新 PIN 码。',
confirmYourChangedPin: '确认您的新 PIN。',
pinMustBeFourDigits: 'PIN 必须正好为 4 位数字。',
- invalidCardLimit: 'Your card limit is $0. Please ask your workspace admin to set a non-zero spending limit, then try again.',
+ invalidCardLimit: '您的卡片额度为 $0。请联系您的工作区管理员设置一个非零消费额度,然后重试。',
invalidPin: '请选择一个更安全的 PIN。',
pinMismatch: 'PIN 不匹配。请重试。',
revealPin: '显示 PIN',
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59a2ff6fdc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| onyxMethod: Onyx.METHOD.MERGE, | ||
| key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, | ||
| value: { | ||
| errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('cardPage.invalidCardLimit'), |
There was a problem hiding this comment.
Restrict card-limit error to invalid-limit responses
failureData now always writes cardPage.invalidCardLimit, but applyHTTPSOnyxUpdates() applies request.failureData for every non-200 response code, not just the invalid-limit case. That means unrelated failures in SetPersonalDetailsAndShipExpensifyCards (e.g., transient server/network errors or other backend validation failures) will incorrectly tell users their card limit is $0, masking the real issue and sending them to the wrong remediation path.
Useful? React with 👍 / 👎.
Explanation of Change
When a user attempts to order a physical Expensify card via
SetPersonalDetailsAndShipExpensifyCardsand the card has an invalid (zero) limit, the Auth backend currently silently swallows the"400 Card has an invalid limit"error and returns 200 OK. A companion Auth PR (fix the silent swallow) properly returns a 400 in this case.This PR adds the frontend defense-in-depth:
failureDatainupdatePersonalDetailsAndShipExpensifyCardsthat writes toONYXKEYS.PRIVATE_PERSONAL_DETAILS.errors, and a new translation keycardPage.invalidCardLimitwith a user-friendly message. TheMissingPersonalDetailsMagicCodePagealready readsprivateDetailsErrorsand displays it as avalidateError— no structural UI changes needed.Note: This PR should be held and merged after/with the companion Auth fix that makes the backend return a proper 400 for invalid card limits.
Fixed Issues
$ https://github.com/Expensify/Expensify/issues/598396
PROPOSAL:
Tests
Offline tests
N/A — this error is only surfaced via an API response; offline behavior is unchanged (the API call never fires while offline).
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.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari