-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Add a duplicate warning to prevent accidental conflicting rules #80847
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add translations for the duplicate merchant rule warning modal in all supported languages (en, es, de, fr, it, ja, nl, pl, pt-BR, zh-hans).
When saving a merchant rule, check if a rule with the same merchant name and match type (contains/exact) already exists. If so, show a confirmation modal asking the user if they want to save anyway. - Add checkForDuplicateRule function to detect duplicates - Show ConfirmModal with "Similar merchant rule already exists" title - Allow user to proceed with "Save anyway" or cancel - Exclude current rule when editing to avoid false positives
🦜 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 6ba4fc9f..d5b0f2f6 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6410,7 +6410,7 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard
matchTypeExact: 'Exakte Übereinstimmung',
expensesExactlyMatching: 'Für Ausgaben mit genau folgender Übereinstimmung:',
duplicateRuleTitle: 'Eine ähnliche Händlerregel existiert bereits',
- duplicateRulePrompt: (merchantName: string) => `Möchten Sie eine neue Regel für „${merchantName}" speichern, obwohl Sie bereits eine bestehende haben?`,
+ duplicateRulePrompt: (merchantName: string) => `Möchten Sie eine neue Regel für „${merchantName}“ speichern, obwohl Sie bereits eine vorhandene haben?`,
saveAnyway: 'Trotzdem speichern',
},
},
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 899983a5..43c112a4 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6420,8 +6420,8 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin
matchTypeContains: 'Contient',
matchTypeExact: 'Correspond exactement',
expensesExactlyMatching: 'Pour les dépenses correspondant exactement :',
- duplicateRuleTitle: 'Une règle commerçant similaire existe déjà',
- duplicateRulePrompt: (merchantName: string) => `Voulez-vous enregistrer une nouvelle règle pour « ${merchantName} » même si vous en avez déjà une ?`,
+ duplicateRuleTitle: 'Une règle de commerçant similaire existe déjà',
+ duplicateRulePrompt: (merchantName: string) => `Voulez-vous enregistrer une nouvelle règle pour « ${merchantName} » même si vous en avez déjà une existante ?`,
saveAnyway: 'Enregistrer quand même',
},
},
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 9ca7c23d..6945dc44 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6391,7 +6391,7 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori
matchTypeContains: 'Contiene',
matchTypeExact: 'Corrisponde esattamente',
expensesExactlyMatching: 'Per le spese che corrispondono esattamente:',
- duplicateRuleTitle: 'Esiste già una regola esercente simile',
+ duplicateRuleTitle: 'Esiste già una regola simile per questo commerciante',
duplicateRulePrompt: (merchantName: string) => `Vuoi salvare una nuova regola per "${merchantName}" anche se ne hai già una esistente?`,
saveAnyway: 'Salva comunque',
},
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 32ac47e4..fc980246 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6346,8 +6346,8 @@ ${reportName}
matchTypeContains: '含む',
matchTypeExact: '完全一致',
expensesExactlyMatching: '以下と完全一致する経費について:',
- duplicateRuleTitle: '類似の取引先ルールが既に存在します',
- duplicateRulePrompt: (merchantName: string) => `既存のルールがあるにもかかわらず、「${merchantName}」の新しいルールを保存しますか?`,
+ duplicateRuleTitle: '同じような支払先ルールがすでに存在します',
+ duplicateRulePrompt: (merchantName: string) => `既に既存のルールがありますが、「${merchantName}」用に新しいルールを保存しますか?`,
saveAnyway: 'それでも保存',
},
},
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index dffd4583..9d30706f 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6379,8 +6379,8 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten
matchTypeContains: 'Bevat',
matchTypeExact: 'Komt exact overeen',
expensesExactlyMatching: 'Voor uitgaven die exact overeenkomen met:',
- duplicateRuleTitle: 'Er bestaat al een vergelijkbare handelaarsregel',
- duplicateRulePrompt: (merchantName: string) => `Wilt u een nieuwe regel opslaan voor "${merchantName}" hoewel u al een bestaande heeft?`,
+ duplicateRuleTitle: 'Soortgelijke regel voor dezelfde handelaar bestaat al',
+ duplicateRulePrompt: (merchantName: string) => `Wilt je een nieuwe regel voor "${merchantName}" opslaan, ook al heb je al een bestaande?`,
saveAnyway: 'Toch opslaan',
},
},
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 378a93af..a3b0502f 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6372,7 +6372,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
matchTypeExact: 'Dokładne dopasowanie',
expensesExactlyMatching: 'Dla wydatków dokładnie pasujących:',
duplicateRuleTitle: 'Podobna reguła sprzedawcy już istnieje',
- duplicateRulePrompt: (merchantName: string) => `Czy chcesz zapisać nową regułę dla „${merchantName}", mimo że masz już istniejącą?`,
+ duplicateRulePrompt: (merchantName: string) => `Czy chcesz zapisać nową regułę dla „${merchantName}”, mimo że masz już istniejącą?`,
saveAnyway: 'Zapisz mimo to',
},
},
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 76eea0c0..a52416a5 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6371,8 +6371,8 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe
matchTypeContains: 'Contém',
matchTypeExact: 'Corresponde exatamente',
expensesExactlyMatching: 'Para despesas que correspondem exatamente:',
- duplicateRuleTitle: 'Já existe uma regra de comerciante semelhante',
- duplicateRulePrompt: (merchantName: string) => `Você deseja salvar uma nova regra para "${merchantName}" mesmo já tendo uma existente?`,
+ duplicateRuleTitle: 'Já existe uma regra semelhante para este comerciante',
+ duplicateRulePrompt: (merchantName: string) => `Você quer salvar uma nova regra para "${merchantName}", mesmo já tendo uma existente?`,
saveAnyway: 'Salvar mesmo assim',
},
},
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 04836288..256fd795 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6236,9 +6236,9 @@ ${reportName}
matchTypeContains: '包含',
matchTypeExact: '完全匹配',
expensesExactlyMatching: '对于完全匹配以下条件的报销:',
- duplicateRuleTitle: '已存在类似的商家规则',
- duplicateRulePrompt: (merchantName: string) => `您想为「${merchantName}」保存一个新规则,即使您已有一个现有规则吗?`,
- saveAnyway: '仍然保存',
+ duplicateRuleTitle: '类似的商家规则已存在',
+ duplicateRulePrompt: (merchantName: string) => `即使您已经有一个现有规则,是否仍要为“${merchantName}”保存新规则?`,
+ saveAnyway: '仍要保存',
},
},
planTypePage: {
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
|
@DylanDylann @JS00001 One of you needs to 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] |
src/pages/workspace/rules/MerchantRules/MerchantRulePageBase.tsx
Outdated
Show resolved
Hide resolved
|
@codex review |
|
Codex Review: Didn't find any major issues. What shall we delve into next? ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
src/pages/workspace/rules/MerchantRules/MerchantRulePageBase.tsx
Outdated
Show resolved
Hide resolved
src/pages/workspace/rules/MerchantRules/MerchantRulePageBase.tsx
Outdated
Show resolved
Hide resolved
src/pages/workspace/rules/MerchantRules/MerchantRulePageBase.tsx
Outdated
Show resolved
Hide resolved
Replace declarative ConfirmModal components with the useConfirmModal hook for a cleaner imperative approach. This removes the need for modal visibility state variables and simplifies the component. Changes: - Replace ConfirmModal imports with useConfirmModal hook - Remove isDeleteModalVisible and isDuplicateWarningVisible state - Use showConfirmModal() with promise chain for delete confirmation - Use showConfirmModal() with promise chain for duplicate warning - Remove ConfirmModal JSX from render
React Compiler automatically memoizes functions, making manual useCallback wrappers unnecessary. Remove useCallback from checkForDuplicateRule and saveRule functions.
|
Addressed comments |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppandroid.movAndroid: mWeb ChromeiOS: HybridAppios.moviOS: mWeb SafariMacOS: Chrome / Safariweb.mov |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 9.3.11-16 🚀
|
Explanation of Change
Adds a duplicate rule warning
Fixed Issues
$ #80526
Tests
Pre-condition: rules are enabled in the workspace
Workspace > Rules > MerchantAdd merchant ruleand create a new rule for merchantExpensifyAdd merchant ruleand create a new rule for merchantExpensifyagainCanceldismisses the modal and takes you back to the rule editorSave anywaysaves the new ruleOffline tests
N/A
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand 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
Screen.Recording.2026-01-28.at.8.23.48.PM.mov
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari