Skip to content

Commit

Permalink
Merge pull request #34882 from JKobrynski/migrateReportParticipantsPa…
Browse files Browse the repository at this point in the history
…geToTypeScript

[TS migration] Migrate 'ReportParticipants' page to TypeScript
  • Loading branch information
Hayata Suenaga authored Jan 30, 2024
2 parents 382679c + 2af51b0 commit 6dd9a75
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 68 deletions.
6 changes: 3 additions & 3 deletions src/components/OptionsList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ type OptionsListProps = {
renderFooterContent?: () => JSX.Element;

/** Whether to show a button pill instead of a standard tickbox */
shouldShowMultipleOptionSelectorAsButton: boolean;
shouldShowMultipleOptionSelectorAsButton?: boolean;

/** Text for button pill */
multipleOptionSelectorButtonText: string;
multipleOptionSelectorButtonText?: string;

/** Callback to fire when the multiple selector (tickbox or button) is clicked */
onAddToSelection: () => void;
onAddToSelection?: () => void;

/** Safe area style */
safeAreaPaddingBottomStyle?: StyleProp<ViewStyle>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,75 +1,61 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OptionsList from '@components/OptionsList';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import type * as Localize from '@libs/Localize';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import type {OptionData} from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {PersonalDetailsList, Report} from '@src/types/onyx';
import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound';
import withReportOrNotFound from './home/report/withReportOrNotFound';
import personalDetailsPropType from './personalDetailsPropType';
import reportPropTypes from './reportPropTypes';

const propTypes = {
/* Onyx Props */

/** The personal details of the person who is logged in */
personalDetails: PropTypes.objectOf(personalDetailsPropType),

/** The active report */
report: reportPropTypes.isRequired,

/** Route params */
route: PropTypes.shape({
params: PropTypes.shape({
/** Report ID passed via route r/:reportID/participants */
reportID: PropTypes.string,
}),
}).isRequired,

...withLocalizePropTypes,
type ReportParticipantsPageOnyxProps = {
/** Personal details of all the users */
personalDetails: OnyxEntry<PersonalDetailsList>;
};

const defaultProps = {
personalDetails: {},
};
type ReportParticipantsPageProps = ReportParticipantsPageOnyxProps & WithReportOrNotFoundProps;

/**
* Returns all the participants in the active report
*
* @param {Object} report The active report object
* @param {Object} personalDetails The personal details of the users
* @param {Object} translate The localize
* @return {Array}
* @param report The active report object
* @param personalDetails The personal details of the users
* @param translate The localize
*/
const getAllParticipants = (report, personalDetails, translate) =>
_.chain(ReportUtils.getVisibleMemberIDs(report))
const getAllParticipants = (
report: OnyxEntry<Report>,
personalDetails: OnyxEntry<PersonalDetailsList>,
translate: <TKey extends TranslationPaths>(phraseKey: TKey, ...phraseParameters: Localize.PhraseParameters<Localize.Phrase<TKey>>) => string,
): OptionData[] =>
ReportUtils.getVisibleMemberIDs(report)
.map((accountID, index) => {
const userPersonalDetail = lodashGet(personalDetails, accountID, {displayName: personalDetails.displayName || translate('common.hidden'), avatar: ''});
const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login || '') || translate('common.hidden');
const userPersonalDetail = personalDetails?.[accountID];
const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail?.login ?? '') ?? translate('common.hidden');
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail);

return {
alternateText: userLogin,
displayName,
accountID: userPersonalDetail.accountID,
accountID: userPersonalDetail?.accountID ?? accountID,
icons: [
{
id: accountID,
source: UserUtils.getAvatar(userPersonalDetail.avatar, accountID),
source: UserUtils.getAvatar(userPersonalDetail?.avatar ?? '', accountID),
name: userLogin,
type: CONST.ICON_TYPE_AVATAR,
},
Expand All @@ -79,16 +65,18 @@ const getAllParticipants = (report, personalDetails, translate) =>
text: displayName,
tooltipText: userLogin,
participantsList: [{accountID, displayName}],
reportID: report?.reportID ?? '',
};
})
.sortBy((participant) => participant.displayName.toLowerCase())
.value();
.sort((a, b) => a.displayName.localeCompare(b.displayName.toLowerCase()));

