Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
28bd2ce
Add SetFeedReimbursable API command and action
youssef-lr Oct 15, 2026
eabe1cd
Add company card feed Reimbursable selection page and route
youssef-lr Oct 15, 2026
65a99ba
Add Reimbursable row to company card feed settings
youssef-lr Oct 15, 2026
f05ce6f
Add change log for company card feed Reimbursable setting
youssef-lr Oct 15, 2026
47e443f
Add non-English translations for company card feed Reimbursable setting
youssef-lr Oct 15, 2026
1a40c5a
Shorten Reimbursable route param type to satisfy max-lines
youssef-lr Oct 15, 2026
86922b1
Revert non-English translations for Reimbursable setting pending gene…
youssef-lr Oct 15, 2026
c7b54d9
Show and clear Reimbursable save errors on company card feed page
youssef-lr Oct 15, 2026
27b1d06
Remove manual memoization from company card Reimbursable setting
youssef-lr Oct 15, 2026
9037ef1
Centralize company card feed Reimbursable normalization in CardUtils
youssef-lr Oct 15, 2026
b04a019
Share selectable Reimbursable type and ignore unrecognized server values
youssef-lr Oct 15, 2026
ecbc392
Localize Reimbursable change log when previous value is missing
youssef-lr Oct 15, 2026
14ca9f1
Flatten Reimbursable page description Text
youssef-lr Oct 15, 2026
c6504e4
Add tests for Reimbursable feed save, optimistic and failure behavior
youssef-lr Oct 15, 2026
da0c76f
Remove double cast from Reimbursable unrecognized-value test
youssef-lr Oct 15, 2026
904d55d
Merge branch 'main' into app-103342-add-reimbursable-setting-company
youssef-lr Oct 16, 2026
da6e8b9
Keep local Reimbursable feed changes and managed card value on duplic…
youssef-lr Oct 18, 2026
a93b67d
Merge remote-tracking branch 'youssef-lr/app-103342-add-reimbursable-…
youssef-lr Oct 18, 2026
422fb2a
Make card feed errorFields partial
youssef-lr Oct 18, 2026
148aa23
Clarify comment
youssef-lr Oct 18, 2026
7fd9dcc
Clarify comments
youssef-lr Oct 18, 2026
18237d8
Merge branch 'main' into app-103342-add-reimbursable-setting-company
youssef-lr Oct 19, 2026
0e80620
Merge remote-tracking branch 'origin/main' into app-103342-add-reimbu…
youssef-lr Oct 19, 2026
afe5d92
Add company card reimbursable screen to relocated workspace param list
youssef-lr Oct 19, 2026
aeef729
Clarify imported reimbursable comment
youssef-lr Oct 19, 2026
bfe905e
Merge origin/main into add-reimbursable-setting and add missing trans…
youssef-lr Oct 22, 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
8 changes: 8 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2271,6 +2271,7 @@ const CONST = {
UNASSIGN_COMPANY_CARD: 'POLICYCHANGELOG_UNASSIGN_COMPANY_CARD',
UPDATE_CARD_FEED_LIABILITY: 'POLICYCHANGELOG_UPDATE_CARD_FEED_LIABILITY',
UPDATE_CARD_FEED_STATEMENT_PERIOD: 'POLICYCHANGELOG_UPDATE_CARD_FEED_STATEMENT_PERIOD',
UPDATE_CARD_FEED_REIMBURSABLE: 'POLICYCHANGELOG_UPDATE_CARD_FEED_REIMBURSABLE',
LEAVE_POLICY: 'POLICYCHANGELOG_LEAVE_POLICY',
CORPORATE_UPGRADE: 'POLICYCHANGELOG_CORPORATE_UPGRADE',
CORPORATE_FORCE_UPGRADE: 'POLICYCHANGELOG_CORPORATE_FORCE_UPGRADE',
Expand Down Expand Up @@ -5925,6 +5926,13 @@ const CONST = {
LAST_BUSINESS_DAY_OF_MONTH: 'LAST_BUSINESS_DAY_OF_MONTH',
CUSTOM_DAY_OF_MONTH: 'CUSTOM_DAY_OF_MONTH',
},
FEED_REIMBURSABLE: {
FORCE_YES: 'force_yes',
Comment thread
youssef-lr marked this conversation as resolved.
FORCE_NO: 'force_no',
DEFAULT_YES: 'default_yes',
DEFAULT_NO: 'default_no',
Comment thread
youssef-lr marked this conversation as resolved.
},
FEED_REIMBURSABLE_LEGACY_NONE: 'none',
CARD_NAME: {
CASH: '__CASH__',
},
Expand Down
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4089,6 +4089,10 @@ const ROUTES = {
route: 'workspaces/:policyID/company-cards/settings/statement-close-date',
getRoute: (policyID: string) => `workspaces/${policyID}/company-cards/settings/statement-close-date` as const,
},
WORKSPACE_COMPANY_CARDS_SETTINGS_REIMBURSABLE: {
route: 'workspaces/:policyID/company-cards/settings/reimbursable',
getRoute: (policyID: string) => `workspaces/${policyID}/company-cards/settings/reimbursable` as const,
},
WORKSPACE_RULES: {
route: 'workspaces/:policyID/rules',
/** @param tab preselects a Rules tab. The page otherwise restores the last one used. */
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ const SCREENS = {
COMPANY_CARDS_SETTINGS: 'Workspace_CompanyCards_Settings',
COMPANY_CARDS_SETTINGS_FEED_NAME: 'Workspace_CompanyCards_Settings_Feed_Name',
COMPANY_CARDS_SETTINGS_STATEMENT_CLOSE_DATE: 'Workspace_CompanyCards_Settings_Statement_Close_Date',
COMPANY_CARDS_SETTINGS_REIMBURSABLE: 'Workspace_CompanyCards_Settings_Reimbursable',
DYNAMIC_COMPANY_CARD_DETAILS: 'Dynamic_Workspace_CompanyCard_Details',
COMPANY_CARD_EDIT_CARD_NAME: 'Workspace_CompanyCard_Edit_Card_Name',
COMPANY_CARD_ADD_WORK_EMAIL: 'Workspace_CompanyCard_Add_Work_Email',
Expand Down
18 changes: 8 additions & 10 deletions src/components/CategoryPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,14 @@ function CategoryPicker({
});

const noneOption: OptionTree[] = shouldShowNoneOption
? getNoneOption(debouncedSearchValue, !selectedCategory, translate).map(
(option): OptionTree => ({
text: option.text,
keyForList: option.keyForList,
searchText: '',
tooltipText: option.text,
isDisabled: false,
isSelected: option.isSelected,
}),
)
? getNoneOption(debouncedSearchValue, !selectedCategory, translate).map((option): OptionTree => ({
text: option.text,
keyForList: option.keyForList,
searchText: '',
tooltipText: option.text,
isDisabled: false,
isSelected: option.isSelected,
}))
: [];
const noneOptionSection = {
title: '',
Expand Down
4 changes: 3 additions & 1 deletion src/languages/IntlStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ class IntlStore {
})
.catch((error: unknown) => {
if (localeSpan) {
endSpanWithAttributes(CONST.TELEMETRY.SPAN_LOCALE.TRANSLATIONS_LOAD, {[CONST.TELEMETRY.ATTRIBUTE_FAILED]: true});
endSpanWithAttributes(CONST.TELEMETRY.SPAN_LOCALE.TRANSLATIONS_LOAD, {
[CONST.TELEMETRY.ATTRIBUTE_FAILED]: true,
});
}

// Recovery is exhausted: the locale never resolves and the boot splash intentionally stays up —
Expand Down
491 changes: 402 additions & 89 deletions src/languages/de.ts

Large diffs are not rendered by default.

182 changes: 151 additions & 31 deletions src/languages/el.ts

Large diffs are not rendered by default.

40 changes: 35 additions & 5 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,10 @@ const translations = {
troubleshootBiometricsStatus: ({status}: {status?: string}) => `Biometrics (${status})`,
statusNeverRegistered: 'Never registered',
statusNotRegistered: 'Not registered',
statusRegisteredOtherDevice: () => ({one: 'Another device registered', other: 'Other devices registered'}),
statusRegisteredOtherDevice: () => ({
one: 'Another device registered',
other: 'Other devices registered',
}),
statusRegisteredThisDevice: 'Registered',
yourAttemptWasUnsuccessful: 'Your authentication attempt was unsuccessful.',
youCouldNotBeAuthenticated: 'You couldn’t be authenticated',
Expand Down Expand Up @@ -2555,9 +2558,18 @@ const translations = {
testingPreferences: 'Testing preferences',
server: 'Server',
servers: {
production: {label: 'Production', description: 'The live environment real users see'},
staging: {label: 'Staging', description: 'Mirror of production. Used for final validation'},
qa: {label: 'QA', description: 'Experimental environment used for testing'},
production: {
label: 'Production',
description: 'The live environment real users see',
},
staging: {
label: 'Staging',
description: 'Mirror of production. Used for final validation',
},
qa: {
label: 'QA',
description: 'Experimental environment used for testing',
},
},
serverPinnedDescription: 'This build always talks to one server, so it cannot be changed here.',
qaAuth: 'QA auth (Cloudflare)',
Expand Down Expand Up @@ -6888,6 +6900,18 @@ const translations = {
[CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_BUSINESS_DAY_OF_MONTH]: 'Last business day of the month',
[CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.CUSTOM_DAY_OF_MONTH]: 'Custom day of month',
},
reimbursable: {
title: 'Reimbursable',
description: 'Choose how card transactions should be created. New transactions will follow these rules.',
[CONST.COMPANY_CARDS.FEED_REIMBURSABLE.FORCE_YES]: 'Always reimbursable',
[`${CONST.COMPANY_CARDS.FEED_REIMBURSABLE.FORCE_YES}Description`]: 'Always paid back to employees',
[CONST.COMPANY_CARDS.FEED_REIMBURSABLE.FORCE_NO]: 'Always non-reimbursable',
[`${CONST.COMPANY_CARDS.FEED_REIMBURSABLE.FORCE_NO}Description`]: 'Never paid back to employees',
[CONST.COMPANY_CARDS.FEED_REIMBURSABLE.DEFAULT_YES]: 'Reimbursable',
[`${CONST.COMPANY_CARDS.FEED_REIMBURSABLE.DEFAULT_YES}Description`]: 'Most often paid back to employees',
[CONST.COMPANY_CARDS.FEED_REIMBURSABLE.DEFAULT_NO]: 'Non-reimbursable',
[`${CONST.COMPANY_CARDS.FEED_REIMBURSABLE.DEFAULT_NO}Description`]: 'Occasionally paid back to employees',
},
assign: 'Assign',
assignCard: 'Assign card',
findCompanyCard: 'Find company card',
Expand Down Expand Up @@ -9834,6 +9858,8 @@ const translations = {
updatedCardFeedLiability: (feedName: string, enabled: boolean) => `${enabled ? 'enabled' : 'disabled'} cardholders to delete card transactions for card feed "${feedName}"`,
updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
`changed card feed "${feedName}" statement period end day${newValue ? ` to "${newValue}"` : ''}${previousValue ? ` (previously "${previousValue}")` : ''}`,
updatedCardFeedReimbursable: (feedName: string, newValue?: string, previousValue?: string) =>
`changed card feed "${feedName}" reimbursable setting${newValue ? ` to "${newValue}"` : ''}${previousValue ? ` (previously "${previousValue}")` : ''}`,
agentRule: {
added: ({title, prompt}: {title: string; prompt: string}) => (title ? `added the agent rule "${title}": ${prompt}` : `added an agent rule: ${prompt}`),
updated: ({title, prompt}: {title: string; prompt: string}) => (title ? `updated the agent rule "${title}" to: ${prompt}` : `updated an agent rule to: ${prompt}`),
Expand Down Expand Up @@ -11517,7 +11543,11 @@ const translations = {
markAsCashToIgnore: 'Mark as cash to ignore and request payment.',
smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
if (missingFields.length > 0) {
const fieldNames: Record<string, string> = {merchant: 'merchant', date: 'date', amount: 'amount'};
const fieldNames: Record<string, string> = {
merchant: 'merchant',
date: 'date',
amount: 'amount',
};
const translated = missingFields.map((f) => fieldNames[f] ?? f);
let fieldList = '';
if (translated.length === 1) {
Expand Down
Loading
Loading