diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 334fa9895205..e53c7915da8a 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -40,13 +40,13 @@ type IconProps = { iconType?: typeof CONST.ICON_TYPE_ICON; /** Icon to display on the left side of component */ - icon: IconAsset; + icon: IconAsset | IconType[]; }; type AvatarProps = { iconType?: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; - icon: AvatarSource; + icon: AvatarSource | IconType[]; }; type NoIcon = { @@ -204,7 +204,7 @@ type MenuItemProps = (IconProps | AvatarProps | NoIcon) & { shouldBlockSelection?: boolean; /** Whether should render title as HTML or as Text */ - shouldParseTitle?: false; + shouldParseTitle?: boolean; /** Should check anonymous user in onPress function */ shouldCheckActionAllowedOnPress?: boolean; diff --git a/src/components/ReportActionItem/TaskView.js b/src/components/ReportActionItem/TaskView.tsx similarity index 66% rename from src/components/ReportActionItem/TaskView.js rename to src/components/ReportActionItem/TaskView.tsx index 7f7b177136ed..ea685d07579d 100644 --- a/src/components/ReportActionItem/TaskView.js +++ b/src/components/ReportActionItem/TaskView.tsx @@ -1,9 +1,7 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useEffect} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; import Checkbox from '@components/Checkbox'; import Hoverable from '@components/Hoverable'; import Icon from '@components/Icon'; @@ -15,68 +13,66 @@ import {usePersonalDetails} from '@components/OnyxProvider'; import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; import SpacerView from '@components/SpacerView'; import Text from '@components/Text'; -import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import withWindowDimensions from '@components/withWindowDimensions'; +import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; +import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import convertToLTR from '@libs/convertToLTR'; import getButtonState from '@libs/getButtonState'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import reportPropTypes from '@pages/reportPropTypes'; import * as Session from '@userActions/Session'; import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {PersonalDetailsList, Policy, Report} from '@src/types/onyx'; -const propTypes = { - /** The report currently being looked at */ - report: reportPropTypes.isRequired, +type TaskViewOnyxProps = { + /** All of the personal details for everyone */ + personalDetails: OnyxEntry; - /** The policy of root parent report */ - policy: PropTypes.shape({ - /** The role of current user */ - role: PropTypes.string, - }), - - /** Whether we should display the horizontal rule below the component */ - shouldShowHorizontalRule: PropTypes.bool.isRequired, - - ...withLocalizePropTypes, - - ...withCurrentUserPersonalDetailsPropTypes, + /** The policy for the current route */ + policy: Pick | null; }; -const defaultProps = { - policy: {}, -}; +type TaskViewProps = TaskViewOnyxProps & + WithCurrentUserPersonalDetailsProps & { + /** The report currently being looked at */ + report: Report; -function TaskView(props) { + /** Whether we should display the horizontal rule below the component */ + shouldShowHorizontalRule: boolean; + }; + +function TaskView({report, policy, shouldShowHorizontalRule, ...props}: TaskViewProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); useEffect(() => { - Task.setTaskReport({...props.report}); - }, [props.report]); + Task.setTaskReport(report); + }, [report]); - const taskTitle = convertToLTR(props.report.reportName || ''); - const assigneeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs([props.report.managerID], props.personalDetails), false); - const isCompleted = ReportUtils.isCompletedTaskReport(props.report); - const isOpen = ReportUtils.isOpenTaskReport(props.report); - const canModifyTask = Task.canModifyTask(props.report, props.currentUserPersonalDetails.accountID, lodashGet(props.policy, 'role', '')); + const taskTitle = convertToLTR(report.reportName ?? ''); + const assigneeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips( + OptionsListUtils.getPersonalDetailsForAccountIDs(report.managerID ? [report.managerID] : [], props.personalDetails), + false, + ); + const isCompleted = ReportUtils.isCompletedTaskReport(report); + const isOpen = ReportUtils.isOpenTaskReport(report); + const canModifyTask = Task.canModifyTask(report, props.currentUserPersonalDetails.accountID, policy?.role); const disableState = !canModifyTask; const isDisableInteractive = !canModifyTask || !isOpen; const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; + const {translate} = useLocalize(); return ( Task.clearTaskErrors(props.report.reportID)} + errors={report.errorFields?.editTask ?? report.errorFields?.createTask} + onClose={() => Task.clearTaskErrors(report.reportID)} errorRowStyles={styles.ph5} > @@ -87,10 +83,10 @@ function TaskView(props) { return; } if (e && e.type === 'click') { - e.currentTarget.blur(); + (e.currentTarget as HTMLElement).blur(); } - Navigation.navigate(ROUTES.TASK_TITLE.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.TASK_TITLE.getRoute(report.reportID)); })} style={({pressed}) => [ styles.ph5, @@ -98,20 +94,19 @@ function TaskView(props) { StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed, false, disableState, !isDisableInteractive), true), isDisableInteractive && !disableState && styles.cursorDefault, ]} - ref={props.forwardedRef} disabled={disableState} - accessibilityLabel={taskTitle || props.translate('task.task')} + accessibilityLabel={taskTitle || translate('task.task')} > {({pressed}) => ( - - {props.translate('task.title')} - + + {translate('task.title')} + { if (isCompleted) { - Task.reopenTask(props.report); + Task.reopenTask(report); } else { - Task.completeTask(props.report); + Task.completeTask(report); } })} isChecked={isCompleted} @@ -119,7 +114,7 @@ function TaskView(props) { containerSize={24} containerBorderRadius={8} caretSize={16} - accessibilityLabel={taskTitle || props.translate('task.task')} + accessibilityLabel={taskTitle || translate('task.task')} disabled={!canModifyTask} /> @@ -145,12 +140,12 @@ function TaskView(props) { )} - + Navigation.navigate(ROUTES.TASK_DESCRIPTION.getRoute(props.report.reportID))} + description={translate('task.description')} + title={report.description ?? ''} + onPress={() => Navigation.navigate(ROUTES.TASK_DESCRIPTION.getRoute(report.reportID))} shouldShowRightIcon={isOpen} disabled={disableState} wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} @@ -159,16 +154,16 @@ function TaskView(props) { interactive={!isDisableInteractive} /> - {props.report.managerID ? ( - + {report.managerID ? ( + Navigation.navigate(ROUTES.TASK_ASSIGNEE.getRoute(props.report.reportID))} + onPress={() => Navigation.navigate(ROUTES.TASK_ASSIGNEE.getRoute(report.reportID))} shouldShowRightIcon={isOpen} disabled={disableState} wrapperStyle={[styles.pv2]} @@ -180,8 +175,8 @@ function TaskView(props) { ) : ( Navigation.navigate(ROUTES.TASK_ASSIGNEE.getRoute(props.report.reportID))} + description={translate('task.assignee')} + onPress={() => Navigation.navigate(ROUTES.TASK_ASSIGNEE.getRoute(report.reportID))} shouldShowRightIcon={isOpen} disabled={disableState} wrapperStyle={[styles.pv2]} @@ -191,31 +186,26 @@ function TaskView(props) { )} ); } -TaskView.propTypes = propTypes; -TaskView.defaultProps = defaultProps; TaskView.displayName = 'TaskView'; -export default compose( - withWindowDimensions, - withLocalize, - withCurrentUserPersonalDetails, - withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, +const TaskViewWithOnyx = withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + policy: { + key: ({report}) => { + const rootParentReport = ReportUtils.getRootParentReport(report); + return `${ONYXKEYS.COLLECTION.POLICY}${rootParentReport ? rootParentReport.policyID : '0'}`; }, - policy: { - key: ({report}) => { - const rootParentReport = ReportUtils.getRootParentReport(report); - return `${ONYXKEYS.COLLECTION.POLICY}${rootParentReport ? rootParentReport.policyID : '0'}`; - }, - selector: (policy) => _.pick(policy, ['role']), - }, - }), -)(TaskView); + selector: (policy: OnyxEntry) => (policy ? {role: policy.role} : null), + }, +})(TaskView); + +export default withCurrentUserPersonalDetails(TaskViewWithOnyx);