Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d265336
Add CodingRule type and update rules in Policy.ts
luacmartins Jan 26, 2026
80f3783
Add translations for merchant rules section
luacmartins Jan 26, 2026
fee9399
Create MerchantRulesSection component
luacmartins Jan 26, 2026
c0f919f
Add MerchantRulesSection to PolicyRulesPage
luacmartins Jan 26, 2026
8f99792
Update MerchantRulesSection to use new rule summary translations
luacmartins Jan 26, 2026
391cdbc
Lowercase subsequent rules in rule description
luacmartins Jan 26, 2026
d1259b7
update copy
luacmartins Jan 26, 2026
06b25cd
Add New feature badge to merchant rules section title
luacmartins Jan 26, 2026
87f6b5a
Ensure title uses dark text color
luacmartins Jan 26, 2026
d00f416
Make New feature badge smaller
luacmartins Jan 26, 2026
30a10b6
fix label colors
luacmartins Jan 26, 2026
c1bfa9d
Add 'Add merchant rule' button to MerchantRulesSection
luacmartins Jan 26, 2026
bef93e7
update rules styles
luacmartins Jan 26, 2026
da5a910
update more styles
luacmartins Jan 26, 2026
a40309f
Add badgeNewFeature style for compact new feature badges
luacmartins Jan 26, 2026
7d2e255
update menu item styles
luacmartins Jan 26, 2026
fd8f46c
update gap
luacmartins Jan 26, 2026
41c6f92
Remove mock data and use real policy codingRules
luacmartins Jan 26, 2026
e34e177
Only show MerchantRulesSection in development environment
luacmartins Jan 26, 2026
75da9dd
add dev beta
luacmartins Jan 26, 2026
a75f310
fix prettier
luacmartins Jan 26, 2026
9e9a1bd
fix spellcheck
luacmartins Jan 26, 2026
9c2f422
apply translations
luacmartins Jan 26, 2026
1d4729e
Perf: Hoist iterator-independent translations in MerchantRulesSection
luacmartins Jan 27, 2026
582dfd7
Decode category and clean tag names in MerchantRulesSection
luacmartins Jan 27, 2026
f7a39fe
Simplify date comparison in MerchantRulesSection sort
luacmartins Jan 27, 2026
3a24559
Fix eslint-disable comment format in Policy.ts
luacmartins Jan 27, 2026
7645ee7
fix linter
luacmartins Jan 27, 2026
2db82fb
fix eslint
luacmartins Jan 27, 2026
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
11 changes: 11 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Ursprünglicher Betrag',
insights: 'Einblicke',
duplicateExpense: 'Doppelte Ausgabe',
newFeature: 'Neue Funktion',
},
supportalNoAccess: {
title: 'Nicht so schnell',
Expand Down Expand Up @@ -6316,6 +6317,16 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard
title: 'Spesenrichtlinie',
cardSubtitle: 'Hier befindet sich die Spesenrichtlinie eures Teams, damit alle genau wissen, was abgedeckt ist.',
},
merchantRules: {
title: 'Händler',
subtitle: 'Legen Sie Händlerregeln fest, damit Ausgaben korrekt codiert ankommen und weniger Nachbearbeitung erfordern.',
addRule: 'Händlerregel hinzufügen',
ruleSummaryTitle: (merchantName: string) => `Wenn Händler „${merchantName}“ enthält`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Händler in „${merchantName}“ umbenennen`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Aktualisiere ${fieldName} zu „${fieldValue}“`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Als "${reimbursable ? 'erstattungsfähig' : 'nicht erstattungsfähig'}" markieren`,
ruleSummarySubtitleBillable: (billable: boolean) => `Als „${billable ? 'Abrechenbar' : 'nicht abrechenbar'}“ markieren`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ const translations = {
in: 'In',
optional: 'Optional',
new: 'New',
newFeature: 'New feature',
search: 'Search',
reports: 'Reports',
find: 'Find',
Expand Down Expand Up @@ -6165,6 +6166,16 @@ const translations = {
unlockFeatureEnableWorkflowsSubtitle: (featureName: string) => `Add ${featureName} to unlock this feature.`,
enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) => `Go to [more features](${moreFeaturesLink}) and enable ${featureName} to unlock this feature.`,
},
merchantRules: {
title: 'Merchant',
subtitle: 'Set the merchant rules so expenses arrive correctly coded and require less cleanup.',
addRule: 'Add merchant rule',
ruleSummaryTitle: (merchantName: string) => `If merchant contains "${merchantName}"`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Rename merchant to "${merchantName}"`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Update ${fieldName} to "${fieldValue}"`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Mark as "${reimbursable ? 'reimbursable' : 'non-reimbursable'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Mark as "${billable ? 'billable' : 'non-billable'}"`,
},
categoryRules: {
title: 'Category rules',
approver: 'Approver',
Expand Down
11 changes: 11 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const translations: TranslationDeepObject<typeof en> = {
in: 'En',
optional: 'Opcional',
new: 'Nuevo',
newFeature: 'Nueva función',
center: 'Centrar',
search: 'Buscar',
reports: 'Informes',
Expand Down Expand Up @@ -5940,6 +5941,16 @@ ${amount} para ${merchant} - ${date}`,
unlockFeatureEnableWorkflowsSubtitle: (featureName) => `Añade ${featureName} para desbloquear esta función.`,
enableFeatureSubtitle: (featureName, moreFeaturesLink) => `Ir a [más características](${moreFeaturesLink}) y habilita ${featureName} para desbloquear esta función.`,
},
merchantRules: {
title: 'Comerciante',
subtitle: 'Configura las reglas de comerciante para que los gastos lleguen correctamente codificados y requieran menos limpieza.',
addRule: 'Añadir regla de comerciante',
ruleSummaryTitle: (merchantName: string) => `Si el comerciante contiene "${merchantName}"`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Renombrar comerciante a "${merchantName}"`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Actualizar ${fieldName} a "${fieldValue}"`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Marcar como "${reimbursable ? 'reembolsable' : 'no reembolsable'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Marcar como "${billable ? 'facturable' : 'no facturable'}"`,
},
categoryRules: {
title: 'Reglas de categoría',
approver: 'Aprobador',
Expand Down
11 changes: 11 additions & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Montant d’origine',
insights: 'Analyses',
duplicateExpense: 'Note de frais en double',
newFeature: 'Nouvelle fonctionnalité',
},
supportalNoAccess: {
title: 'Pas si vite',
Expand Down Expand Up @@ -6327,6 +6328,16 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin
title: 'Politique de dépenses',
cardSubtitle: 'Voici l’endroit où se trouve la politique de dépenses de votre équipe, afin que tout le monde soit sur la même longueur d’onde concernant ce qui est couvert.',
},
merchantRules: {
title: 'Commerçant',
subtitle: 'Définissez les règles de marchand afin que les dépenses arrivent correctement codées et nécessitent moins de nettoyage.',
addRule: 'Ajouter une règle de commerçant',
ruleSummaryTitle: (merchantName: string) => `Si le commerçant contient « ${merchantName} »`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Renommer le marchand en « ${merchantName} »`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Mettre à jour ${fieldName} sur « ${fieldValue} »`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Marquer comme « ${reimbursable ? 'remboursable' : 'non remboursable'} »`,
ruleSummarySubtitleBillable: (billable: boolean) => `Marquer comme « ${billable ? 'facturable' : 'non facturable'} »`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Importo originale',
insights: 'Analisi',
duplicateExpense: 'Spesa duplicata',
newFeature: 'Nuova funzionalità',
},
supportalNoAccess: {
title: 'Non così in fretta',
Expand Down Expand Up @@ -6300,6 +6301,16 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori
title: 'Policy di spesa',
cardSubtitle: 'Qui è dove si trova la policy di spesa del tuo team, così tutti sono allineati su cosa è coperto.',
},
merchantRules: {
title: 'Esercente',
subtitle: 'Imposta le regole per gli esercenti in modo che le spese arrivino già codificate correttamente e richiedano meno correzioni.',
addRule: 'Aggiungi regola esercente',
ruleSummaryTitle: (merchantName: string) => `Se l’esercente contiene "${merchantName}"`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Rinomina esercente in "${merchantName}"`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Aggiorna ${fieldName} a "${fieldValue}"`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Segna come "${reimbursable ? 'rimborsabile' : 'non rimborsabile'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Contrassegna come "${billable ? 'fatturabile' : 'non fatturabile'}"`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: '元の金額',
insights: 'インサイト',
duplicateExpense: '重複した経費',
newFeature: '新機能',
},
supportalNoAccess: {
title: 'ちょっと待ってください',
Expand Down Expand Up @@ -6257,6 +6258,16 @@ ${reportName}
title: '経費ポリシー',
cardSubtitle: 'ここにはチームの経費ポリシーが保存されています。これにより、何が対象になるかについて全員が同じ認識を持てます。',
},
merchantRules: {
title: '加盟店',
subtitle: '取引先ルールを設定して、経費が正しくコード化された状態で届くようにし、後処理を最小限に抑えましょう。',
addRule: '店舗ルールを追加',
ruleSummaryTitle: (merchantName: string) => `もし取引先に「${merchantName}」が含まれている場合`,
ruleSummarySubtitleMerchant: (merchantName: string) => `支払先名を「${merchantName}」に変更`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `${fieldName} を「${fieldValue}」に更新`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `「${reimbursable ? '払い戻し対象' : '精算対象外'}」としてマーク`,
ruleSummarySubtitleBillable: (billable: boolean) => `「${billable ? '請求可能' : '請求対象外'}」としてマーク`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Oorspronkelijk bedrag',
insights: 'Inzichten',
duplicateExpense: 'Dubbele uitgave',
newFeature: 'Nieuwe functie',
},
supportalNoAccess: {
title: 'Niet zo snel',
Expand Down Expand Up @@ -6286,6 +6287,16 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten
title: 'Onkostennota-beleid',
cardSubtitle: 'Hier staat het onkostebeleid van je team, zodat iedereen goed weet wat wel en niet wordt vergoed.',
},
merchantRules: {
title: 'Handelaar',
subtitle: 'Stel de merchantregels zo in dat onkosten met de juiste codering binnenkomen en er minder nabewerking nodig is.',
addRule: 'Merchantregel toevoegen',
ruleSummaryTitle: (merchantName: string) => `Als handelaar "${merchantName}" bevat`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Naam handelaar wijzigen in "${merchantName}"`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Werk ${fieldName} bij naar "${fieldValue}"`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Markeren als "${reimbursable ? 'Vergoedbaar' : 'niet-vergoedbaar'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Markeren als "${billable ? 'factureerbaar' : 'niet-factureerbaar'}"`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Kwota pierwotna',
insights: 'Analizy',
duplicateExpense: 'Zduplikowany wydatek',
newFeature: 'Nowa funkcja',
},
supportalNoAccess: {
title: 'Nie tak szybko',
Expand Down Expand Up @@ -6280,6 +6281,16 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
title: 'Polityka wydatków',
cardSubtitle: 'Tutaj znajduje się polityka wydatków Twojego zespołu, aby wszyscy mieli jasność, co jest objęte.',
},
merchantRules: {
title: 'Sprzedawca',
subtitle: 'Skonfiguruj reguły dla sprzedawców, aby wydatki trafiały z poprawnym kodowaniem i wymagały mniej poprawek.',
addRule: 'Dodaj regułę sprzedawcy',
ruleSummaryTitle: (merchantName: string) => `Jeśli sprzedawca zawiera „${merchantName}”`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Zmień sprzedawcę na „${merchantName}”`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Zaktualizuj ${fieldName} na „${fieldValue}”`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Oznacz jako "${reimbursable ? 'kwalifikujący się do zwrotu kosztów' : 'niepodlegający zwrotowi'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Oznacz jako „${billable ? 'fakturowalne' : 'poza fakturą'}”`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: 'Valor original',
insights: 'Insights',
duplicateExpense: 'Despesa duplicada',
newFeature: 'Novo recurso',
},
supportalNoAccess: {
title: 'Não tão rápido',
Expand Down Expand Up @@ -6281,6 +6282,16 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe
title: 'Política de despesas',
cardSubtitle: 'É aqui que fica a política de despesas da sua equipe, para que todos estejam alinhados sobre o que é coberto.',
},
merchantRules: {
title: 'Estabelecimento',
subtitle: 'Defina as regras de comerciante para que as despesas cheguem corretamente categorizadas e exijam menos retrabalho.',
addRule: 'Adicionar regra de estabelecimento',
ruleSummaryTitle: (merchantName: string) => `Se o comerciante contiver "${merchantName}"`,
ruleSummarySubtitleMerchant: (merchantName: string) => `Renomear comerciante para "${merchantName}"`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Atualizar ${fieldName} para "${fieldValue}"`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Marcar como "${reimbursable ? 'reembolsável' : 'não reembolsável'}"`,
ruleSummarySubtitleBillable: (billable: boolean) => `Marcar como "${billable ? 'faturável' : 'não faturável'}"`,
},
},
planTypePage: {
planTypes: {
Expand Down
11 changes: 11 additions & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ const translations: TranslationDeepObject<typeof en> = {
originalAmount: '原始金额',
insights: '洞察',
duplicateExpense: '重复报销',
newFeature: '新功能',
},
supportalNoAccess: {
title: '先别急',
Expand Down Expand Up @@ -6147,6 +6148,16 @@ ${reportName}
title: '报销政策',
cardSubtitle: '这里是你们团队报销政策所在的位置,让所有人都能清楚了解哪些费用包含在内。',
},
merchantRules: {
title: '商家',
subtitle: '设置商家规则,让报销费用自动按正确科目归类,减少后期清理工作。',
addRule: '添加商家规则',
ruleSummaryTitle: (merchantName: string) => `如果商户包含“${merchantName}”`,
ruleSummarySubtitleMerchant: (merchantName: string) => `将商家重命名为 “${merchantName}”`,
ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `将 ${fieldName} 更新为“${fieldValue}”`,
ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `标记为“${reimbursable ? '可报销' : '不予报销'}”`,
ruleSummarySubtitleBillable: (billable: boolean) => `标记为“${billable ? '可计费' : '不可计费'}”`,
},
},
planTypePage: {
planTypes: {
Expand Down
Loading
Loading