Skip to content

Commit

Permalink
Merge pull request #34157 from allroundexperts/feat-32763
Browse files Browse the repository at this point in the history
feat: Add report field picker components
  • Loading branch information
thienlnam authored Jan 23, 2024
2 parents 203a5cf + cfa4cea commit 616d75f
Show file tree
Hide file tree
Showing 12 changed files with 365 additions and 5 deletions.
6 changes: 5 additions & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ const ONYXKEYS = {
REPORT_VIRTUAL_CARD_FRAUD_DRAFT: 'reportVirtualCardFraudFormDraft',
GET_PHYSICAL_CARD_FORM: 'getPhysicalCardForm',
GET_PHYSICAL_CARD_FORM_DRAFT: 'getPhysicalCardFormDraft',
POLICY_REPORT_FIELD_EDIT_FORM: 'policyReportFieldEditForm',
POLICY_REPORT_FIELD_EDIT_FORM_DRAFT: 'policyReportFieldEditFormDraft',
},
} as const;

Expand Down Expand Up @@ -442,7 +444,7 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories;
[ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS]: OnyxTypes.PolicyReportField;
[ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS]: OnyxTypes.PolicyReportFields;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields;
[ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: Record<string, number>;
Expand Down Expand Up @@ -528,6 +530,8 @@ type OnyxValues = {
[ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form | undefined;
[ONYXKEYS.FORMS.POLICY_REPORT_FIELD_EDIT_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.POLICY_REPORT_FIELD_EDIT_FORM_DRAFT]: OnyxTypes.Form | undefined;
};

type OnyxKeyValue<TOnyxKey extends (OnyxKey | OnyxCollectionKey) & keyof OnyxValues> = OnyxEntry<OnyxValues[TOnyxKey]>;
Expand Down
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ const ROUTES = {
route: 'r/:threadReportID/edit/currency',
getRoute: (threadReportID: string, currency: string, backTo: string) => `r/${threadReportID}/edit/currency?currency=${currency}&backTo=${backTo}` as const,
},
EDIT_REPORT_FIELD_REQUEST: {
route: 'r/:reportID/edit/policyField/:policyID/:fieldID',
getRoute: (reportID: string, policyID: string, fieldID: string) => `r/${reportID}/edit/policyField/${policyID}/${fieldID}` as const,
},
REPORT_WITH_ID_DETAILS_SHARE_CODE: {
route: 'r/:reportID/details/shareCode',
getRoute: (reportID: string) => `r/${reportID}/details/shareCode` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ const SCREENS = {
EDIT_REQUEST: {
ROOT: 'EditRequest_Root',
CURRENCY: 'EditRequest_Currency',
REPORT_FIELD: 'EditRequest_ReportField',
},

NEW_CHAT: {
Expand Down
4 changes: 3 additions & 1 deletion src/components/ReportActionItem/MoneyReportView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground';
import variables from '@styles/variables';
import ROUTES from '@src/ROUTES';
import type {PolicyReportField, Report} from '@src/types/onyx';

type MoneyReportViewProps = {
Expand Down Expand Up @@ -73,7 +75,7 @@ function MoneyReportView({report, policyReportFields, shouldShowHorizontalRule}:
<MenuItemWithTopDescription
description={reportField.name}
title={title}
onPress={() => {}}
onPress={() => Navigation.navigate(ROUTES.EDIT_REPORT_FIELD_REQUEST.getRoute(report.reportID, report.policyID ?? '', reportField.fieldID))}
shouldShowRightIcon
disabled={false}
wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]}
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ const FlagCommentStackNavigator = createModalStackNavigator<FlagCommentNavigator
const EditRequestStackNavigator = createModalStackNavigator<EditRequestNavigatorParamList>({
[SCREENS.EDIT_REQUEST.ROOT]: () => require('../../../pages/EditRequestPage').default as React.ComponentType,
[SCREENS.EDIT_REQUEST.CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType,
[SCREENS.EDIT_REQUEST.REPORT_FIELD]: () => require('../../../pages/EditReportFieldPage').default as React.ComponentType,
});

const PrivateNotesModalStackNavigator = createModalStackNavigator<PrivateNotesNavigatorParamList>({
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ const linkingConfig: LinkingOptions<RootStackParamList> = {
screens: {
[SCREENS.EDIT_REQUEST.ROOT]: ROUTES.EDIT_REQUEST.route,
[SCREENS.EDIT_REQUEST.CURRENCY]: ROUTES.EDIT_CURRENCY_REQUEST.route,
[SCREENS.EDIT_REQUEST.REPORT_FIELD]: ROUTES.EDIT_REPORT_FIELD_REQUEST.route,
},
},
[SCREENS.RIGHT_MODAL.SIGN_IN]: {
Expand Down
82 changes: 82 additions & 0 deletions src/pages/EditReportFieldDatePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, {useCallback, useRef} from 'react';
import {View} from 'react-native';
import DatePicker from '@components/DatePicker';
import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

type EditReportFieldDatePageProps = {
/** Value of the policy report field */
fieldValue: string;

/** Name of the policy report field */
fieldName: string;

/** ID of the policy report field */
fieldID: string;

/** Callback to fire when the Save button is pressed */
onSubmit: () => void;
};

function EditReportFieldDatePage({fieldName, onSubmit, fieldValue, fieldID}: EditReportFieldDatePageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const inputRef = useRef<HTMLInputElement>(null);

const validate = useCallback(
(value: Record<string, string>) => {
const errors: Record<string, string> = {};
if (value[fieldID].trim() === '') {
errors[fieldID] = 'common.error.fieldRequired';
}
return errors;
},
[fieldID],
);

return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnableMaxHeight
onEntryTransitionEnd={() => inputRef.current?.focus()}
testID={EditReportFieldDatePage.displayName}
>
<HeaderWithBackButton title={fieldName} />
{/* @ts-expect-error TODO: TS migration */}
<FormProvider
style={[styles.flexGrow1, styles.ph5]}
formID={ONYXKEYS.FORMS.POLICY_REPORT_FIELD_EDIT_FORM}
onSubmit={onSubmit}
validate={validate}
submitButtonText={translate('common.save')}
enabledWhenOffline
>
<View style={styles.mb4}>
<InputWrapper
// @ts-expect-error TODO: TS migration
InputComponent={DatePicker}
inputID={fieldID}
name={fieldID}
defaultValue={fieldValue}
label={fieldName}
accessibilityLabel={fieldName}
role={CONST.ROLE.PRESENTATION}
maxDate={CONST.CALENDAR_PICKER.MAX_DATE}
minDate={CONST.CALENDAR_PICKER.MIN_DATE}
ref={inputRef}
/>
</View>
</FormProvider>
</ScreenWrapper>
);
}

EditReportFieldDatePage.displayName = 'EditReportFieldDatePage';

export default EditReportFieldDatePage;
82 changes: 82 additions & 0 deletions src/pages/EditReportFieldDropdownPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, {useMemo, useState} from 'react';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OptionsSelector from '@components/OptionsSelector';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';

type EditReportFieldDropdownPageProps = {
/** Value of the policy report field */
fieldValue: string;

/** Name of the policy report field */
fieldName: string;

/** Options of the policy report field */
fieldOptions: string[];

/** Callback to fire when the Save button is pressed */
onSubmit: () => void;
};

function EditReportFieldDropdownPage({fieldName, onSubmit, fieldValue, fieldOptions}: EditReportFieldDropdownPageProps) {
const [searchValue, setSearchValue] = useState('');
const styles = useThemeStyles();
const {getSafeAreaMargins} = useStyleUtils();
const {translate} = useLocalize();

const sections = useMemo(() => {
const filteredOptions = fieldOptions.filter((option) => option.toLowerCase().includes(searchValue.toLowerCase()));
return [
{
title: translate('common.recents'),
shouldShow: true,
data: [],
},
{
title: translate('common.all'),
shouldShow: true,
data: filteredOptions.map((option) => ({
text: option,
keyForList: option,
searchText: option,
tooltipText: option,
})),
},
];
}, [fieldOptions, searchValue, translate]);

return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnableMaxHeight
testID={EditReportFieldDropdownPage.displayName}
>
{({insets}) => (
<>
<HeaderWithBackButton title={fieldName} />
<OptionsSelector
// @ts-expect-error TODO: TS migration
contentContainerStyles={[{paddingBottom: getSafeAreaMargins(insets).marginBottom}]}
optionHoveredStyle={styles.hoveredComponentBG}
sectionHeaderStyle={styles.mt5}
selectedOptions={[{name: fieldValue}]}
textInputLabel={translate('common.search')}
boldStyle
sections={sections}
value={searchValue}
onSelectRow={onSubmit}
onChangeText={setSearchValue}
highlightSelectedOptions
isRowMultilineSupported
/>
</>
)}
</ScreenWrapper>
);
}

EditReportFieldDropdownPage.displayName = 'EditReportFieldDropdownPage';

export default EditReportFieldDropdownPage;
103 changes: 103 additions & 0 deletions src/pages/EditReportFieldPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React, {useEffect} from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ScreenWrapper from '@components/ScreenWrapper';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PolicyReportFields, Report} from '@src/types/onyx';
import EditReportFieldDatePage from './EditReportFieldDatePage';
import EditReportFieldDropdownPage from './EditReportFieldDropdownPage';
import EditReportFieldTextPage from './EditReportFieldTextPage';

type EditReportFieldPageOnyxProps = {
/** The report object for the expense report */
report: OnyxEntry<Report>;

/** Policy report fields */
policyReportFields: OnyxEntry<PolicyReportFields>;
};

type EditReportFieldPageProps = EditReportFieldPageOnyxProps & {
/** Route from navigation */
route: {
/** Params from the route */
params: {
/** Which field we are editing */
fieldID: string;

/** reportID for the expense report */
reportID: string;

/** policyID for the expense report */
policyID: string;
};
};
};

function EditReportFieldPage({route, report, policyReportFields}: EditReportFieldPageProps) {
const policyReportField = policyReportFields?.[route.params.fieldID];
const reportFieldValue = report?.reportFields?.[policyReportField?.fieldID ?? ''];

// Decides whether to allow or disallow editing a money request
useEffect(() => {}, []);

if (policyReportField) {
if (policyReportField.type === 'text' || policyReportField.type === 'formula') {
return (
<EditReportFieldTextPage
fieldName={policyReportField.name}
fieldID={policyReportField.fieldID}
fieldValue={reportFieldValue ?? policyReportField.defaultValue}
onSubmit={() => {}}
/>
);
}

if (policyReportField.type === 'date') {
return (
<EditReportFieldDatePage
fieldName={policyReportField.name}
fieldID={policyReportField.fieldID}
fieldValue={reportFieldValue ?? policyReportField.defaultValue}
onSubmit={() => {}}
/>
);
}

if (policyReportField.type === 'dropdown') {
return (
<EditReportFieldDropdownPage
fieldName={policyReportField.name}
fieldValue={reportFieldValue ?? policyReportField.defaultValue}
fieldOptions={policyReportField.values}
onSubmit={() => {}}
/>
);
}
}

return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnableMaxHeight
testID={EditReportFieldPage.displayName}
>
<FullPageNotFoundView
shouldShow
onBackButtonPress={() => {}}
onLinkPress={() => {}}
/>
</ScreenWrapper>
);
}

EditReportFieldPage.displayName = 'EditReportFieldPage';

export default withOnyx<EditReportFieldPageProps, EditReportFieldPageOnyxProps>({
report: {
key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`,
},
policyReportFields: {
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS}${route.params.policyID}`,
},
})(EditReportFieldPage);
Loading

0 comments on commit 616d75f

Please sign in to comment.