diff --git a/src/pages/FlagCommentPage.js b/src/pages/FlagCommentPage.tsx similarity index 50% rename from src/pages/FlagCommentPage.js rename to src/pages/FlagCommentPage.tsx index 47d2ad356dad..9543c48cff25 100644 --- a/src/pages/FlagCommentPage.js +++ b/src/pages/FlagCommentPage.tsx @@ -1,155 +1,150 @@ -import PropTypes from 'prop-types'; +import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; +import type {SvgProps} from 'react-native-svg'; +import type {ValueOf} from 'type-fest'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; +import type {FlagCommentNavigatorParamList} from '@libs/Navigation/types'; import * as ReportUtils from '@libs/ReportUtils'; import * as Report from '@userActions/Report'; import * as Session from '@userActions/Session'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import reportActionPropTypes from './home/report/reportActionPropTypes'; +import type SCREENS from '@src/SCREENS'; +import type * as OnyxTypes from '@src/types/onyx'; import withReportAndReportActionOrNotFound from './home/report/withReportAndReportActionOrNotFound'; -import reportPropTypes from './reportPropTypes'; +import type {WithReportAndReportActionOrNotFoundProps} from './home/report/withReportAndReportActionOrNotFound'; -const propTypes = { - /** Array of report actions for this report */ - reportActions: PropTypes.shape(reportActionPropTypes), - - /** The active report */ - report: reportPropTypes, +type FlagCommentPageWithOnyxProps = { + /** All the report actions from the parent report */ + parentReportActions: OnyxEntry; +}; - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** Report ID passed via route r/:reportID/:reportActionID */ - reportID: PropTypes.string, +type FlagCommentPageNavigationProps = StackScreenProps; - /** ReportActionID passed via route r/:reportID/:reportActionID */ - reportActionID: PropTypes.string, - }), - }).isRequired, +type FlagCommentPageProps = FlagCommentPageNavigationProps & WithReportAndReportActionOrNotFoundProps & FlagCommentPageWithOnyxProps; - ...withLocalizePropTypes, +type Severity = ValueOf; - /* Onyx Props */ - /** All the report actions from the parent report */ - parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), +type SeverityItem = { + severity: Severity; + name: string; + icon: React.FC; + description: string; + furtherDetails: string; + furtherDetailsIcon: React.FC; }; -const defaultProps = { - reportActions: {}, - parentReportActions: {}, - report: {}, -}; +type SeverityItemList = SeverityItem[]; /** * Get the reportID for the associated chatReport - * - * @param {Object} route - * @param {Object} route.params - * @param {String} route.params.reportID - * @returns {String} */ -function getReportID(route) { +function getReportID(route: FlagCommentPageNavigationProps['route']) { return route.params.reportID.toString(); } -function FlagCommentPage(props) { +function FlagCommentPage({parentReportActions, route, report, reportActions}: FlagCommentPageProps) { const styles = useThemeStyles(); - const severities = [ + const {translate} = useLocalize(); + + const severities: SeverityItemList = [ { severity: CONST.MODERATION.FLAG_SEVERITY_SPAM, - name: props.translate('moderation.spam'), + name: translate('moderation.spam'), icon: Expensicons.FlagLevelOne, - description: props.translate('moderation.spamDescription'), - furtherDetails: props.translate('moderation.levelOneResult'), + description: translate('moderation.spamDescription'), + furtherDetails: translate('moderation.levelOneResult'), furtherDetailsIcon: Expensicons.FlagLevelOne, }, { severity: CONST.MODERATION.FLAG_SEVERITY_INCONSIDERATE, - name: props.translate('moderation.inconsiderate'), + name: translate('moderation.inconsiderate'), icon: Expensicons.FlagLevelOne, - description: props.translate('moderation.inconsiderateDescription'), - furtherDetails: props.translate('moderation.levelOneResult'), + description: translate('moderation.inconsiderateDescription'), + furtherDetails: translate('moderation.levelOneResult'), furtherDetailsIcon: Expensicons.FlagLevelOne, }, { severity: CONST.MODERATION.FLAG_SEVERITY_INTIMIDATION, - name: props.translate('moderation.intimidation'), + name: translate('moderation.intimidation'), icon: Expensicons.FlagLevelTwo, - description: props.translate('moderation.intimidationDescription'), - furtherDetails: props.translate('moderation.levelTwoResult'), + description: translate('moderation.intimidationDescription'), + furtherDetails: translate('moderation.levelTwoResult'), furtherDetailsIcon: Expensicons.FlagLevelTwo, }, { severity: CONST.MODERATION.FLAG_SEVERITY_BULLYING, - name: props.translate('moderation.bullying'), + name: translate('moderation.bullying'), icon: Expensicons.FlagLevelTwo, - description: props.translate('moderation.bullyingDescription'), - furtherDetails: props.translate('moderation.levelTwoResult'), + description: translate('moderation.bullyingDescription'), + furtherDetails: translate('moderation.levelTwoResult'), furtherDetailsIcon: Expensicons.FlagLevelTwo, }, { severity: CONST.MODERATION.FLAG_SEVERITY_HARASSMENT, - name: props.translate('moderation.harassment'), + name: translate('moderation.harassment'), icon: Expensicons.FlagLevelThree, - description: props.translate('moderation.harassmentDescription'), - furtherDetails: props.translate('moderation.levelThreeResult'), + description: translate('moderation.harassmentDescription'), + furtherDetails: translate('moderation.levelThreeResult'), furtherDetailsIcon: Expensicons.FlagLevelThree, }, { severity: CONST.MODERATION.FLAG_SEVERITY_ASSAULT, - name: props.translate('moderation.assault'), + name: translate('moderation.assault'), icon: Expensicons.FlagLevelThree, - description: props.translate('moderation.assaultDescription'), - furtherDetails: props.translate('moderation.levelThreeResult'), + description: translate('moderation.assaultDescription'), + furtherDetails: translate('moderation.levelThreeResult'), furtherDetailsIcon: Expensicons.FlagLevelThree, }, ]; - const getActionToFlag = useCallback(() => { - let reportAction = props.reportActions[`${props.route.params.reportActionID.toString()}`]; + const getActionToFlag = useCallback((): OnyxTypes.ReportAction | null => { + let reportAction = reportActions?.[`${route.params.reportActionID.toString()}`]; // Handle threads if needed - if (reportAction === undefined || reportAction.reportActionID === undefined) { - reportAction = props.parentReportActions[props.report.parentReportActionID] || {}; + if (reportAction?.reportActionID === undefined) { + reportAction = parentReportActions?.[report?.parentReportActionID ?? '']; + } + + if (!reportAction) { + return null; } return reportAction; - }, [props.report, props.reportActions, props.route.params.reportActionID, props.parentReportActions]); + }, [report, reportActions, route.params.reportActionID, parentReportActions]); - const flagComment = (severity) => { - let reportID = getReportID(props.route); + const flagComment = (severity: Severity) => { + let reportID: string | undefined = getReportID(route); const reportAction = getActionToFlag(); - const parentReportAction = props.parentReportActions[props.report.parentReportActionID] || {}; + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '']; // Handle threads if needed - if (ReportUtils.isChatThread(props.report) && reportAction.reportActionID === parentReportAction.reportActionID) { - reportID = ReportUtils.getParentReport(props.report).reportID; + if (ReportUtils.isChatThread(report) && reportAction?.reportActionID === parentReportAction?.reportActionID) { + reportID = ReportUtils.getParentReport(report)?.reportID; } - if (ReportUtils.canFlagReportAction(reportAction, reportID)) { - Report.flagComment(reportID, reportAction, severity); + if (reportAction && ReportUtils.canFlagReportAction(reportAction, reportID)) { + Report.flagComment(reportID ?? '', reportAction, severity); } Navigation.dismissModal(); }; - const severityMenuItems = _.map(severities, (item, index) => ( + const severityMenuItems = severities.map((item) => ( {({safeAreaPaddingBottomStyle}) => ( - + { Navigation.goBack(); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '')); }} /> - {props.translate('moderation.flagDescription')} + {translate('moderation.flagDescription')} - {props.translate('moderation.chooseAReason')} + {translate('moderation.chooseAReason')} {severityMenuItems} @@ -193,17 +188,13 @@ function FlagCommentPage(props) { ); } -FlagCommentPage.propTypes = propTypes; -FlagCommentPage.defaultProps = defaultProps; FlagCommentPage.displayName = 'FlagCommentPage'; -export default compose( - withLocalize, - withReportAndReportActionOrNotFound, - withOnyx({ +export default withReportAndReportActionOrNotFound( + withOnyx({ parentReportActions: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID || report.reportID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID ?? report?.reportID}`, canEvict: false, }, - }), -)(FlagCommentPage); + })(FlagCommentPage), +); diff --git a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx index ed686852158b..f8d52744d8aa 100644 --- a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx +++ b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx @@ -1,5 +1,5 @@ /* eslint-disable rulesdir/no-negated-variables */ -import type {RouteProp} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; import React, {useCallback, useEffect} from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; @@ -9,11 +9,13 @@ import withWindowDimensions from '@components/withWindowDimensions'; import type {WindowDimensionsProps} from '@components/withWindowDimensions/types'; import compose from '@libs/compose'; import getComponentDisplayName from '@libs/getComponentDisplayName'; +import type {FlagCommentNavigatorParamList} from '@libs/Navigation/types'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as Report from '@userActions/Report'; import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -37,12 +39,11 @@ type OnyxProps = { isLoadingReportData: OnyxEntry; }; -type ComponentProps = OnyxProps & - WindowDimensionsProps & { - route: RouteProp<{params: {reportID: string; reportActionID: string}}>; - }; +type WithReportAndReportActionOrNotFoundProps = OnyxProps & WindowDimensionsProps & StackScreenProps; -export default function (WrappedComponent: ComponentType>): ComponentType> { +export default function ( + WrappedComponent: ComponentType>, +): ComponentType> { function WithReportOrNotFound(props: TProps, ref: ForwardedRef) { const getReportAction = useCallback(() => { let reportAction: OnyxTypes.ReportAction | Record | undefined = props.reportActions?.[`${props.route.params.reportActionID}`]; @@ -118,3 +119,5 @@ export default function (WrappedComponent: withWindowDimensions, )(React.forwardRef(WithReportOrNotFound)); } + +export type {WithReportAndReportActionOrNotFoundProps};