Skip to content
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

[Simplified Collect][Taxes] Create WorkspaceTaxesSettingsPage and subpages #38373

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
3 changes: 3 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ const CONST = {
INSTALLED: 'installed',
NOT_INSTALLED: 'not-installed',
},
TAX_RATES: {
NAME_MAX_LENGTH: 50,
filip-solecki marked this conversation as resolved.
Show resolved Hide resolved
},
PLATFORM: {
IOS: 'ios',
ANDROID: 'android',
Expand Down
3 changes: 3 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ const ONYXKEYS = {
WORKSPACE_DESCRIPTION_FORM_DRAFT: 'workspaceDescriptionFormDraft',
WORKSPACE_RATE_AND_UNIT_FORM: 'workspaceRateAndUnitForm',
WORKSPACE_RATE_AND_UNIT_FORM_DRAFT: 'workspaceRateAndUnitFormDraft',
WORKSPACE_TAX_CUSTOM_NAME: 'workspaceTaxCustomName',
WORKSPACE_TAX_CUSTOM_NAME_DRAFT: 'workspaceTaxCustomNameDraft',
CLOSE_ACCOUNT_FORM: 'closeAccount',
CLOSE_ACCOUNT_FORM_DRAFT: 'closeAccountDraft',
PROFILE_SETTINGS_FORM: 'profileSettingsForm',
Expand Down Expand Up @@ -420,6 +422,7 @@ type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FORM]: FormTypes.WorkspaceCategoryForm;
[ONYXKEYS.FORMS.WORKSPACE_TAG_CREATE_FORM]: FormTypes.WorkspaceTagCreateForm;
[ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM]: FormTypes.WorkspaceRateAndUnitForm;
[ONYXKEYS.FORMS.WORKSPACE_TAX_CUSTOM_NAME]: FormTypes.WorkspaceTaxCustomName;
[ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM]: FormTypes.CloseAccountForm;
[ONYXKEYS.FORMS.PROFILE_SETTINGS_FORM]: FormTypes.ProfileSettingsForm;
[ONYXKEYS.FORMS.DISPLAY_NAME_FORM]: FormTypes.DisplayNameForm;
Expand Down
16 changes: 16 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,22 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/taxes',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes` as const,
},
WORKSPACE_TAXES_SETTINGS: {
route: 'settings/workspaces/:policyID/taxes/settings',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes/settings` as const,
},
WORKSPACE_TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT: {
route: 'settings/workspaces/:policyID/taxes/settings/workspace-currency',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes/settings/workspace-currency` as const,
},
WORKSPACE_TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT: {
route: 'settings/workspaces/:policyID/taxes/settings/foreign-currency',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes/settings/foreign-currency` as const,
},
WORKSPACE_TAXES_SETTINGS_CUSTOM_TAX_NAME: {
route: 'settings/workspaces/:policyID/taxes/settings/tax-name',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes/settings/tax-name` as const,
},
WORKSPACE_MEMBER_DETAILS: {
route: 'settings/workspaces/:policyID/members/:accountID',
getRoute: (policyID: string, accountID: number, backTo?: string) => getUrlWithBackToParam(`settings/workspaces/${policyID}/members/${accountID}`, backTo),
Expand Down
4 changes: 4 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ const SCREENS = {
TAGS_SETTINGS: 'Tags_Settings',
TAGS_EDIT: 'Tags_Edit',
TAXES: 'Workspace_Taxes',
TAXES_SETTINGS: 'Workspace_Taxes_Settings',
TAXES_SETTINGS_CUSTOM_TAX_NAME: 'Workspace_Taxes_Settings_CustomTaxName',
TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT: 'Workspace_Taxes_Settings_WorkspaceCurrency',
TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT: 'Workspace_Taxes_Settings_ForeignCurrency',
TAG_CREATE: 'Tag_Create',
CURRENCY: 'Workspace_Profile_Currency',
WORKFLOWS: 'Workspace_Workflows',
Expand Down
74 changes: 29 additions & 45 deletions src/components/TaxPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React, {useMemo, useState} from 'react';
import React, {useState} from 'react';
import type {EdgeInsets} from 'react-native-safe-area-context';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import CONST from '@src/CONST';
import type {TaxRatesWithDefault} from '@src/types/onyx';
import OptionsSelector from './OptionsSelector';
import type {TaxRate, TaxRatesWithDefault} from '@src/types/onyx';
import SelectionList from './SelectionList';
import RadioListItem from './SelectionList/RadioListItem';
import type {ListItem} from './SelectionList/types';

type TaxPickerProps = {
/** Collection of tax rates attached to a policy */
taxRates: TaxRatesWithDefault;
taxRates?: TaxRatesWithDefault;

/** The selected tax rate of an expense */
selectedTaxRate?: string;
Expand All @@ -23,60 +23,44 @@ type TaxPickerProps = {
insets?: EdgeInsets;

/** Callback to fire when a tax is pressed */
onSubmit: () => void;
onSubmit: (tax: ListItem) => void;

/** Default key of selectedtax */
defaultTaxKey?: string;
};

function TaxPicker({selectedTaxRate = '', taxRates, insets, onSubmit}: TaxPickerProps) {
const styles = useThemeStyles();
function TaxPicker({selectedTaxRate = '', taxRates, insets, onSubmit, defaultTaxKey}: TaxPickerProps) {
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const [searchValue, setSearchValue] = useState('');

const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates.taxes);
const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD;
if (!taxRates) {
return;
}

const shouldShowTextInput = !isTaxRatesCountBelowThreshold;
const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates?.taxes);
const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD;

const selectedOptions = useMemo(() => {
if (!selectedTaxRate) {
return [];
}
const defaultSelectedTaxKey = defaultTaxKey ?? taxRates.defaultExternalID;

return [
{
name: selectedTaxRate,
enabled: true,
accountID: null,
},
];
}, [selectedTaxRate]);
const getModifiedName = (data: TaxRate, code: string) => `${data.name} (${data.value})${defaultSelectedTaxKey === code ? ` • ${translate('common.default')}` : ''}`;

const sections = useMemo(() => {
const {taxRatesOptions} = OptionsListUtils.getFilteredOptions({}, {}, [], searchValue, selectedOptions, [], false, false, false, {}, [], false, {}, [], false, false, true, taxRates);
return taxRatesOptions;
filip-solecki marked this conversation as resolved.
Show resolved Hide resolved
}, [taxRates, searchValue, selectedOptions]);
const shouldShowTextInput = !isTaxRatesCountBelowThreshold;

const selectedOptionKey = sections?.[0]?.data?.find((taxRate) => taxRate.searchText === selectedTaxRate)?.keyForList;
const section = Object.entries(taxRates.taxes ?? {}).map(([key, item]) => ({text: getModifiedName(item, key), keyForList: key}));
const selectedOptionKey = section.find((taxRate) => taxRate.text === selectedTaxRate)?.keyForList;

filip-solecki marked this conversation as resolved.
Show resolved Hide resolved
return (
<OptionsSelector
// @ts-expect-error TODO: Remove this once OptionsSelector (https://github.com/Expensify/App/issues/25125) is migrated to TypeScript.
contentContainerStyles={[{paddingBottom: StyleUtils.getSafeAreaMargins(insets).marginBottom}]}
optionHoveredStyle={styles.hoveredComponentBG}
sectionHeaderStyle={styles.mt5}
sections={sections}
selectedOptions={selectedOptions}
value={searchValue}
// Focus the first option when searching
focusedIndex={0}
initiallyFocusedOptionKey={selectedOptionKey}
textInputLabel={translate('common.search')}
boldStyle
highlightSelectedOptions
<SelectionList
ListItem={RadioListItem}
onSelectRow={onSubmit}
initiallyFocusedOptionKey={selectedOptionKey ?? ''}
sections={[{data: section}]}
containerStyle={{paddingBottom: StyleUtils.getSafeAreaMargins(insets).marginBottom}}
textInputLabel={shouldShowTextInput ? translate('common.search') : undefined}
isRowMultilineSupported
shouldShowTextInput={shouldShowTextInput}
textInputValue={searchValue}
onChangeText={setSearchValue}
onSelectRow={onSubmit}
/>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,7 @@ export default {
addRate: 'Add rate',
workspaceDefault: 'Workspace currency default',
foreignDefault: 'Foreign currency default',
customTaxName: 'Custom tax name',
filip-solecki marked this conversation as resolved.
Show resolved Hide resolved
},
emptyWorkspace: {
title: 'Create a workspace',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,7 @@ export default {
addRate: 'Añadir tasa',
workspaceDefault: 'Moneda por defecto del espacio de trabajo',
foreignDefault: 'Moneda extranjera por defecto',
customTaxName: 'Nombre del impuesto personalizado',
filip-solecki marked this conversation as resolved.
Show resolved Hide resolved
},
emptyWorkspace: {
title: 'Crea un espacio de trabajo',
Expand Down
6 changes: 6 additions & 0 deletions src/libs/API/parameters/SetPolicyCurrencyDefaultParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type SetPolicyCurrencyDefaultParams = {
policyID: string;
taxCode: string;
};

export default SetPolicyCurrencyDefaultParams;
6 changes: 6 additions & 0 deletions src/libs/API/parameters/SetPolicyCustomTaxNameParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type SetPolicyCustomTaxNameParams = {
policyID: string;
customTaxName: string;
};

export default SetPolicyCustomTaxNameParams;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type SetPolicyForeignCurrencyDefaultParams = {
policyID: string;
taxCode: string;
};

export default SetPolicyForeignCurrencyDefaultParams;
3 changes: 3 additions & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,6 @@ export type {default as OpenPolicyDistanceRatesPageParams} from './OpenPolicyDis
export type {default as OpenPolicyTaxesPageParams} from './OpenPolicyTaxesPageParams';
export type {default as OpenPolicyMoreFeaturesPageParams} from './OpenPolicyMoreFeaturesPageParams';
export type {default as CreatePolicyTagsParams} from './CreatePolicyTagsParams';
export type {default as SetPolicyCustomTaxNameParams} from './SetPolicyCustomTaxNameParams';
export type {default as SetPolicyForeignCurrencyDefaultParams} from './SetPolicyForeignCurrencyDefaultParams';
export type {default as SetPolicyCurrencyDefaultParams} from './SetPolicyCurrencyDefaultParams';
6 changes: 6 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ const WRITE_COMMANDS = {
ENABLE_POLICY_TAXES: 'EnablePolicyTaxes',
ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows',
ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields',
SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax',
SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax',
SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName',
JOIN_POLICY_VIA_INVITE_LINK: 'JoinWorkspaceViaInviteLink',
ACCEPT_JOIN_REQUEST: 'AcceptJoinRequest',
DECLINE_JOIN_REQUEST: 'DeclineJoinRequest',
Expand Down Expand Up @@ -346,6 +349,9 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams;
[WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams;
[WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams;
[WRITE_COMMANDS.SET_POLICY_TAXES_CURRENCY_DEFAULT]: Parameters.SetPolicyCurrencyDefaultParams;
[WRITE_COMMANDS.SET_POLICY_CUSTOM_TAX_NAME]: Parameters.SetPolicyCustomTaxNameParams;
[WRITE_COMMANDS.SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT]: Parameters.SetPolicyForeignCurrencyDefaultParams;
};

const READ_COMMANDS = {
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.TAGS_SETTINGS]: () => require('../../../pages/workspace/tags/WorkspaceTagsSettingsPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAGS_EDIT]: () => require('../../../pages/workspace/tags/WorkspaceEditTagsPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAG_CREATE]: () => require('../../../pages/workspace/tags/WorkspaceCreateTagPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_SETTINGS]: () => require('../../../pages/workspace/taxes/WorkspaceTaxesSettingsPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_SETTINGS_CUSTOM_TAX_NAME]: () => require('../../../pages/workspace/taxes/WorkspaceTaxesSettingsCustomTaxName').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT]: () => require('../../../pages/workspace/taxes/WorkspaceTaxesSettingsForeignCurrency').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT]: () => require('../../../pages/workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency').default as React.ComponentType,
[SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType,
[SCREENS.GET_ASSISTANCE]: () => require('../../../pages/GetAssistancePage').default as React.ComponentType,
[SCREENS.SETTINGS.TWO_FACTOR_AUTH]: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default as React.ComponentType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.WORKFLOWS_PAYER,
],
[SCREENS.WORKSPACE.TAGS]: [SCREENS.WORKSPACE.TAGS_SETTINGS, SCREENS.WORKSPACE.TAGS_EDIT, SCREENS.WORKSPACE.TAG_CREATE],
[SCREENS.WORKSPACE.TAXES]: [
SCREENS.WORKSPACE.TAXES_SETTINGS,
SCREENS.WORKSPACE.TAXES_SETTINGS_CUSTOM_TAX_NAME,
SCREENS.WORKSPACE.TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT,
SCREENS.WORKSPACE.TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT,
],
[SCREENS.WORKSPACE.CATEGORIES]: [SCREENS.WORKSPACE.CATEGORY_CREATE, SCREENS.WORKSPACE.CATEGORY_SETTINGS, SCREENS.WORKSPACE.CATEGORIES_SETTINGS, SCREENS.WORKSPACE.CATEGORY_EDIT],
};

Expand Down
12 changes: 12 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,18 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.TAG_CREATE]: {
path: ROUTES.WORKSPACE_TAG_CREATE.route,
},
[SCREENS.WORKSPACE.TAXES_SETTINGS]: {
path: ROUTES.WORKSPACE_TAXES_SETTINGS.route,
},
[SCREENS.WORKSPACE.TAXES_SETTINGS_CUSTOM_TAX_NAME]: {
path: ROUTES.WORKSPACE_TAXES_SETTINGS_CUSTOM_TAX_NAME.route,
},
[SCREENS.WORKSPACE.TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT]: {
path: ROUTES.WORKSPACE_TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT.route,
},
[SCREENS.WORKSPACE.TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT]: {
path: ROUTES.WORKSPACE_TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT.route,
},
[SCREENS.REIMBURSEMENT_ACCOUNT]: {
path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route,
exact: true,
Expand Down
12 changes: 12 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@ type SettingsNavigatorParamList = {
policyID: string;
tagName: string;
};
[SCREENS.WORKSPACE.TAXES_SETTINGS]: {
policyID: string;
};
[SCREENS.WORKSPACE.TAXES_SETTINGS_CUSTOM_TAX_NAME]: {
policyID: string;
};
[SCREENS.WORKSPACE.TAXES_SETTINGS_FOREIGN_CURRENCY_DEFAULT]: {
policyID: string;
};
[SCREENS.WORKSPACE.TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT]: {
policyID: string;
};
[SCREENS.WORKSPACE.MEMBER_DETAILS]: {
policyID: string;
accountID: string;
Expand Down
Loading
Loading