Skip to content

Commit e7b31c3

Browse files
authored
Merge pull request #88915 from software-mansion-labs/feat/migrate-expense-limit-type-selector-modal-to-navigation
Migrate ExpenseLimitTypeSelectorModal to nav RHP
2 parents f824da8 + e909ff1 commit e7b31c3

10 files changed

Lines changed: 114 additions & 156 deletions

File tree

src/ROUTES.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ const DYNAMIC_ROUTES = {
9999
path: 'owner-selector',
100100
entryScreens: [],
101101
},
102+
EXPENSE_LIMIT_TYPE_SELECTOR: {
103+
path: 'expense-limit-type',
104+
entryScreens: [SCREENS.WORKSPACE.CATEGORY_FLAG_AMOUNTS_OVER],
105+
},
102106
REPORT_SETTINGS_NAME: {
103107
path: 'settings/name',
104108
entryScreens: [SCREENS.REPORT_DETAILS.ROOT],

src/SCREENS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ const SCREENS = {
784784
CATEGORY_SETTINGS: 'Category_Settings',
785785
CATEGORY_DEFAULT_TAX_RATE: 'Category_Default_Tax_Rate',
786786
CATEGORY_FLAG_AMOUNTS_OVER: 'Category_Flag_Amounts_Over',
787+
DYNAMIC_EXPENSE_LIMIT_TYPE_SELECTOR: 'Dynamic_Expense_Limit_Type_Selector',
787788
CATEGORY_DESCRIPTION_HINT: 'Category_Description_Hint',
788789
CATEGORY_APPROVER: 'Category_Approver',
789790
CATEGORY_REQUIRE_RECEIPTS_OVER: 'Category_Require_Receipts_Over',

src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
545545
[SCREENS.WORKSPACE.CATEGORY_GL_CODE]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryGLCodePage').default,
546546
[SCREENS.WORKSPACE.CATEGORY_DEFAULT_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryDefaultTaxRatePage').default,
547547
[SCREENS.WORKSPACE.CATEGORY_FLAG_AMOUNTS_OVER]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryFlagAmountsOverPage').default,
548+
[SCREENS.WORKSPACE.DYNAMIC_EXPENSE_LIMIT_TYPE_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/DynamicExpenseLimitTypeSelectorPage').default,
548549
[SCREENS.WORKSPACE.CATEGORY_DESCRIPTION_HINT]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryDescriptionHintPage').default,
549550
[SCREENS.WORKSPACE.CATEGORY_REQUIRE_RECEIPTS_OVER]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryRequireReceiptsOverPage').default,
550551
[SCREENS.WORKSPACE.CATEGORY_REQUIRE_ITEMIZED_RECEIPTS_OVER]: () =>

src/libs/Navigation/linkingConfig/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
10381038
[SCREENS.WORKSPACE.CATEGORY_FLAG_AMOUNTS_OVER]: {
10391039
path: ROUTES.WORKSPACE_CATEGORY_FLAG_AMOUNTS_OVER.route,
10401040
},
1041+
[SCREENS.WORKSPACE.DYNAMIC_EXPENSE_LIMIT_TYPE_SELECTOR]: DYNAMIC_ROUTES.EXPENSE_LIMIT_TYPE_SELECTOR.path,
10411042
[SCREENS.WORKSPACE.CATEGORY_DESCRIPTION_HINT]: {
10421043
path: ROUTES.WORKSPACE_CATEGORY_DESCRIPTION_HINT.route,
10431044
},

src/libs/Navigation/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ type SettingsNavigatorParamList = {
386386
policyID: string;
387387
categoryName: string;
388388
};
389+
[SCREENS.WORKSPACE.DYNAMIC_EXPENSE_LIMIT_TYPE_SELECTOR]: {
390+
policyID: string;
391+
categoryName: string;
392+
};
389393
[SCREENS.WORKSPACE.CATEGORY_DESCRIPTION_HINT]: {
390394
policyID: string;
391395
categoryName: string;

src/pages/workspace/categories/CategoryFlagAmountsOverPage.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import React, {useState} from 'react';
1+
import React, {useEffect} from 'react';
22
import {View} from 'react-native';
33
import AmountForm from '@components/AmountForm';
44
import FormProvider from '@components/Form/FormProvider';
55
import InputWrapper from '@components/Form/InputWrapper';
66
import HeaderWithBackButton from '@components/HeaderWithBackButton';
7+
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
78
import ScreenWrapper from '@components/ScreenWrapper';
89
import Text from '@components/Text';
910
import useAutoFocusInput from '@hooks/useAutoFocusInput';
@@ -12,20 +13,20 @@ import useLocalize from '@hooks/useLocalize';
1213
import useOnyx from '@hooks/useOnyx';
1314
import usePolicy from '@hooks/usePolicy';
1415
import useThemeStyles from '@hooks/useThemeStyles';
16+
import {clearDraftValues} from '@libs/actions/FormActions';
1517
import {getDecodedCategoryName} from '@libs/CategoryUtils';
1618
import {convertToFrontendAmountAsString} from '@libs/CurrencyUtils';
19+
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
1720
import Navigation from '@libs/Navigation/Navigation';
1821
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
1922
import type {SettingsNavigatorParamList} from '@navigation/types';
2023
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
2124
import {setPolicyCategoryMaxAmount} from '@userActions/Policy/Category';
2225
import CONST from '@src/CONST';
2326
import ONYXKEYS from '@src/ONYXKEYS';
24-
import ROUTES from '@src/ROUTES';
27+
import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
2528
import type SCREENS from '@src/SCREENS';
2629
import INPUT_IDS from '@src/types/form/WorkspaceCategoryFlagAmountsOverForm';
27-
import type {PolicyCategoryExpenseLimitType} from '@src/types/onyx/PolicyCategory';
28-
import ExpenseLimitTypeSelector from './ExpenseLimitTypeSelector/ExpenseLimitTypeSelector';
2930

3031
type EditCategoryPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORY_FLAG_AMOUNTS_OVER>;
3132

@@ -39,9 +40,16 @@ function CategoryFlagAmountsOverPage({
3940
const {translate} = useLocalize();
4041
const {getCurrencyDecimals} = useCurrencyListActions();
4142
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`);
42-
const [expenseLimitType, setExpenseLimitType] = useState<PolicyCategoryExpenseLimitType>(policyCategories?.[categoryName]?.expenseLimitType ?? CONST.POLICY.EXPENSE_LIMIT_TYPES.EXPENSE);
43+
const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FLAG_AMOUNTS_OVER_FORM_DRAFT);
44+
const expenseLimitType = formDraft?.expenseLimitType ?? policyCategories?.[categoryName]?.expenseLimitType ?? CONST.POLICY.EXPENSE_LIMIT_TYPES.EXPENSE;
4345
const decodedCategoryName = getDecodedCategoryName(categoryName);
4446

47+
useEffect(() => {
48+
return () => {
49+
clearDraftValues(ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FLAG_AMOUNTS_OVER_FORM);
50+
};
51+
}, []);
52+
4553
const {inputCallbackRef} = useAutoFocusInput();
4654

4755
const policyCategoryMaxExpenseAmount = policyCategories?.[categoryName]?.maxExpenseAmount;
@@ -59,7 +67,7 @@ function CategoryFlagAmountsOverPage({
5967
>
6068
<ScreenWrapper
6169
enableEdgeToEdgeBottomSafeAreaPadding
62-
style={[styles.defaultModalContainer]}
70+
style={styles.defaultModalContainer}
6371
testID="CategoryFlagAmountsOverPage"
6472
shouldEnableMaxHeight
6573
>
@@ -94,11 +102,12 @@ function CategoryFlagAmountsOverPage({
94102
/>
95103
<Text style={[styles.mutedTextLabel, styles.mt2]}>{translate('workspace.rules.categoryRules.flagAmountsOverSubtitle')}</Text>
96104
</View>
97-
<ExpenseLimitTypeSelector
98-
label={translate('common.type')}
99-
defaultValue={expenseLimitType}
105+
<MenuItemWithTopDescription
106+
shouldShowRightIcon
107+
title={translate(`workspace.rules.categoryRules.expenseLimitTypes.${expenseLimitType}`)}
108+
description={translate('common.type')}
109+
onPress={() => Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.EXPENSE_LIMIT_TYPE_SELECTOR.path))}
100110
wrapperStyle={[styles.ph5, styles.mt3]}
101-
setNewExpenseLimitType={setExpenseLimitType}
102111
/>
103112
</FormProvider>
104113
</ScreenWrapper>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react';
2+
import HeaderWithBackButton from '@components/HeaderWithBackButton';
3+
import ScreenWrapper from '@components/ScreenWrapper';
4+
import SelectionList from '@components/SelectionList';
5+
import RadioListItem from '@components/SelectionList/ListItem/RadioListItem';
6+
import useDynamicBackPath from '@hooks/useDynamicBackPath';
7+
import useLocalize from '@hooks/useLocalize';
8+
import useOnyx from '@hooks/useOnyx';
9+
import useThemeStyles from '@hooks/useThemeStyles';
10+
import {setDraftValues} from '@libs/actions/FormActions';
11+
import Navigation from '@libs/Navigation/Navigation';
12+
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
13+
import type {SettingsNavigatorParamList} from '@navigation/types';
14+
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
15+
import CONST from '@src/CONST';
16+
import ONYXKEYS from '@src/ONYXKEYS';
17+
import {DYNAMIC_ROUTES} from '@src/ROUTES';
18+
import type SCREENS from '@src/SCREENS';
19+
import INPUT_IDS from '@src/types/form/WorkspaceCategoryFlagAmountsOverForm';
20+
import type {PolicyCategoryExpenseLimitType} from '@src/types/onyx/PolicyCategory';
21+
22+
type DynamicExpenseLimitTypeSelectorPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.DYNAMIC_EXPENSE_LIMIT_TYPE_SELECTOR>;
23+
24+
function DynamicExpenseLimitTypeSelectorPage({
25+
route: {
26+
params: {policyID, categoryName},
27+
},
28+
}: DynamicExpenseLimitTypeSelectorPageProps) {
29+
const styles = useThemeStyles();
30+
const {translate} = useLocalize();
31+
const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EXPENSE_LIMIT_TYPE_SELECTOR.path);
32+
const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FLAG_AMOUNTS_OVER_FORM_DRAFT);
33+
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`);
34+
35+
const currentExpenseLimitType = formDraft?.expenseLimitType ?? policyCategories?.[categoryName]?.expenseLimitType ?? CONST.POLICY.EXPENSE_LIMIT_TYPES.EXPENSE;
36+
37+
const expenseLimitTypes = Object.values(CONST.POLICY.EXPENSE_LIMIT_TYPES).map((value) => ({
38+
value,
39+
text: translate(`workspace.rules.categoryRules.expenseLimitTypes.${value}`),
40+
alternateText: translate(`workspace.rules.categoryRules.expenseLimitTypes.${value}Subtitle`),
41+
keyForList: value,
42+
isSelected: currentExpenseLimitType === value,
43+
}));
44+
45+
const onSelectRow = (item: {value: PolicyCategoryExpenseLimitType}) => {
46+
setDraftValues(ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FLAG_AMOUNTS_OVER_FORM, {
47+
[INPUT_IDS.EXPENSE_LIMIT_TYPE]: item.value,
48+
});
49+
Navigation.goBack(backPath);
50+
};
51+
52+
return (
53+
<AccessOrNotFoundWrapper
54+
accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
55+
policyID={policyID}
56+
featureName={CONST.POLICY.MORE_FEATURES.ARE_CATEGORIES_ENABLED}
57+
>
58+
<ScreenWrapper
59+
style={styles.pb0}
60+
enableEdgeToEdgeBottomSafeAreaPadding
61+
testID="DynamicExpenseLimitTypeSelectorPage"
62+
>
63+
<HeaderWithBackButton
64+
title={translate('common.type')}
65+
onBackButtonPress={() => Navigation.goBack(backPath)}
66+
/>
67+
<SelectionList
68+
data={expenseLimitTypes}
69+
ListItem={RadioListItem}
70+
onSelectRow={onSelectRow}
71+
shouldSingleExecuteRowSelect
72+
style={{containerStyle: [styles.pt3]}}
73+
initiallyFocusedItemKey={currentExpenseLimitType}
74+
alternateNumberOfSupportedLines={3}
75+
addBottomSafeAreaPadding
76+
/>
77+
</ScreenWrapper>
78+
</AccessOrNotFoundWrapper>
79+
);
80+
}
81+
82+
export default DynamicExpenseLimitTypeSelectorPage;

src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelector.tsx

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/pages/workspace/categories/ExpenseLimitTypeSelector/ExpenseLimitTypeSelectorModal.tsx

Lines changed: 0 additions & 75 deletions
This file was deleted.

src/types/form/WorkspaceCategoryFlagAmountsOverForm.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {ValueOf} from 'type-fest';
2+
import type {PolicyCategoryExpenseLimitType} from '@src/types/onyx/PolicyCategory';
23
import type Form from './Form';
34

45
const INPUT_IDS = {
@@ -12,7 +13,7 @@ type WorkspaceCategoryFlagAmountsOverForm = Form<
1213
InputID,
1314
{
1415
[INPUT_IDS.MAX_EXPENSE_AMOUNT]: string;
15-
[INPUT_IDS.EXPENSE_LIMIT_TYPE]: string;
16+
[INPUT_IDS.EXPENSE_LIMIT_TYPE]: PolicyCategoryExpenseLimitType;
1617
}
1718
>;
1819

0 commit comments

Comments
 (0)