function ReportParticipantsPage(props) {
function ReportParticipantsPage({report, personalDetails}: ReportParticipantsPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const participants = _.map(getAllParticipants(props.report, props.personalDetails, props.translate), (participant) => ({

const participants = getAllParticipants(report, personalDetails, translate).map((participant) => ({
...participant,
isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID),
isDisabled: participant?.accountID ? ReportUtils.isOptimisticPersonalDetail(participant.accountID) : false,
}));

return (
Expand All @@ -97,20 +85,20 @@ function ReportParticipantsPage(props) {
testID={ReportParticipantsPage.displayName}
>
{({safeAreaPaddingBottomStyle}) => (
<FullPageNotFoundView shouldShow={_.isEmpty(props.report) || ReportUtils.isArchivedRoom(props.report)}>
<FullPageNotFoundView shouldShow={!report || ReportUtils.isArchivedRoom(report)}>
<HeaderWithBackButton
title={props.translate(
ReportUtils.isChatRoom(props.report) ||
ReportUtils.isPolicyExpenseChat(props.report) ||
ReportUtils.isChatThread(props.report) ||
ReportUtils.isTaskReport(props.report) ||
ReportUtils.isMoneyRequestReport(props.report)
title={translate(
ReportUtils.isChatRoom(report) ||
ReportUtils.isPolicyExpenseChat(report) ||
ReportUtils.isChatThread(report) ||
ReportUtils.isTaskReport(report) ||
ReportUtils.isMoneyRequestReport(report)
? 'common.members'
: 'common.details',
)}
/>
<View style={[styles.containerWithSpaceBetween, styles.pointerEventsBoxNone]}>
{Boolean(participants.length) && (
{participants?.length && (
<OptionsList
sections={[
{
Expand All @@ -120,7 +108,10 @@ function ReportParticipantsPage(props) {
indexOffset: 0,
},
]}
onSelectRow={(option) => {
onSelectRow={(option: OptionData) => {
if (!option.accountID) {
return;
}
Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID));
}}
hideSectionHeaders
Expand All @@ -139,16 +130,12 @@ function ReportParticipantsPage(props) {
);
}

ReportParticipantsPage.propTypes = propTypes;
ReportParticipantsPage.defaultProps = defaultProps;
ReportParticipantsPage.displayName = 'ReportParticipantsPage';

export default compose(
withLocalize,
withReportOrNotFound(),
withOnyx({
export default withReportOrNotFound()(
withOnyx<ReportParticipantsPageProps, ReportParticipantsPageOnyxProps>({
personalDetails: {
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
},
}),
)(ReportParticipantsPage);
})(ReportParticipantsPage),
);
9 changes: 5 additions & 4 deletions src/pages/home/report/withReportOrNotFound.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type OnyxProps = {
type WithReportOrNotFoundOnyxProps = {
/** The report currently being looked at */
report: OnyxEntry<OnyxTypes.Report>;
/** The policies which the user has access to */
Expand All @@ -24,15 +24,15 @@ type OnyxProps = {
isLoadingReportData: OnyxEntry<boolean>;
};

type WithReportOrNotFoundProps = OnyxProps & {
type WithReportOrNotFoundProps = WithReportOrNotFoundOnyxProps & {
route: RouteProp<{params: {reportID: string}}>;
};

export default function (
shouldRequireReportID = true,
): <TProps extends WithReportOrNotFoundProps, TRef>(
WrappedComponent: React.ComponentType<TProps & React.RefAttributes<TRef>>,
) => React.ComponentType<Omit<TProps & React.RefAttributes<TRef>, keyof OnyxProps>> {
) => React.ComponentType<Omit<TProps & React.RefAttributes<TRef>, keyof WithReportOrNotFoundOnyxProps>> {
return function <TProps extends WithReportOrNotFoundProps, TRef>(WrappedComponent: ComponentType<TProps & RefAttributes<TRef>>) {
function WithReportOrNotFound(props: TProps, ref: ForwardedRef<TRef>) {
const contentShown = React.useRef(false);
Expand Down Expand Up @@ -87,7 +87,7 @@ export default function (

WithReportOrNotFound.displayName = `withReportOrNotFound(${getComponentDisplayName(WrappedComponent)})`;

return withOnyx<TProps & RefAttributes<TRef>, OnyxProps>({
return withOnyx<TProps & RefAttributes<TRef>, WithReportOrNotFoundOnyxProps>({
report: {
key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`,
},
Expand All @@ -103,4 +103,5 @@ export default function (
})(React.forwardRef(WithReportOrNotFound));
};
}

export type {WithReportOrNotFoundProps};
2 changes: 1 addition & 1 deletion src/types/onyx/PersonalDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type PersonalDetails = {
phoneNumber?: string;

/** Avatar URL of the current user from their personal details */
avatar: AvatarSource;
avatar?: AvatarSource;

/** Avatar thumbnail URL of the current user from their personal details */
avatarThumbnail?: string;
Expand Down

0 comments on commit 6dd9a75

Please sign in to comment.