Skip to content

Commit

Permalink
Migrate WorkspaceSwitcherPage
Browse files Browse the repository at this point in the history
  • Loading branch information
filip-solecki committed Feb 1, 2024
1 parent 7860696 commit a8b35da
Showing 1 changed file with 93 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import type {OnyxCollection} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
Expand All @@ -26,51 +24,39 @@ import {getWorkspacesBrickRoads, getWorkspacesUnreadStatuses} from '@libs/Worksp
import * as App from '@userActions/App';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import type {Policy} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import WorkspaceCardCreateAWorkspace from './workspace/card/WorkspaceCardCreateAWorkspace';

const sortWorkspacesBySelected = (workspace1, workspace2, selectedWorkspaceID) => {
type SimpleWorkspaceItem = {
text?: string;
policyID?: string;
isPolicyAdmin?: boolean;
};

const sortWorkspacesBySelected = (workspace1: SimpleWorkspaceItem, workspace2: SimpleWorkspaceItem, selectedWorkspaceID: string | undefined): number => {
if (workspace1.policyID === selectedWorkspaceID) {
return -1;
}
if (workspace2.policyID === selectedWorkspaceID) {
return 1;
}
return workspace1.text.toLowerCase().localeCompare(workspace2.text.toLowerCase());
return workspace1.text?.toLowerCase().localeCompare(workspace2.text?.toLowerCase() ?? '') ?? 0;
};

const propTypes = {
type WorkspaceSwitcherPageOnyxProps = {
/** The list of this user's policies */
policies: PropTypes.objectOf(
PropTypes.shape({
/** The ID of the policy */
id: PropTypes.string,

/** The name of the policy */
name: PropTypes.string,

/** The type of the policy */
type: PropTypes.string,

/** The user's role in the policy */
role: PropTypes.string,

/** The current action that is waiting to happen on the policy */
pendingAction: PropTypes.oneOf(_.values(CONST.RED_BRICK_ROAD_PENDING_ACTION)),
}),
),
policies: OnyxCollection<Policy>;
};

const defaultProps = {
policies: {},
};
type WorkspaceSwitcherPageProps = WorkspaceSwitcherPageOnyxProps;

function WorkspaceSwitcherPage({policies}) {
function WorkspaceSwitcherPage({policies}: WorkspaceSwitcherPageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const [selectedOption, setSelectedOption] = useState();
const [searchTerm, setSearchTerm] = useState('');
const [selectedOption, setSelectedOption] = useState<SimpleWorkspaceItem | undefined>(undefined);
const [searchTerm, setSearchTerm] = useState<string>();
const {inputCallbackRef} = useAutoFocusInput();
const {translate} = useLocalize();
const {activeWorkspaceID, setActiveWorkspaceID} = useActiveWorkspace();
Expand All @@ -79,16 +65,16 @@ function WorkspaceSwitcherPage({policies}) {
const unreadStatusesForPolicies = useMemo(() => getWorkspacesUnreadStatuses(), []);

const getIndicatorTypeForPolicy = useCallback(
(policyId) => {
(policyId?: string) => {
if (policyId && policyId !== activeWorkspaceID) {
return brickRoadsForPolicies[policyId];
}

if (_.values(brickRoadsForPolicies).includes(CONST.BRICK_ROAD.RBR)) {
if (Object.values(brickRoadsForPolicies).includes(CONST.BRICK_ROAD.RBR)) {
return CONST.BRICK_ROAD.RBR;
}

if (_.values(brickRoadsForPolicies).includes(CONST.BRICK_ROAD.GBR)) {
if (Object.values(brickRoadsForPolicies).includes(CONST.BRICK_ROAD.GBR)) {
return CONST.BRICK_ROAD.GBR;
}

Expand All @@ -99,62 +85,69 @@ function WorkspaceSwitcherPage({policies}) {

const hasUnreadData = useCallback(
// TO DO: Implement checking if policy has some unread data
// eslint-disable-next-line no-unused-vars
(policyId) => {
(policyId?: string) => {
if (policyId) {
return unreadStatusesForPolicies[policyId];
}

return _.some(_.values(unreadStatusesForPolicies), (status) => status);
return Object.values(unreadStatusesForPolicies).some((status) => status);
},
[unreadStatusesForPolicies],
);

const selectPolicy = (option) => {
const {policyID, isPolicyAdmin} = option;
const selectPolicy = useCallback(
(option?: SimpleWorkspaceItem) => {
if (!option) {
return;
}

if (policyID) {
setSelectedOption(option);
} else {
setSelectedOption(undefined);
}
setActiveWorkspaceID(policyID);
Navigation.goBack();
if (policyID !== activeWorkspaceID) {
Navigation.navigateWithSwitchPolicyID({policyID, isPolicyAdmin});
}
};
const {policyID, isPolicyAdmin} = option;

const usersWorkspaces = useMemo(
() =>
_.chain(policies)
.filter((policy) => PolicyUtils.shouldShowPolicy(policy, isOffline))
.map((policy) => ({
text: policy.name,
policyID: policy.id,
brickRoadIndicator: getIndicatorTypeForPolicy(policy.id),
icons: [
{
source: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name),
fallbackIcon: Expensicons.FallbackWorkspaceAvatar,
name: policy.name,
type: CONST.ICON_TYPE_WORKSPACE,
},
],
boldStyle: hasUnreadData(policy.id),
keyForList: policy.id,
isPolicyAdmin: PolicyUtils.isPolicyAdmin(policy),
}))
.value(),
[policies, getIndicatorTypeForPolicy, hasUnreadData],
if (policyID) {
setSelectedOption(option);
} else {
setSelectedOption(undefined);
}
setActiveWorkspaceID(policyID);
Navigation.goBack();
if (policyID !== activeWorkspaceID) {
Navigation.navigateWithSwitchPolicyID({policyID, isPolicyAdmin});
}
},
[activeWorkspaceID, setActiveWorkspaceID],
);

const usersWorkspaces = useMemo(() => {
if (!policies || isEmptyObject(policies)) {
return [];
}

return Object.values(policies)
.filter((policy) => PolicyUtils.shouldShowPolicy(policy, !!isOffline))
.map((policy) => ({
text: policy?.name,
policyID: policy?.id,
brickRoadIndicator: getIndicatorTypeForPolicy(policy?.id),
icons: [
{
source: policy?.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy?.name),
fallbackIcon: Expensicons.FallbackWorkspaceAvatar,
name: policy?.name,
type: CONST.ICON_TYPE_WORKSPACE,
},
],
boldStyle: hasUnreadData(policy?.id),
keyForList: policy?.id,
isPolicyAdmin: PolicyUtils.isPolicyAdmin(policy),
}));
}, [policies, getIndicatorTypeForPolicy, hasUnreadData, isOffline]);

const filteredAndSortedUserWorkspaces = useMemo(
() =>
_.filter(usersWorkspaces, (policy) => policy.text.toLowerCase().includes(searchTerm.toLowerCase())).sort((policy1, policy2) =>
sortWorkspacesBySelected(policy1, policy2, activeWorkspaceID),
),
[searchTerm, usersWorkspaces],
usersWorkspaces
.filter((policy) => policy.text?.toLowerCase().includes(searchTerm?.toLowerCase() ?? ''))
.sort((policy1, policy2) => sortWorkspacesBySelected(policy1, policy2, activeWorkspaceID)),
[searchTerm, usersWorkspaces, activeWorkspaceID],
);

const usersWorkspacesSectionData = useMemo(
Expand Down Expand Up @@ -192,10 +185,9 @@ function WorkspaceSwitcherPage({policies}) {
</View>
<View>
<OptionRow
option={{...option, brickRoadIndicator: !activeWorkspaceID ? undefined : option.brickRoadIndicator}}
option={{...option, brickRoadIndicator: !activeWorkspaceID ? undefined : option.brickRoadIndicator, reportID: ''}}
onSelectRow={selectPolicy}
showTitleTooltip={false}
shouldShowSubscript={false}
highlightSelected
isSelected={!activeWorkspaceID}
optionIsFocused={!activeWorkspaceID}
Expand All @@ -210,7 +202,7 @@ function WorkspaceSwitcherPage({policies}) {
const workspacesSection = useMemo(
() => (
<>
<View style={[styles.mh4, styles.mt6, styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, ...(usersWorkspaces.length > 0 ? [styles.mb0] : [styles.mb3])]}>
<View style={[styles.mh4, styles.mt6, styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, ...(usersWorkspaces.length > 0 ? [styles.mb1] : [styles.mb3])]}>
<View>
<Text
style={styles.label}
Expand All @@ -220,6 +212,7 @@ function WorkspaceSwitcherPage({policies}) {
</Text>
</View>
<PressableWithFeedback
accessible={false}
role={CONST.ROLE.BUTTON}
onPress={() => {
App.createWorkspaceWithPolicyDraftAndNavigateToIt();
Expand All @@ -239,12 +232,13 @@ function WorkspaceSwitcherPage({policies}) {

{usersWorkspaces.length > 0 ? (
<OptionsSelector
placeholderText={translate('workspace.switcher.placeholder')}
// @ts-expect-error TODO: remove this comment once OptionsSelector (https://github.com/Expensify/App/issues/25125) is migrated to TS
placeholder={translate('workspace.switcher.placeholder')}
ref={inputCallbackRef}
sections={[usersWorkspacesSectionData]}
value={searchTerm}
shouldShowTextInput={usersWorkspaces.length >= CONST.WORKSPACE_SWITCHER.MINIMUM_WORKSPACES_TO_SHOW_SEARCH}
onChangeText={(newSearchTerm) => setSearchTerm(newSearchTerm)}
onChangeText={setSearchTerm}
selectedOptions={selectedOption ? [selectedOption] : []}
onSelectRow={selectPolicy}
shouldPreventDefaultFocusOnSelectRow
Expand All @@ -266,22 +260,35 @@ function WorkspaceSwitcherPage({policies}) {
)}
</>
),
[inputCallbackRef, setSearchTerm, searchTerm, selectPolicy, selectedOption, styles, theme.textSupporting, translate, usersWorkspaces.length, usersWorkspacesSectionData],
[
inputCallbackRef,
setSearchTerm,
searchTerm,
selectPolicy,
selectedOption,
styles,
theme.textSupporting,
translate,
usersWorkspaces.length,
usersWorkspacesSectionData,
activeWorkspaceID,
theme.icon,
headerMessage,
],
);

useEffect(() => {
if (!activeWorkspaceID) {
return;
}
const optionToSet = _.find(usersWorkspaces, (option) => option.policyID === activeWorkspaceID);
const optionToSet = usersWorkspaces.find((option) => option.policyID === activeWorkspaceID);
setSelectedOption(optionToSet);
}, [activeWorkspaceID, usersWorkspaces]);

return (
<ScreenWrapper>
<ScreenWrapper testID={WorkspaceSwitcherPage.displayName}>
<HeaderWithBackButton
title={translate('workspace.switcher.headerTitle')}
backgroundColor={theme.PAGE_THEMES[SCREENS.WORKSPACE_SWITCHER.ROOT].backgroundColor}
onBackButtonPress={Navigation.goBack}
/>
{everythingSection}
Expand All @@ -290,11 +297,9 @@ function WorkspaceSwitcherPage({policies}) {
);
}

WorkspaceSwitcherPage.propTypes = propTypes;
WorkspaceSwitcherPage.defaultProps = defaultProps;
WorkspaceSwitcherPage.displayName = 'WorkspaceSwitcherPage';

export default withOnyx({
export default withOnyx<WorkspaceSwitcherPageProps, WorkspaceSwitcherPageOnyxProps>({
policies: {
key: ONYXKEYS.COLLECTION.POLICY,
},
Expand Down

0 comments on commit a8b35da

Please sign in to comment.