Skip to content

Commit f5a0d7b

Browse files
committed
Integrate search bar
1 parent 2b0cb18 commit f5a0d7b

File tree

4 files changed

+125
-136
lines changed

4 files changed

+125
-136
lines changed

src/components/OptionsList/BaseOptionsList.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ function BaseOptionsList({
192192
return true;
193193
}
194194

195+
if (option.policyID && option.policyID === item.policyID) {
196+
return true;
197+
}
198+
195199
if (_.isEmpty(option.name)) {
196200
return false;
197201
}
@@ -201,7 +205,7 @@ function BaseOptionsList({
201205

202206
return (
203207
<OptionRow
204-
option={item}
208+
option={{...item, brickRoadIndicator: isSelected ? undefined : item.brickRoadIndicator}}
205209
showTitleTooltip={showTitleTooltip}
206210
hoverStyle={optionHoveredStyle}
207211
optionIsFocused={!disableFocusOptions && !isItemDisabled && focusedIndex === index + section.indexOffset}
@@ -212,7 +216,7 @@ function BaseOptionsList({
212216
selectedStateButtonText={multipleOptionSelectorButtonText}
213217
onSelectedStatePressed={onAddToSelection}
214218
highlightSelected={highlightSelectedOptions}
215-
boldStyle={boldStyle}
219+
boldStyle={_.isUndefined(item.boldStyle) ? boldStyle : item.boldStyle}
216220
isDisabled={isItemDisabled}
217221
shouldHaveOptionSeparator={index > 0 && shouldHaveOptionSeparator}
218222
shouldDisableRowInnerPadding={shouldDisableRowInnerPadding}

src/components/OptionsSelector/BaseOptionsSelector.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ class BaseOptionsSelector extends Component {
501501
onSelectRow={this.props.onSelectRow ? this.selectRow : undefined}
502502
sections={this.state.sections}
503503
focusedIndex={this.state.focusedIndex}
504+
disableFocusOptions={this.props.disableFocusOptions}
504505
selectedOptions={this.props.selectedOptions}
505506
canSelectMultipleOptions={this.props.canSelectMultipleOptions}
506507
shouldShowMultipleOptionSelectorAsButton={this.props.shouldShowMultipleOptionSelectorAsButton}

src/components/OptionsSelector/optionsSelectorPropTypes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ const propTypes = {
7272
/** Whether to disable interactivity of option rows */
7373
isDisabled: PropTypes.bool,
7474

75+
/** Whether to disable focus options of rows */
76+
disableFocusOptions: PropTypes.bool,
77+
7578
/** Display the text of the option in bold font style */
7679
boldStyle: PropTypes.bool,
7780

@@ -163,6 +166,7 @@ const defaultProps = {
163166
shouldShowOptions: true,
164167
disableArrowKeysActions: false,
165168
isDisabled: false,
169+
disableFocusOptions: false,
166170
shouldHaveOptionSeparator: false,
167171
initiallyFocusedOptionKey: undefined,
168172
maxLength: CONST.SEARCH_MAX_LENGTH,

src/pages/WorkspaceSwitcherPage.js

Lines changed: 114 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
import PropTypes from 'prop-types';
2-
import React, {useCallback, useMemo} from 'react';
2+
import React, {useCallback, useEffect, useMemo, useState} from 'react';
33
import {View} from 'react-native';
44
import {withOnyx} from 'react-native-onyx';
55
import _ from 'underscore';
66
import HeaderPageLayout from '@components/HeaderPageLayout';
77
import * as Expensicons from '@components/Icon/Expensicons';
8-
import MenuItem from '@components/MenuItem';
98
import OptionRow from '@components/OptionRow';
109
import OptionsSelector from '@components/OptionsSelector';
11-
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
1210
import Text from '@components/Text';
1311
import useAutoFocusInput from '@hooks/useAutoFocusInput';
14-
import useLocalize from '@hooks/useLocalize';
1512
import useNetwork from '@hooks/useNetwork';
1613
import * as PolicyUtils from '@libs/PolicyUtils';
1714
import * as ReportUtils from '@libs/ReportUtils';
1815
import useTheme from '@styles/themes/useTheme';
1916
import useThemeStyles from '@styles/useThemeStyles';
2017
import * as Policy from '@userActions/Policy';
21-
import Icon from '@src/components/Icon';
2218
import CONST from '@src/CONST';
2319
import ONYXKEYS from '@src/ONYXKEYS';
2420
import SCREENS from '@src/SCREENS';
@@ -54,180 +50,164 @@ const defaultProps = {
5450
function WorkspaceSwitcherPage({policies, activeWorkspaceID}) {
5551
const theme = useTheme();
5652
const styles = useThemeStyles();
57-
const {translate} = useLocalize();
5853
const {isOffline} = useNetwork();
54+
const [selectedOption, setSelectedOption] = useState();
55+
const [searchTerm, setSearchTerm] = useState('');
5956

6057
const getIndicatorTypeForPolicy = useCallback(
6158
// TO DO: Wait for missing logic to be implemented in other PR
6259
// CONST.BRICK_ROAD_INDICATOR_STATUS.INFO or CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR
60+
// eslint-disable-next-line no-unused-vars
6361
(policyId) => undefined,
6462
[],
6563
);
6664

67-
const getMenuItem = useCallback(
68-
(item) => {
69-
const keyTitle = item.translationKey ? translate(item.translationKey) : item.title;
70-
71-
const option = {
72-
text: keyTitle,
73-
brickRoadIndicator: getIndicatorTypeForPolicy(item.policyId),
74-
icons: [
75-
{
76-
source: item.icon,
77-
type: item.iconType,
78-
fill: item.iconFill,
79-
name: keyTitle,
80-
fallbackIcon: item.fallbackIcon,
81-
},
82-
],
83-
};
84-
85-
// return (
86-
// <MenuItem
87-
// title={keyTitle}
88-
// icon={item.icon}
89-
// iconType={CONST.ICON_TYPE_WORKSPACE}
90-
// onPress={item.action}
91-
// iconStyles={item.iconStyles}
92-
// iconFill={item.iconFill}
93-
// fallbackIcon={item.fallbackIcon}
94-
// brickRoadIndicator={item.brickRoadIndicator}
95-
// disabled={item.disabled}
96-
// rightComponent={rightComponent}
97-
// shouldShowRightComponent={shouldShowRightComponent}
98-
// />
99-
// );
100-
101-
return (
102-
<OptionRow
103-
option={option}
104-
onSelectRow={item.action}
105-
showTitleTooltip={false}
106-
shouldShowSubscript={false}
107-
highlightSelected
108-
isSelected={item.policyId === activeWorkspaceID}
109-
/>
110-
);
111-
},
112-
[activeWorkspaceID, getIndicatorTypeForPolicy, translate],
65+
const hasUnreadData = useCallback(
66+
// TO DO: Implement checking if policy has some unread data
67+
// eslint-disable-next-line no-unused-vars
68+
(policyId) => false,
69+
[]
11370
);
11471

72+
const selectPolicy = useCallback((option) => {
73+
const policyID = option.policyID;
74+
Policy.selectWorkspace(policyID);
75+
76+
if (policyID) {
77+
setSelectedOption(option);
78+
} else {
79+
setSelectedOption(undefined);
80+
}
81+
}, []);
82+
83+
const onChangeText = useCallback((newSearchTerm) => {
84+
// TO DO: Handle searching logic
85+
setSearchTerm(newSearchTerm);
86+
}, [])
87+
11588
const usersWorkspaces = useMemo(
11689
() =>
11790
_.chain(policies)
11891
.filter((policy) => PolicyUtils.shouldShowPolicy(policy, isOffline))
11992
.map((policy) => ({
120-
title: policy.name,
121-
policyId: policy.id,
122-
icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name),
123-
iconType: CONST.ICON_TYPE_WORKSPACE,
124-
action: () => {
125-
Policy.selectWorkspace(policy.id);
126-
},
127-
fallbackIcon: Expensicons.FallbackWorkspaceAvatar,
128-
pendingAction: policy.pendingAction,
129-
errors: policy.errors,
130-
disabled: policy.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
93+
text: policy.name,
94+
policyID: policy.id,
95+
brickRoadIndicator: getIndicatorTypeForPolicy(policy.id),
96+
icons: [
97+
{
98+
source: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name),
99+
fallbackIcon: Expensicons.FallbackWorkspaceAvatar,
100+
name: policy.name,
101+
type: CONST.ICON_TYPE_WORKSPACE,
102+
},
103+
],
104+
boldStyle: hasUnreadData(policy.id),
131105
}))
132-
.sortBy((policy) => policy.title.toLowerCase())
106+
.sortBy((policy) => policy.text.toLowerCase())
133107
.value(),
134-
[policies, isOffline],
108+
[policies, isOffline, getIndicatorTypeForPolicy, hasUnreadData],
135109
);
136110

137111
const usersWorkspacesSectionData = useMemo(
138-
() => [
139-
{
112+
() => ({
140113
data: usersWorkspaces,
141114
shouldShow: true,
142115
indexOffset: 0,
143-
},
144-
],
116+
}),
145117
[usersWorkspaces],
146118
);
147119

148-
const allWorkspaces = useMemo(
149-
() => [
150-
{
151-
title: 'Expensify',
152-
icon: Expensicons.ExpensifyAppIcon,
153-
iconType: CONST.ICON_TYPE_AVATAR,
154-
action: () => {
155-
Policy.selectWorkspace(undefined);
120+
const everythingSection = useMemo(() => {
121+
const option = {
122+
text: 'Expensify',
123+
icons: [
124+
{
125+
source: Expensicons.ExpensifyAppIcon,
126+
name: 'Expensify',
127+
type: CONST.ICON_TYPE_AVATAR,
156128
},
157-
indicatorType: getIndicatorTypeForPolicy(undefined),
158-
},
159-
],
160-
[getIndicatorTypeForPolicy],
161-
);
129+
],
130+
brickRoadIndicator: getIndicatorTypeForPolicy(undefined),
131+
boldStyle: hasUnreadData(undefined),
132+
};
162133

163-
const getWorkspacesSection = useCallback(
164-
(workspaces, section, showAddWorkspaceButton) => (
165-
<View>
134+
return (
135+
<>
166136
<View style={[styles.mh4, styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, styles.mb3]}>
167137
<Text
168138
style={styles.label}
169139
color={theme.textSupporting}
170140
>
171-
{section}
141+
Everything
172142
</Text>
173-
{showAddWorkspaceButton && (
174-
<PressableWithFeedback accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON}>
175-
{({hovered}) => (
176-
<Icon
177-
src={Expensicons.Plus}
178-
width={12}
179-
height={12}
180-
additionalStyles={[styles.highlightBG, styles.borderRadiusNormal, styles.p2, hovered && styles.bordersBG]}
181-
/>
182-
)}
183-
</PressableWithFeedback>
184-
)}
185143
</View>
186-
<View style={{marginBottom: 12}}>{_.map(workspaces, (item, index) => getMenuItem(item, index))}</View>
187-
</View>
144+
<View>
145+
<OptionRow
146+
option={{...option, brickRoadIndicator: option.policyID === activeWorkspaceID ? undefined : option.brickRoadIndicator}}
147+
onSelectRow={selectPolicy}
148+
showTitleTooltip={false}
149+
shouldShowSubscript={false}
150+
highlightSelected
151+
isSelected={option.policyID === activeWorkspaceID}
152+
/>
153+
</View>
154+
</>
155+
);
156+
}, [activeWorkspaceID, getIndicatorTypeForPolicy, hasUnreadData, selectPolicy, styles.alignItemsCenter, styles.flexRow, styles.justifyContentBetween, styles.label, styles.mb3, styles.mh4, theme.textSupporting]);
157+
158+
const inputCallbackRef = useAutoFocusInput();
159+
const workspacesSection = useMemo(
160+
() => (
161+
<>
162+
<View style={[styles.mh4, styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, styles.mb1]}>
163+
<Text
164+
style={[styles.mt3, styles.label]}
165+
color={theme.textSupporting}
166+
>
167+
Workspaces
168+
</Text>
169+
</View>
170+
{/* TO DO: Display breadcrumb */}
171+
{usersWorkspacesSectionData.data.length === 0 && <View/>}
172+
<OptionsSelector
173+
ref={inputCallbackRef}
174+
sections={[usersWorkspacesSectionData]}
175+
value={searchTerm}
176+
shouldShowTextInput={usersWorkspacesSectionData.data.length > 8}
177+
onChangeText={onChangeText}
178+
selectedOptions={selectedOption ? [selectedOption] : []}
179+
onSelectRow={selectPolicy}
180+
boldStyle
181+
shouldPreventDefaultFocusOnSelectRow
182+
highlightSelectedOptions
183+
shouldShowOptions
184+
autoFocus={false}
185+
disableFocusOptions
186+
canSelectMultipleOptions={false}
187+
shouldShowSubscript={false}
188+
showTitleTooltip={false}
189+
contentContainerStyles={[styles.pt0, styles.mt0]}
190+
/>
191+
</>
188192
),
189-
[
190-
getMenuItem,
191-
styles.alignItemsCenter,
192-
styles.borderRadiusNormal,
193-
styles.bordersBG,
194-
styles.flexRow,
195-
styles.highlightBG,
196-
styles.justifyContentBetween,
197-
styles.label,
198-
styles.mb3,
199-
styles.mh4,
200-
styles.p2,
201-
theme.textSupporting,
202-
],
193+
[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],
203194
);
204195

205-
const allWorkspacesSection = useMemo(() => getWorkspacesSection(allWorkspaces, 'Everything', false, false), [allWorkspaces, getWorkspacesSection]);
206-
const usersWorkspacesSection = useMemo(() => getWorkspacesSection(usersWorkspaces, 'Workspaces', true, true), [getWorkspacesSection, usersWorkspaces]);
207-
208-
// const {inputCallbackRef} = useAutoFocusInput();
196+
useEffect(() => {
197+
if (!activeWorkspaceID) {
198+
return;
199+
}
200+
const optionToSet = _.find(usersWorkspaces, (option) => option.policyID === activeWorkspaceID);
201+
setSelectedOption(optionToSet);
202+
}, [activeWorkspaceID, usersWorkspaces]);
209203

210204
return (
211205
<HeaderPageLayout
212206
title="Choose a workspace"
213207
backgroundColor={theme.PAGE_THEMES[SCREENS.WORKSPACE_SELECTOR.ROOT].backgroundColor}
214208
>
215-
{allWorkspacesSection}
216-
{usersWorkspacesSection}
217-
{/* <OptionsSelector
218-
ref={inputCallbackRef}
219-
onAddToSelection={(option) => {}}
220-
sections={usersWorkspacesSectionData}
221-
selectedOptions={[]}
222-
value="Find"
223-
onSelectRow={(option) => {}}
224-
onChangeText
225-
headerMessage
226-
boldStyle
227-
shouldPreventDefaultFocusOnSelectRow
228-
shouldShowOptions
229-
autoFocus={false}
230-
/> */}
209+
{everythingSection}
210+
{workspacesSection}
231211
</HeaderPageLayout>
232212
);
233213
}

0 commit comments

Comments
 (0)