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] Creating new taxes #37967

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b7cdc1b
add initial new tax page
kosmydel Mar 7, 2024
b351a28
add API command
kosmydel Mar 7, 2024
0f5eaad
add AmountSelectorModal
kosmydel Feb 27, 2024
3c3fc37
add TextPicker
kosmydel Feb 27, 2024
fd5029c
fix new pickers
kosmydel Mar 7, 2024
9e492c2
use pendingActions and errors in tax rates
kosmydel Mar 8, 2024
da6573f
draft
kosmydel Mar 8, 2024
4538c2a
Merge branch 'wave8/WorkspaceTaxesPage' into wave8/CreatingNewTaxes
kosmydel Mar 8, 2024
01a70b9
fix validation
kosmydel Mar 8, 2024
05f3a09
add saving drafts
kosmydel Mar 8, 2024
c0ead40
fix displaying tax rate in the list
kosmydel Mar 8, 2024
34cef2a
change type names
kosmydel Mar 11, 2024
d9574c2
Merge branch 'wave8/WorkspaceTaxesPage' into wave8/CreatingNewTaxes
kosmydel Mar 11, 2024
71d90f4
add spanish translation drafts
kosmydel Mar 11, 2024
4be8838
fix translation
kosmydel Mar 11, 2024
ae25dc5
Merge branch 'wave8/WorkspaceTaxesPage' into wave8/CreatingNewTaxes
kosmydel Mar 12, 2024
b6b6fd4
add auto focus
kosmydel Mar 12, 2024
6903cb5
add brickRoadIndicator
kosmydel Mar 12, 2024
d461d15
fix parameters
kosmydel Mar 12, 2024
4728b24
Merge branch 'wave8/WorkspaceTaxesPage' into wave8/CreatingNewTaxes
kosmydel Mar 13, 2024
7ba715e
fix rhp mapping
kosmydel Mar 13, 2024
c8ce6bb
clear drafts
kosmydel Mar 13, 2024
31d41b9
cleanup
kosmydel Mar 13, 2024
3cf7374
lint
kosmydel Mar 13, 2024
2747599
Merge branch 'main' into wave8/CreatingNewTaxes
kosmydel Mar 14, 2024
5ebdcb1
extract validation
kosmydel Mar 14, 2024
46da5b0
fix types
kosmydel Mar 14, 2024
5d6fb5e
adress review
kosmydel Mar 15, 2024
438c973
Fix
kosmydel Mar 15, 2024
e94dde9
Merge branch 'main' into wave8/CreatingNewTaxes
kosmydel Mar 15, 2024
3e62eb3
prevent creating duplicate id
kosmydel Mar 15, 2024
efd2a9b
cleanup
kosmydel Mar 15, 2024
58e682b
polish
kosmydel Mar 15, 2024
a0a1049
address review
kosmydel Mar 15, 2024
145c10b
Merge branch 'main' into wave8/CreatingNewTaxes
kosmydel Mar 18, 2024
bda7696
address review
kosmydel Mar 18, 2024
9671e6c
fix types
kosmydel Mar 18, 2024
082eeed
rename WorkspaceCreateTaxPage
kosmydel Mar 18, 2024
dc900fc
rename: getNextTaxCode
kosmydel Mar 18, 2024
ca68505
rename
kosmydel Mar 18, 2024
186a79b
rename TAX_CREATE screen
kosmydel Mar 18, 2024
79977f2
Update src/SCREENS.ts
kosmydel Mar 18, 2024
4b764ea
address review
kosmydel Mar 18, 2024
dd79adb
fix comments
kosmydel Mar 18, 2024
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
2 changes: 1 addition & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/members/:accountID/role-selection',
getRoute: (policyID: string, accountID: number, backTo?: string) => getUrlWithBackToParam(`settings/workspaces/${policyID}/members/${accountID}/role-selection`, backTo),
},
WORKSPACE_TAXES_NEW: {
WORKSPACE_TAX_CREATE: {
route: 'settings/workspaces/:policyID/taxes/new',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes/new` as const,
},
Expand Down
1 change: 1 addition & 0 deletions src/components/AmountPicker/AmountSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function AmountSelectorModal({value, description = '', onValueSelected, isVisibl
includePaddingTop={false}
includeSafeAreaPaddingBottom={false}
testID={AmountSelectorModal.displayName}
shouldEnableMaxHeight
>
<HeaderWithBackButton
title={description}
Expand Down
13 changes: 1 addition & 12 deletions src/components/AmountPicker/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import type {AmountFormProps} from '@components/AmountForm';
import type {MenuItemBaseProps} from '@components/MenuItem';
import type {ListItem} from '@components/SelectionList/types';
import type {MaybePhraseKey} from '@libs/Localize';

type AmountPickerListItem = ListItem & {
value?: string;
};

type AmountPickerItem = {
label?: string;
value?: string;
description?: string;
};

type AmountSelectorModalProps = {
/** Whether the modal is visible */
isVisible: boolean;
Expand Down Expand Up @@ -48,4 +37,4 @@ type AmountPickerProps = {
} & Pick<MenuItemBaseProps, 'rightLabel' | 'description'> &
AmountFormProps;

export type {AmountPickerItem, AmountSelectorModalProps, AmountPickerProps, AmountPickerListItem};
export type {AmountSelectorModalProps, AmountPickerProps};
2 changes: 2 additions & 0 deletions src/components/Form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type RoomNameInput from '@components/RoomNameInput';
import type SingleChoiceQuestion from '@components/SingleChoiceQuestion';
import type StatePicker from '@components/StatePicker';
import type TextInput from '@components/TextInput';
import type TextPicker from '@components/TextPicker';
import type ValuePicker from '@components/ValuePicker';
import type {MaybePhraseKey} from '@libs/Localize';
import type BusinessTypePicker from '@pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker';
Expand Down Expand Up @@ -45,6 +46,7 @@ type ValidInputs =
| typeof DatePicker
| typeof RadioButtons
| typeof AmountPicker
| typeof TextPicker
| typeof AddPlaidBankAccount;

type ValueTypeKey = 'string' | 'boolean' | 'date' | 'country';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function BaseTextInputWithCurrencySymbol(
const isCurrencySymbolLTR = CurrencyUtils.isCurrencySymbolLTR(selectedCurrencyCode);
const styles = useThemeStyles();

const currencySymbolButton = (
const currencySymbolButton = !hideCurrencySymbol && (
<CurrencySymbolButton
currencySymbol={currencySymbol ?? ''}
onCurrencyButtonPress={onCurrencyButtonPress}
Expand Down Expand Up @@ -69,7 +69,7 @@ function BaseTextInputWithCurrencySymbol(
if (isCurrencySymbolLTR) {
return (
<>
{!hideCurrencySymbol && currencySymbolButton}
{currencySymbolButton}
{amountTextInput}
{extraSymbol}
</>
Expand All @@ -79,7 +79,7 @@ function BaseTextInputWithCurrencySymbol(
return (
<>
{amountTextInput}
{!hideCurrencySymbol && currencySymbolButton}
{currencySymbolButton}
{extraSymbol}
</>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/TextPicker/TextSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function TextSelectorModal({value, description = '', onValueSelected, isVisible,
includePaddingTop={false}
includeSafeAreaPaddingBottom={false}
testID={TextSelectorModal.displayName}
shouldEnableMaxHeight
>
<HeaderWithBackButton
title={description}
Expand Down
13 changes: 1 addition & 12 deletions src/components/TextPicker/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import type {MenuItemBaseProps} from '@components/MenuItem';
import type {ListItem} from '@components/SelectionList/types';
import type {BaseTextInputProps} from '@components/TextInput/BaseTextInput/types';
import type {MaybePhraseKey} from '@libs/Localize';

type TextPickerListItem = ListItem & {
value?: string;
};

type TextPickerItem = {
label?: string;
value?: string;
description?: string;
};

type TextProps = Exclude<BaseTextInputProps, 'value' | 'onInputChange'>;

type TextSelectorModalProps = {
Expand Down Expand Up @@ -54,4 +43,4 @@ type TextPickerProps = {
} & Pick<MenuItemBaseProps, 'rightLabel' | 'description'> &
TextProps;

export type {TextPickerItem, TextSelectorModalProps, TextPickerProps, TextPickerListItem};
export type {TextSelectorModalProps, TextPickerProps};
2 changes: 1 addition & 1 deletion src/components/ValuePicker/ValueSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function ValueSelectorModal({items = [], selectedItem, label = '', isVisible, on
style={styles.pb0}
includePaddingTop={false}
includeSafeAreaPaddingBottom={false}
testID="ValueSelectorModal"
testID={ValueSelectorModal.displayName}
>
<HeaderWithBackButton
title={label}
Expand Down
4 changes: 2 additions & 2 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1858,8 +1858,8 @@ export default {
foreignDefault: 'Foreign currency default',
value: 'Value',
Copy link
Contributor

@DylanDylann DylanDylann Mar 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we confirm these translations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked once again for confirmation here.

errors: {
taxRatealreadyExists: 'A tax with this name already exists',
valuePercentageRange: 'Please enter a valid percentage between 0 and 100',
taxRateAlreadyExists: 'This tax name is already in use.',
valuePercentageRange: 'Please enter a valid percentage between 0 and 100.',
genericFailureMessage: 'An error occurred while updating the tax rate, please try again.',
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1882,7 +1882,7 @@ export default {
foreignDefault: 'Moneda extranjera por defecto',
value: 'Valor',
errors: {
taxRatealreadyExists: 'Ya existe un impuesto con este nombre',
taxRateAlreadyExists: 'Ya existe un impuesto con este nombre',
valuePercentageRange: 'Introduzca un porcentaje válido entre 0 y 100',
genericFailureMessage: 'Se produjo un error al actualizar el tipo impositivo, inténtelo nuevamente.',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.SETTINGS.EXIT_SURVEY.CONFIRM]: () => require('../../../pages/settings/ExitSurvey/ExitSurveyConfirmPage').default as React.ComponentType,
[SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default as React.ComponentType,
[SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_NEW]: () => require('../../../pages/workspace/taxes/WorkspaceNewTaxPage').default as React.ComponentType,
[SCREENS.WORKSPACE.TAXES_NEW]: () => require('../../../pages/workspace/taxes/WorkspaceCreateTaxPage').default as React.ComponentType,
});

const EnablePaymentsStackNavigator = createModalStackNavigator<EnablePaymentsNavigatorParamList>({
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
path: ROUTES.SETTINGS_EXIT_SURVEY_CONFIRM.route,
},
[SCREENS.WORKSPACE.TAXES_NEW]: {
path: ROUTES.WORKSPACE_TAXES_NEW.route,
path: ROUTES.WORKSPACE_TAX_CREATE.route,
},
},
},
Expand Down
19 changes: 9 additions & 10 deletions src/libs/actions/TaxRate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ function covertTaxNameToID(name: string) {
/**
* Get new tax ID
*/
function getNextTaxID(name: string, taxRates?: TaxRates): string {
function getNextTaxCode(name: string, taxRates?: TaxRates): string {
const newID = covertTaxNameToID(name);
if (!taxRates?.[newID]) {
return newID;
}

// If the tax ID already exists, we need to find a unique ID
let nextID = 1;
while (nextID < 100) {
const newNameCandidate = covertTaxNameToID(`${name}_${nextID}`);
if (!taxRates?.[newNameCandidate]) {
return newNameCandidate;
}
while (taxRates?.[covertTaxNameToID(`${name}_${nextID}`)]) {
nextID++;
}
throw new Error('Could not find a unique tax ID');
return covertTaxNameToID(`${name}_${nextID}`);
}

function createWorkspaceTax(policyID: string, taxRate: TaxRate) {
function createPolicyTax(policyID: string, taxRate: TaxRate) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We kept the create policy tags / categories in the policy.ts actions file. I think we should keep this in as well @luacmartins

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks for the link. I think we should then follow up with similar update for other Policy features. @luacmartins

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I think we can clean this up later and create an utils file for each of them. Created issue here

if (!taxRate.code) {
throw new Error('Tax code is required when creating a new tax rate.');
}

const onyxData: OnyxData = {
optimisticData: [
{
Expand All @@ -68,7 +68,6 @@ function createWorkspaceTax(policyID: string, taxRate: TaxRate) {
taxRates: {
taxes: {
[taxRate.code]: {
pendingAction: null,
errors: null,
},
},
Expand Down Expand Up @@ -127,4 +126,4 @@ function clearTaxRateError(policyID: string, taxID: string, pendingAction?: Pend
});
}

export {createWorkspaceTax, clearTaxRateError, getNextTaxID, getTaxValueWithPercentage};
export {createPolicyTax, clearTaxRateError, getNextTaxCode, getTaxValueWithPercentage};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Text from '@components/Text';
import TextPicker from '@components/TextPicker';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import {createWorkspaceTax, getNextTaxID, getTaxValueWithPercentage} from '@libs/actions/TaxRate';
import {createPolicyTax, getNextTaxCode, getTaxValueWithPercentage} from '@libs/actions/TaxRate';
import Navigation from '@libs/Navigation/Navigation';
import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
import * as ValidationUtils from '@libs/ValidationUtils';
Expand All @@ -25,14 +25,14 @@ import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/WorkspaceNewTaxForm';
import type {TaxRate} from '@src/types/onyx';

type WorkspaceNewTaxPageProps = WithPolicyAndFullscreenLoadingProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.TAXES_NEW>;
type WorkspaceCreateTaxPageProps = WithPolicyAndFullscreenLoadingProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.TAXES_NEW>;

function WorkspaceNewTaxPage({
function WorkspaceCreateTaxPage({
policy,
route: {
params: {policyID},
},
}: WorkspaceNewTaxPageProps) {
}: WorkspaceCreateTaxPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

Expand All @@ -47,7 +47,7 @@ function WorkspaceNewTaxPage({

const name = values[INPUT_IDS.NAME];
if (policy?.taxRates?.taxes && ValidationUtils.isExistingTaxName(name, policy.taxRates.taxes)) {
errors[INPUT_IDS.NAME] = 'workspace.taxes.errors.taxRatealreadyExists';
errors[INPUT_IDS.NAME] = 'workspace.taxes.errors.taxRateAlreadyExists';
}

return errors;
Expand All @@ -60,9 +60,9 @@ function WorkspaceNewTaxPage({
const taxRate = {
...values,
value: getTaxValueWithPercentage(value),
code: getNextTaxID(values[INPUT_IDS.NAME], policy?.taxRates?.taxes),
code: getNextTaxCode(values[INPUT_IDS.NAME], policy?.taxRates?.taxes),
} satisfies TaxRate;
createWorkspaceTax(policyID, taxRate);
createPolicyTax(policyID, taxRate);
Navigation.goBack();
},
[policy?.taxRates?.taxes, policyID],
Expand All @@ -72,8 +72,9 @@ function WorkspaceNewTaxPage({
<AdminPolicyAccessOrNotFoundWrapper policyID={policyID}>
<PaidPolicyAccessOrNotFoundWrapper policyID={policyID}>
<ScreenWrapper
testID={WorkspaceNewTaxPage.displayName}
testID={WorkspaceCreateTaxPage.displayName}
includeSafeAreaPaddingBottom={false}
style={[styles.defaultModalContainer]}
>
<View style={[styles.h100, styles.flex1, styles.justifyContentBetween]}>
<HeaderWithBackButton title={translate('workspace.taxes.addRate')} />
Expand Down Expand Up @@ -118,6 +119,6 @@ function WorkspaceNewTaxPage({
);
}

WorkspaceNewTaxPage.displayName = 'WorkspaceNewTaxPage';
WorkspaceCreateTaxPage.displayName = 'WorkspaceCreateTaxPage';

export default withPolicyAndFullscreenLoading(WorkspaceNewTaxPage);
export default withPolicyAndFullscreenLoading(WorkspaceCreateTaxPage);
2 changes: 1 addition & 1 deletion src/pages/workspace/taxes/WorkspaceTaxesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function WorkspaceTaxesPage({policy, route}: WorkspaceTaxesPageProps) {
<Button
medium
success
onPress={() => Navigation.navigate(ROUTES.WORKSPACE_TAXES_NEW.getRoute(route.params.policyID))}
onPress={() => Navigation.navigate(ROUTES.WORKSPACE_TAX_CREATE.getRoute(route.params.policyID))}
icon={Expensicons.Plus}
text={translate('workspace.taxes.addRate')}
style={[styles.mr3, isSmallScreenWidth && styles.w50]}
Expand Down
2 changes: 1 addition & 1 deletion src/types/onyx/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type TaxRate = OnyxCommon.OnyxValueWithOfflineFeedback<{
value: string;

/** The code associated with the tax rate. */
code: string;
code?: string;

/** This contains the tax name and tax value as one name */
modifiedName?: string;
Expand Down
Loading