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

Update RequestStepCategory to add Empty and Loading states for category list #41344

Merged
Show file tree
Hide file tree
Changes from 7 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
29 changes: 25 additions & 4 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,27 @@ const ROUTES = {
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
},
SETTINGS_CATEGORIES_ROOT: {
route: 'settings/:policyID/categories',
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/categories`, backTo),
},
SETTINGS_CATEGORY_SETTINGS: {
route: 'settings/:policyID/categories/:categoryName',
getRoute: (policyID: string, categoryName: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/categories/${encodeURIComponent(categoryName)}`, backTo),
},
SETTINGS_CATEGORIES_SETTINGS: {
route: 'settings/:policyID/categories/settings',
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/categories/settings`, backTo),
},
SETTINGS_CATEGORY_CREATE: {
route: 'settings/:policyID/categories/new',
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/categories/new`, backTo),
},
SETTINGS_CATEGORY_EDIT: {
route: 'settings/:policyID/categories/:categoryName/edit',
getRoute: (policyID: string, categoryName: string, backTo = '') =>
getUrlWithBackToParam(`settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/edit`, backTo),
},
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
MONEY_REQUEST_STEP_CURRENCY: {
route: ':action/:iouType/currency/:transactionID/:reportID/:pageIndex?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, pageIndex = '', currency = '', backTo = '') =>
Expand Down Expand Up @@ -640,10 +661,6 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/categories/settings',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories/settings` as const,
},
WORKSPACE_MORE_FEATURES: {
route: 'settings/workspaces/:policyID/more-features',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/more-features` as const,
},
WORKSPACE_CATEGORY_CREATE: {
route: 'settings/workspaces/:policyID/categories/new',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories/new` as const,
Expand All @@ -652,6 +669,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/categories/:categoryName/edit',
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/edit` as const,
},
WORKSPACE_MORE_FEATURES: {
route: 'settings/workspaces/:policyID/more-features',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/more-features` as const,
},
WORKSPACE_TAGS: {
route: 'settings/workspaces/:policyID/tags',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/tags` as const,
Expand Down
9 changes: 9 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const SCREENS = {
PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold',
TRAVEL: 'Travel',
SEARCH_REPORT: 'SearchReport',
SETTINGS_CATEGORIES: 'SettingsCategories',
},
ONBOARDING_MODAL: {
ONBOARDING: 'Onboarding',
Expand Down Expand Up @@ -183,6 +184,14 @@ const SCREENS = {
ENABLE_PAYMENTS: 'IOU_Send_Enable_Payments',
},

SETTINGS_CATEGORIES: {
SETTINGS_CATEGORY_SETTINGS: 'Settings_Category_Settings',
SETTINGS_CATEGORIES_SETTINGS: 'Settings_Categories_Settings',
SETTINGS_CATEGORY_CREATE: 'Settings_Category_Create',
SETTINGS_CATEGORY_EDIT: 'Settings_Category_Edit',
SETTINGS_CATEGORIES_ROOT: 'Settings_Categories',
},

REPORT_SETTINGS: {
ROOT: 'Report_Settings_Root',
ROOM_NAME: 'Report_Settings_Room_Name',
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,7 @@ export default {
createFailureMessage: 'An error occurred while creating the category, please try again.',
addCategory: 'Add category',
editCategory: 'Edit category',
editCategories: 'Edit categories',
categoryRequiredError: 'Category name is required.',
existingCategoryError: 'A category with this name already exists.',
invalidCategoryName: 'Invalid category name.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,7 @@ export default {
createFailureMessage: 'Se ha producido un error al intentar crear la categoría. Por favor, inténtalo más tarde.',
addCategory: 'Añadir categoría',
editCategory: 'Editar categoría',
editCategories: 'Editar categorías',
categoryRequiredError: 'Lo nombre de la categoría es obligatorio.',
existingCategoryError: 'Ya existe una categoría con este nombre.',
invalidCategoryName: 'Lo nombre de la categoría es invalido.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
[SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE]: () => require('@pages/iou/request/step/IOURequestStepDistanceRate').default as React.ComponentType,
[SCREENS.MONEY_REQUEST.STEP_MERCHANT]: () => require('../../../../pages/iou/request/step/IOURequestStepMerchant').default as React.ComponentType,
[SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS]: () => require('../../../../pages/iou/request/step/IOURequestStepParticipants').default as React.ComponentType,
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_ROOT]: () => require('../../../../pages/workspace/categories/WorkspaceCategoriesPage').default as React.ComponentType,
[SCREENS.MONEY_REQUEST.STEP_SCAN]: () => require('../../../../pages/iou/request/step/IOURequestStepScan').default as React.ComponentType,
[SCREENS.MONEY_REQUEST.STEP_TAG]: () => require('../../../../pages/iou/request/step/IOURequestStepTag').default as React.ComponentType,
[SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: () => require('../../../../pages/iou/request/step/IOURequestStepWaypoint').default as React.ComponentType,
Expand Down Expand Up @@ -137,6 +138,13 @@ const ReportDescriptionModalStackNavigator = createModalStackNavigator<ReportDes
[SCREENS.REPORT_DESCRIPTION_ROOT]: () => require('../../../../pages/ReportDescriptionPage').default as React.ComponentType,
});

const CategoriesModalStackNavigator = createModalStackNavigator({
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_SETTINGS]: () => require('../../../../pages/workspace/categories/WorkspaceCategoriesSettingsPage').default as React.ComponentType,
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_CREATE]: () => require('../../../../pages/workspace/categories/CreateCategoryPage').default as React.ComponentType,
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_EDIT]: () => require('../../../../pages/workspace/categories/EditCategoryPage').default as React.ComponentType,
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_SETTINGS]: () => require('../../../../pages/workspace/categories/CategorySettingsPage').default as React.ComponentType,
});

const ReportParticipantsModalStackNavigator = createModalStackNavigator<ParticipantsNavigatorParamList>({
[SCREENS.REPORT_PARTICIPANTS.ROOT]: () => require('../../../../pages/ReportParticipantsPage').default as React.ComponentType,
[SCREENS.REPORT_PARTICIPANTS.INVITE]: () => require('../../../../pages/InviteReportParticipantsPage').default as React.ComponentType,
Expand Down Expand Up @@ -385,6 +393,7 @@ export {
ChatFinderModalStackNavigator,
SettingsModalStackNavigator,
SignInModalStackNavigator,
CategoriesModalStackNavigator,
SplitDetailsModalStackNavigator,
TaskModalStackNavigator,
WalletStatementStackNavigator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) {
name={SCREENS.RIGHT_MODAL.REPORT_DESCRIPTION}
component={ModalStackNavigators.ReportDescriptionModalStackNavigator}
/>
<Stack.Screen
name={SCREENS.RIGHT_MODAL.SETTINGS_CATEGORIES}
component={ModalStackNavigators.CategoriesModalStackNavigator}
/>
<Stack.Screen
name={SCREENS.RIGHT_MODAL.PARTICIPANTS}
component={ModalStackNavigators.ReportParticipantsModalStackNavigator}
Expand Down
17 changes: 17 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,22 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
},
},
},
[SCREENS.RIGHT_MODAL.SETTINGS_CATEGORIES]: {
screens: {
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_SETTINGS]: {
path: ROUTES.SETTINGS_CATEGORY_SETTINGS.route,
},
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_SETTINGS]: {
path: ROUTES.SETTINGS_CATEGORIES_SETTINGS.route,
},
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_CREATE]: {
path: ROUTES.SETTINGS_CATEGORY_CREATE.route,
},
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORY_EDIT]: {
path: ROUTES.SETTINGS_CATEGORY_EDIT.route,
},
},
},
[SCREENS.RIGHT_MODAL.REPORT_DESCRIPTION]: {
screens: {
[SCREENS.REPORT_DESCRIPTION_ROOT]: ROUTES.REPORT_DESCRIPTION.route,
Expand Down Expand Up @@ -617,6 +633,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
},
},
},
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_ROOT]: ROUTES.SETTINGS_CATEGORIES_ROOT.route,
[SCREENS.MONEY_REQUEST.STEP_SEND_FROM]: ROUTES.MONEY_REQUEST_STEP_SEND_FROM.route,
[SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route,
[SCREENS.MONEY_REQUEST.STEP_CATEGORY]: ROUTES.MONEY_REQUEST_STEP_CATEGORY.route,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/types.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it weird we don't have any of the new SCREENS.SETTINGS_CATEGORIES listed in this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry
Didn't notice the comment
It's not really necessary
Since we already have types for the current CATEGORIES screens
Which have the same typing as for new ones

Original file line number Diff line number Diff line change
Expand Up @@ -184,17 +184,21 @@ type SettingsNavigatorParamList = {
};
[SCREENS.WORKSPACE.CATEGORY_CREATE]: {
policyID: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.CATEGORY_EDIT]: {
policyID: string;
categoryName: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.CATEGORY_SETTINGS]: {
policyID: string;
categoryName: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: {
policyID: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.TAG_CREATE]: {
policyID: string;
Expand Down Expand Up @@ -695,6 +699,7 @@ type RightModalNavigatorParamList = {
[SCREENS.SETTINGS.SHARE_CODE]: undefined;
[SCREENS.RIGHT_MODAL.REPORT_DETAILS]: NavigatorScreenParams<ReportDetailsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.REPORT_SETTINGS]: NavigatorScreenParams<ReportSettingsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.SETTINGS_CATEGORIES]: NavigatorScreenParams<SettingsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.REPORT_DESCRIPTION]: NavigatorScreenParams<ReportDescriptionNavigatorParamList>;
[SCREENS.RIGHT_MODAL.PARTICIPANTS]: NavigatorScreenParams<ParticipantsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.ROOM_MEMBERS]: NavigatorScreenParams<RoomMembersNavigatorParamList>;
Expand Down Expand Up @@ -758,6 +763,7 @@ type WorkspacesCentralPaneNavigatorParamList = {
};
[SCREENS.WORKSPACE.CATEGORIES]: {
policyID: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.MORE_FEATURES]: {
policyID: string;
Expand Down
65 changes: 57 additions & 8 deletions src/pages/iou/request/step/IOURequestStepCategory.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import lodashIsEmpty from 'lodash/isEmpty';
import React, {useEffect} from 'react';
import {ActivityIndicator, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import BlockingView from '@components/BlockingViews/BlockingView';
import Button from '@components/Button';
import CategoryPicker from '@components/CategoryPicker';
import FixedFooter from '@components/FixedFooter';
import * as Illustrations from '@components/Icon/Illustrations';
import type {ListItem} from '@components/SelectionList/types';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import variables from '@styles/variables';
import * as IOU from '@userActions/IOU';
import * as PolicyActions from '@userActions/Policy';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -63,6 +70,7 @@ function IOURequestStepCategory({
session,
}: IOURequestStepCategoryProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();
const isEditing = action === CONST.IOU.ACTION.EDIT;
const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT;
Expand All @@ -78,7 +86,7 @@ function IOURequestStepCategory({
const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT;
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction);
// eslint-disable-next-line rulesdir/no-negated-variables
Beamanator marked this conversation as resolved.
Show resolved Hide resolved
const shouldShowNotFoundPage = !shouldShowCategory || (isEditing && (isSplitBill ? !canEditSplitBill : !ReportUtils.canEditMoneyRequest(reportAction)));
const shouldShowNotFoundPage = isEditing && (isSplitBill ? !canEditSplitBill : !ReportUtils.canEditMoneyRequest(reportAction));

const fetchData = () => {
if (policy && policyCategories) {
Expand All @@ -87,7 +95,9 @@ function IOURequestStepCategory({

PolicyActions.openDraftWorkspaceRequest(report?.policyID ?? '');
};
useNetwork({onReconnect: fetchData});
const {isOffline} = useNetwork({onReconnect: fetchData});
const isLoading = !isOffline && policyCategories === undefined;
const shouldShowEmptyState = !isLoading && !shouldShowCategory;

useEffect(() => {
fetchData();
Expand Down Expand Up @@ -137,12 +147,51 @@ function IOURequestStepCategory({
testID={IOURequestStepCategory.displayName}
includeSafeAreaPaddingBottom={false}
>
<Text style={[styles.ph5, styles.pv3]}>{translate('iou.categorySelection')}</Text>
<CategoryPicker
selectedCategory={transactionCategory}
policyID={report?.policyID ?? ''}
onSubmit={updateCategory}
/>
{isLoading && (
<ActivityIndicator
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
style={[styles.flex1]}
color={theme.spinner}
/>
)}
{shouldShowEmptyState && (
<View style={[styles.flex1]}>
<BlockingView
icon={Illustrations.EmptyStateExpenses}
iconWidth={variables.modalTopIconWidth}
Copy link
Contributor

Choose a reason for hiding this comment

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

Coming from #43064. This caused a regression where the empty folder icon was not centred. This is because the width and height values used here are incorrect for the icon used.

iconHeight={variables.modalTopIconHeight}
title={translate('workspace.categories.emptyCategories.title')}
subtitle={translate('workspace.categories.emptyCategories.subtitle')}
/>
<FixedFooter style={[styles.mtAuto, styles.pt5]}>
<Button
large
success
style={[styles.w100]}
onPress={() =>
Navigation.navigate(
ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(
policy?.id ?? '',
ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, report?.reportID ?? '', backTo, reportActionID),
),
)
}
text={translate('workspace.categories.editCategories')}
pressOnEnter
/>
</FixedFooter>
</View>
)}
{!shouldShowEmptyState && !isLoading && (
<>
<Text style={[styles.ph5, styles.pv3]}>{translate('iou.categorySelection')}</Text>
<CategoryPicker
selectedCategory={transactionCategory}
policyID={report?.policyID ?? ''}
onSubmit={updateCategory}
/>
</>
)}
</StepScreenWrapper>
);
}
Expand Down
4 changes: 1 addition & 3 deletions src/pages/workspace/categories/CategoryForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -58,9 +57,8 @@ function CategoryForm({onSubmit, policyCategories, categoryName, validateEdit}:

const submit = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FORM>) => {
onSubmit(values);
Keyboard.dismiss();
Navigation.dismissModal();
onSubmit(values);
},
[onSubmit],
);
Expand Down
6 changes: 6 additions & 0 deletions src/pages/workspace/categories/CategorySettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function CategorySettingsPage({route, policyCategories}: CategorySettingsPagePro
const {translate} = useLocalize();
const {windowWidth} = useWindowDimensions();
const [deleteCategoryConfirmModalVisible, setDeleteCategoryConfirmModalVisible] = useState(false);
const backTo = route.params?.backTo ?? '';
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need a fallback string?

Copy link
Contributor Author

@ZhenjaHorbach ZhenjaHorbach May 6, 2024

Choose a reason for hiding this comment

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

It doesn't really affect anything
So I think not)
I'll remove it now

const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${route.params.policyID}`);

const policyCategory = policyCategories?.[route.params.categoryName];
Expand All @@ -52,6 +53,10 @@ function CategorySettingsPage({route, policyCategories}: CategorySettingsPagePro
};

const navigateToEditCategory = () => {
if (backTo) {
Navigation.navigate(ROUTES.SETTINGS_CATEGORY_EDIT.getRoute(route.params.policyID, policyCategory.name, backTo));
return;
}
Navigation.navigate(ROUTES.WORKSPACE_CATEGORY_EDIT.getRoute(route.params.policyID, policyCategory.name));
};

Expand Down Expand Up @@ -87,6 +92,7 @@ function CategorySettingsPage({route, policyCategories}: CategorySettingsPagePro
title={route.params.categoryName}
threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)}
threeDotsMenuItems={threeDotsMenuItems}
onBackButtonPress={() => (backTo ? Navigation.goBack(ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(route.params.policyID, backTo)) : Navigation.goBack())}
/>
<ConfirmModal
isVisible={deleteCategoryConfirmModalVisible}
Expand Down
Loading
Loading