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

fix: categorize all expense switch is not disabled #39036

Merged
merged 13 commits into from
Apr 3, 2024
64 changes: 49 additions & 15 deletions src/libs/actions/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import getIsNarrowLayout from '@libs/getIsNarrowLayout';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import * as NumberUtils from '@libs/NumberUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PhoneNumber from '@libs/PhoneNumber';
import * as PolicyUtils from '@libs/PolicyUtils';
Expand Down Expand Up @@ -2854,27 +2855,29 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string

function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Record<string, {name: string; enabled: boolean}>) {
const policyCategories = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {};
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
const optimisticPolicyCategoriesData = {
...Object.keys(categoriesToUpdate).reduce<PolicyCategories>((acc, key) => {
acc[key] = {
...policyCategories[key],
...categoriesToUpdate[key],
errors: null,
pendingFields: {
enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
};

return acc;
}, {}),
};
const shouldDisableRequiresCategory = !OptionsListUtils.hasEnabledOptions({...policyCategories, ...optimisticPolicyCategoriesData});
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
...Object.keys(categoriesToUpdate).reduce<PolicyCategories>((acc, key) => {
acc[key] = {
...policyCategories[key],
...categoriesToUpdate[key],
errors: null,
pendingFields: {
enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
};

return acc;
}, {}),
},
value: optimisticPolicyCategoriesData,
},
],
successData: [
Expand Down Expand Up @@ -2920,6 +2923,37 @@ function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Recor
},
],
};
if (shouldDisableRequiresCategory) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we do the same for deleteWorkspaceCategories?

function deleteWorkspaceCategories(policyID: string, categoryNamesToDelete: string[]) {

Screen.Recording.2024-04-02.at.9.55.11.at.night.mov

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 updated to do the same when deleting category

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice catch!

onyxData.optimisticData?.push({
tienifr marked this conversation as resolved.
Show resolved Hide resolved
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: false,
pendingFields: {
requiresCategory: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
});
onyxData.successData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingFields: {
requiresCategory: null,
},
},
});
onyxData.failureData?.push({
tienifr marked this conversation as resolved.
Show resolved Hide resolved
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: policy?.requiresCategory,
pendingFields: {
requiresCategory: null,
},
},
});
}

const parameters = {
policyID,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ScreenWrapper from '@components/ScreenWrapper';
Expand All @@ -9,23 +11,32 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import {setWorkspaceRequiresCategory} from '@libs/actions/Policy';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper';
import FeatureEnabledAccessOrNotFoundWrapper from '@pages/workspace/FeatureEnabledAccessOrNotFoundWrapper';
import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';

type WorkspaceCategoriesSettingsPageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORIES_SETTINGS>;
type WorkspaceCategoriesSettingsPageOnyxProps = {
/** Collection of categories attached to a policy */
policyCategories: OnyxEntry<OnyxTypes.PolicyCategories>;
};

function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPageProps) {
type WorkspaceCategoriesSettingsPageProps = WorkspaceCategoriesSettingsPageOnyxProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORIES_SETTINGS>;

function WorkspaceCategoriesSettingsPage({route, policyCategories}: WorkspaceCategoriesSettingsPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

const updateWorkspaceRequiresCategory = (value: boolean) => {
setWorkspaceRequiresCategory(route.params.policyID, value);
};

const policyCategoriesCount = OptionsListUtils.getEnabledCategoriesCount(policyCategories ?? {});
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use OptionsListUtils.hasEnabledOptions too? I think that might be slightly better since it short-circuits the loop if it finds an enabled option.

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 updated to use OptionsListUtils.hasEnabledOptions instead

return (
<AdminPolicyAccessOrNotFoundWrapper policyID={route.params.policyID}>
<PaidPolicyAccessOrNotFoundWrapper policyID={route.params.policyID}>
Expand Down Expand Up @@ -53,7 +64,7 @@ function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPag
isOn={policy?.requiresCategory ?? false}
accessibilityLabel={translate('workspace.categories.requiresCategory')}
onToggle={updateWorkspaceRequiresCategory}
disabled={!policy?.areCategoriesEnabled}
disabled={!policy?.areCategoriesEnabled || policyCategoriesCount === 0}
/>
</View>
</View>
Expand All @@ -69,4 +80,8 @@ function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPag

WorkspaceCategoriesSettingsPage.displayName = 'WorkspaceCategoriesSettingsPage';

export default WorkspaceCategoriesSettingsPage;
export default withOnyx<WorkspaceCategoriesSettingsPageProps, WorkspaceCategoriesSettingsPageOnyxProps>({
policyCategories: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like we're back at it again 🙂 #37508 (comment)

Copy link
Contributor Author

@tienifr tienifr Apr 2, 2024

Choose a reason for hiding this comment

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

@getusha

Yeah. Previously, I said that:

It's much less performant since we need to connect to the entire policyCategories in Onyx. And anywhere we use such are categories enabled logic, there'll be this overhead and duplicated logic.

Meanwhile we can just use areCategoriesEnabled which is an existing field designed for this very purpose (more details #37508 (comment)). There's no overhead since the places that need this use case already have the policy object passed in.

It is because we can use areCategoriesEnabled in this case. But now, we only turn off the requiresCategories, so I think to address the issue, we still need to subscribe the policyCategories

key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${route.params.policyID}`,
},
})(WorkspaceCategoriesSettingsPage);
Loading