From f5a0d7b04aa56d3ac7541f277258016e03d7c4d9 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Wed, 20 Dec 2023 12:33:52 +0100 Subject: [PATCH] Integrate search bar --- src/components/OptionsList/BaseOptionsList.js | 8 +- .../OptionsSelector/BaseOptionsSelector.js | 1 + .../optionsSelectorPropTypes.js | 4 + src/pages/WorkspaceSwitcherPage.js | 248 ++++++++---------- 4 files changed, 125 insertions(+), 136 deletions(-) diff --git a/src/components/OptionsList/BaseOptionsList.js b/src/components/OptionsList/BaseOptionsList.js index d22df00bd0b3..9aa9e7d796b6 100644 --- a/src/components/OptionsList/BaseOptionsList.js +++ b/src/components/OptionsList/BaseOptionsList.js @@ -192,6 +192,10 @@ function BaseOptionsList({ return true; } + if (option.policyID && option.policyID === item.policyID) { + return true; + } + if (_.isEmpty(option.name)) { return false; } @@ -201,7 +205,7 @@ function BaseOptionsList({ return ( 0 && shouldHaveOptionSeparator} shouldDisableRowInnerPadding={shouldDisableRowInnerPadding} diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 3361718db31e..808031b320c2 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -501,6 +501,7 @@ class BaseOptionsSelector extends Component { onSelectRow={this.props.onSelectRow ? this.selectRow : undefined} sections={this.state.sections} focusedIndex={this.state.focusedIndex} + disableFocusOptions={this.props.disableFocusOptions} selectedOptions={this.props.selectedOptions} canSelectMultipleOptions={this.props.canSelectMultipleOptions} shouldShowMultipleOptionSelectorAsButton={this.props.shouldShowMultipleOptionSelectorAsButton} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index e52187fa76d7..847409c70269 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -72,6 +72,9 @@ const propTypes = { /** Whether to disable interactivity of option rows */ isDisabled: PropTypes.bool, + /** Whether to disable focus options of rows */ + disableFocusOptions: PropTypes.bool, + /** Display the text of the option in bold font style */ boldStyle: PropTypes.bool, @@ -163,6 +166,7 @@ const defaultProps = { shouldShowOptions: true, disableArrowKeysActions: false, isDisabled: false, + disableFocusOptions: false, shouldHaveOptionSeparator: false, initiallyFocusedOptionKey: undefined, maxLength: CONST.SEARCH_MAX_LENGTH, diff --git a/src/pages/WorkspaceSwitcherPage.js b/src/pages/WorkspaceSwitcherPage.js index ffb955b14e20..dc4c2b682319 100644 --- a/src/pages/WorkspaceSwitcherPage.js +++ b/src/pages/WorkspaceSwitcherPage.js @@ -1,24 +1,20 @@ import PropTypes from 'prop-types'; -import React, {useCallback, useMemo} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import HeaderPageLayout from '@components/HeaderPageLayout'; import * as Expensicons from '@components/Icon/Expensicons'; -import MenuItem from '@components/MenuItem'; import OptionRow from '@components/OptionRow'; import OptionsSelector from '@components/OptionsSelector'; -import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import Text from '@components/Text'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; -import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import useTheme from '@styles/themes/useTheme'; import useThemeStyles from '@styles/useThemeStyles'; import * as Policy from '@userActions/Policy'; -import Icon from '@src/components/Icon'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; @@ -54,180 +50,164 @@ const defaultProps = { function WorkspaceSwitcherPage({policies, activeWorkspaceID}) { const theme = useTheme(); const styles = useThemeStyles(); - const {translate} = useLocalize(); const {isOffline} = useNetwork(); + const [selectedOption, setSelectedOption] = useState(); + const [searchTerm, setSearchTerm] = useState(''); const getIndicatorTypeForPolicy = useCallback( // TO DO: Wait for missing logic to be implemented in other PR // CONST.BRICK_ROAD_INDICATOR_STATUS.INFO or CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + // eslint-disable-next-line no-unused-vars (policyId) => undefined, [], ); - const getMenuItem = useCallback( - (item) => { - const keyTitle = item.translationKey ? translate(item.translationKey) : item.title; - - const option = { - text: keyTitle, - brickRoadIndicator: getIndicatorTypeForPolicy(item.policyId), - icons: [ - { - source: item.icon, - type: item.iconType, - fill: item.iconFill, - name: keyTitle, - fallbackIcon: item.fallbackIcon, - }, - ], - }; - - // return ( - // - // ); - - return ( - - ); - }, - [activeWorkspaceID, getIndicatorTypeForPolicy, translate], + const hasUnreadData = useCallback( + // TO DO: Implement checking if policy has some unread data + // eslint-disable-next-line no-unused-vars + (policyId) => false, + [] ); + const selectPolicy = useCallback((option) => { + const policyID = option.policyID; + Policy.selectWorkspace(policyID); + + if (policyID) { + setSelectedOption(option); + } else { + setSelectedOption(undefined); + } + }, []); + + const onChangeText = useCallback((newSearchTerm) => { + // TO DO: Handle searching logic + setSearchTerm(newSearchTerm); + }, []) + const usersWorkspaces = useMemo( () => _.chain(policies) .filter((policy) => PolicyUtils.shouldShowPolicy(policy, isOffline)) .map((policy) => ({ - title: policy.name, - policyId: policy.id, - icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name), - iconType: CONST.ICON_TYPE_WORKSPACE, - action: () => { - Policy.selectWorkspace(policy.id); - }, - fallbackIcon: Expensicons.FallbackWorkspaceAvatar, - pendingAction: policy.pendingAction, - errors: policy.errors, - disabled: policy.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + 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), })) - .sortBy((policy) => policy.title.toLowerCase()) + .sortBy((policy) => policy.text.toLowerCase()) .value(), - [policies, isOffline], + [policies, isOffline, getIndicatorTypeForPolicy, hasUnreadData], ); const usersWorkspacesSectionData = useMemo( - () => [ - { + () => ({ data: usersWorkspaces, shouldShow: true, indexOffset: 0, - }, - ], + }), [usersWorkspaces], ); - const allWorkspaces = useMemo( - () => [ - { - title: 'Expensify', - icon: Expensicons.ExpensifyAppIcon, - iconType: CONST.ICON_TYPE_AVATAR, - action: () => { - Policy.selectWorkspace(undefined); + const everythingSection = useMemo(() => { + const option = { + text: 'Expensify', + icons: [ + { + source: Expensicons.ExpensifyAppIcon, + name: 'Expensify', + type: CONST.ICON_TYPE_AVATAR, }, - indicatorType: getIndicatorTypeForPolicy(undefined), - }, - ], - [getIndicatorTypeForPolicy], - ); + ], + brickRoadIndicator: getIndicatorTypeForPolicy(undefined), + boldStyle: hasUnreadData(undefined), + }; - const getWorkspacesSection = useCallback( - (workspaces, section, showAddWorkspaceButton) => ( - + return ( + <> - {section} + Everything - {showAddWorkspaceButton && ( - - {({hovered}) => ( - - )} - - )} - {_.map(workspaces, (item, index) => getMenuItem(item, index))} - + + + + + ); + }, [activeWorkspaceID, getIndicatorTypeForPolicy, hasUnreadData, selectPolicy, styles.alignItemsCenter, styles.flexRow, styles.justifyContentBetween, styles.label, styles.mb3, styles.mh4, theme.textSupporting]); + + const inputCallbackRef = useAutoFocusInput(); + const workspacesSection = useMemo( + () => ( + <> + + + Workspaces + + + {/* TO DO: Display breadcrumb */} + {usersWorkspacesSectionData.data.length === 0 && } + 8} + onChangeText={onChangeText} + selectedOptions={selectedOption ? [selectedOption] : []} + onSelectRow={selectPolicy} + boldStyle + shouldPreventDefaultFocusOnSelectRow + highlightSelectedOptions + shouldShowOptions + autoFocus={false} + disableFocusOptions + canSelectMultipleOptions={false} + shouldShowSubscript={false} + showTitleTooltip={false} + contentContainerStyles={[styles.pt0, styles.mt0]} + /> + ), - [ - getMenuItem, - styles.alignItemsCenter, - styles.borderRadiusNormal, - styles.bordersBG, - styles.flexRow, - styles.highlightBG, - styles.justifyContentBetween, - styles.label, - styles.mb3, - styles.mh4, - styles.p2, - theme.textSupporting, - ], + [inputCallbackRef, onChangeText, searchTerm, selectPolicy, selectedOption, styles.alignItemsCenter, styles.flexRow, styles.justifyContentBetween, styles.label, styles.mb1, styles.mh4, styles.mt0, styles.mt3, styles.pt0, theme.textSupporting, usersWorkspacesSectionData], ); - const allWorkspacesSection = useMemo(() => getWorkspacesSection(allWorkspaces, 'Everything', false, false), [allWorkspaces, getWorkspacesSection]); - const usersWorkspacesSection = useMemo(() => getWorkspacesSection(usersWorkspaces, 'Workspaces', true, true), [getWorkspacesSection, usersWorkspaces]); - - // const {inputCallbackRef} = useAutoFocusInput(); + useEffect(() => { + if (!activeWorkspaceID) { + return; + } + const optionToSet = _.find(usersWorkspaces, (option) => option.policyID === activeWorkspaceID); + setSelectedOption(optionToSet); + }, [activeWorkspaceID, usersWorkspaces]); return ( - {allWorkspacesSection} - {usersWorkspacesSection} - {/* {}} - sections={usersWorkspacesSectionData} - selectedOptions={[]} - value="Find" - onSelectRow={(option) => {}} - onChangeText - headerMessage - boldStyle - shouldPreventDefaultFocusOnSelectRow - shouldShowOptions - autoFocus={false} - /> */} + {everythingSection} + {workspacesSection} ); }