Skip to content

Commit

Permalink
Merge pull request #30 from DaleMcGrew/Dale-WCC-Feb15-2025
Browse files Browse the repository at this point in the history
Implemented search on Teams page, which returns people or teams matching the search terms. Updated SearchBase to set autofocus on the search box. Now unsetting addPersonDrawerTeam team when closing AddPersonDrawer. Started implementing new UX team designs.
  • Loading branch information
DaleMcGrew authored Feb 16, 2025
2 parents 7fb604f + 84f3c7c commit 4f957e7
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 153 deletions.
20 changes: 14 additions & 6 deletions src/js/common/components/Search/SearchBase.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, { createRef } from 'react';
import styled from 'styled-components';
import colors from '../Style/Colors';
import normalizedImagePath from '../../utils/normalizedImagePath';
Expand All @@ -11,6 +11,13 @@ class SearchBase extends React.Component {
constructor (props) {
super(props);
this.state = { searchText: '' };
this.inputRef = createRef();
}

componentDidMount () {
if (this.inputRef.current) {
this.inputRef.current.focus();
}
}

handleInputChange = (event) => {
Expand Down Expand Up @@ -40,12 +47,14 @@ class SearchBase extends React.Component {
<SearchBaseWrapper>
{!this.state.searchText && <SearchIcon />}
<SearchInput
type="search"
placeholder={this.props.placeholder}
value={this.state.searchText}
autoFocus
maxLength={50}
onBlur={this.props.onBlur}
onChange={this.handleInputChange}
maxLength={50}
placeholder={this.props.placeholder}
ref={this.inputRef}
type="search"
value={this.state.searchText}
/>
{this.state.searchText && <ClearButton onClick={this.handleClear} />}
</SearchBaseWrapper>
Expand Down Expand Up @@ -110,7 +119,6 @@ const SearchInput = styled('input')`
padding-right: 40px;
padding-left: 12px;
&:focus-visible {
border: none;
outline: ${colors.primary} solid 2px !important;
Expand Down
9 changes: 8 additions & 1 deletion src/js/components/Drawers/AddPersonDrawer.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import React from 'react';
import { renderLog } from '../../common/utils/logging';
import AddPersonDrawerMainContent from '../Person/AddPersonDrawerMainContent';
import { useConnectAppContext } from '../../contexts/ConnectAppContext';
import DrawerTemplateA from './DrawerTemplateA';


const AddPersonDrawer = () => {
renderLog('AddPersonDrawer'); // Set LOG_RENDER_EVENTS to log all renders
const { getAppContextValue, setAppContextValue } = useConnectAppContext();

const onDrawerClose = () => {
setAppContextValue('addPersonDrawerTeam', undefined);
};

return (
<DrawerTemplateA
drawerId="addPersonDrawer"
drawerOpenGlobalVariableName="addPersonDrawerOpen"
mainContentJsx={<AddPersonDrawerMainContent />}
headerTitleJsx={<>Add Team Member</>}
headerTitleJsx={<>{getAppContextValue('AddPersonDrawerLabel')}</>}
headerFixedJsx={<></>}
onDrawerClose={onDrawerClose}
/>
);
};
Expand Down
15 changes: 12 additions & 3 deletions src/js/components/Drawers/DrawerTemplateA.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { cordovaDrawerTopMargin } from '../../utils/cordovaOffsets';
import { DrawerHeaderAnimateDownInnerContainer, DrawerHeaderAnimateDownOuterContainer, DrawerHeaderWrapper, DrawerTitle } from '../Style/drawerLayoutStyles';


const DrawerTemplateA = ({ classes, drawerId, drawerOpenGlobalVariableName, headerFixedJsx, headerTitleJsx, mainContentJsx }) => { // classes, teamId
const DrawerTemplateA = (props) => {
const { classes, drawerId, drawerOpenGlobalVariableName, headerFixedJsx, headerTitleJsx, mainContentJsx, onDrawerClose } = props;
renderLog(`DrawerTemplateA (${drawerId})`); // Set LOG_RENDER_EVENTS to log all renders
const { getAppContextData, setAppContextValue, getAppContextValue } = useConnectAppContext();

Expand All @@ -31,6 +32,13 @@ const DrawerTemplateA = ({ classes, drawerId, drawerOpenGlobalVariableName, head
}
};

const onDrawerCloseLocal = () => {
setAppContextValue(drawerOpenGlobalVariableName, false);
if (onDrawerClose) {
onDrawerClose();
}
};

useEffect(() => {
// console.log('DrawerTemplateA: Context value changed: ',
// drawerId, drawerOpenGlobalVariableName, getAppContextValue(drawerOpenGlobalVariableName));
Expand Down Expand Up @@ -61,7 +69,7 @@ const DrawerTemplateA = ({ classes, drawerId, drawerOpenGlobalVariableName, head
classes={{ paper: classes.drawer }}
direction="left"
id={drawerId}
onClose={() => setAppContextValue(drawerOpenGlobalVariableName, false)}
onClose={onDrawerCloseLocal}
open={drawerOpen}
>
<DrawerHeaderWrapper>
Expand All @@ -73,7 +81,7 @@ const DrawerTemplateA = ({ classes, drawerId, drawerOpenGlobalVariableName, head
aria-label="Close"
className={classes.closeButton}
id={`${drawerId}Close`}
onClick={() => setAppContextValue(drawerOpenGlobalVariableName, false)}
onClick={onDrawerCloseLocal}
size="large"
>
<span className="u-cursor--pointer">
Expand All @@ -100,6 +108,7 @@ DrawerTemplateA.propTypes = {
mainContentJsx: PropTypes.object,
headerTitleJsx: PropTypes.object,
headerFixedJsx: PropTypes.object,
onDrawerClose: PropTypes.func,
};

const styles = () => ({
Expand Down
106 changes: 63 additions & 43 deletions src/js/components/Person/AddPersonDrawerMainContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled from 'styled-components';
import arrayContains from '../../common/utils/arrayContains';
import { renderLog } from '../../common/utils/logging';
import { useConnectAppContext } from '../../contexts/ConnectAppContext';
import { getTeamMembersListByTeamId } from '../../models/TeamModel';
import makeRequestParams from '../../react-query/makeRequestParams';
import { useAddPersonToTeamMutation } from '../../react-query/mutations';
import { SpanWithLinkStyle } from '../Style/linkStyles';
Expand All @@ -13,50 +14,68 @@ import AddPersonForm from './AddPersonForm';
const AddPersonDrawerMainContent = () => {
renderLog('AddPersonDrawerMainContent');
const { apiDataCache, getAppContextValue } = useConnectAppContext();
const { allPeopleCache } = apiDataCache;
const { allPeopleCache, allTeamsCache } = apiDataCache;
const { mutate } = useAddPersonToTeamMutation();

// const params = useParams();
// console.log('AddPersonDrawerMainContent params: ', params);

const [addToTeamList, setAddToTeamList] = useState([]);
const [allPeopleList, setAllPeopleList] = useState([]);
const [remainingPeopleToAdd, setRemainingPeopleToAdd] = useState([]);
const [searchResultsList, setSearchResultsList] = useState(undefined);
const [thisTeamsCurrentMembersList] = useState(getAppContextValue('addPersonDrawerTeamMemberList'));
const [thisTeamsCurrentMembersList, setThisTeamsCurrentMembersList] = useState([]);
const [team] = useState(getAppContextValue('addPersonDrawerTeam'));
const [teamMemberPersonIdList] = useState([]);
const [matchingCountText, setMatchingCountText] = useState('');

const searchStringRef = useRef('');

const initializeRemainingPeopleToAddList = () => {
const updateRemainingPeopleToAdd = () => {
// console.log('initializeTheRemainingPeopleToAddListList in AddPersonDrawerMainContent');
// Start with the passed in allPeopleList, create the remainingPeopleToAddList, by removing any people already on the team
if (allPeopleList && allPeopleList.length > 0) {
const personToDisplay = [];
allPeopleList.forEach((onePeople) => {
const isOnTeam = thisTeamsCurrentMembersList.some((obj) => obj.id === onePeople.id);
if (allPeopleList && allPeopleList.length > 0 && thisTeamsCurrentMembersList && thisTeamsCurrentMembersList.length >= 0) {
const remainingPeopleToAddTemp = [];
allPeopleList.forEach((onePerson) => {
const isOnTeam = thisTeamsCurrentMembersList.some((obj) => obj.id === onePerson.personId);
if (!isOnTeam) {
personToDisplay.push(onePeople);
remainingPeopleToAddTemp.push(onePerson);
}
});
setRemainingPeopleToAdd(personToDisplay);
setRemainingPeopleToAdd(remainingPeopleToAddTemp);
}
};

useEffect(() => {
initializeRemainingPeopleToAddList();
}, [apiDataCache]);
setAllPeopleList(Object.values(allPeopleCache));
}, [allPeopleCache]);

useEffect(() => {
initializeRemainingPeopleToAddList();
}, [allPeopleList]);
const teamId = team ? team.teamId : -1;
if (teamId >= 0) {
const teamMembersListTemp = getTeamMembersListByTeamId(teamId, apiDataCache);
// console.log('useEffect in AddPersonDrawerMainContent teamMembersListTemp:', teamMembersListTemp);
setThisTeamsCurrentMembersList(teamMembersListTemp);
} else {
console.log('useEffect in AddPersonDrawerMainContent teamId is -1, so no teamId');
}
}, [allPeopleCache, allPeopleList, allTeamsCache, team]);

useEffect(() => {
updateRemainingPeopleToAdd();
}, [thisTeamsCurrentMembersList]);

useEffect(() => {
// console.log('useEffect in AddPersonDrawerMainContent allPeopleCache:', allPeopleCache);
// TODO: Need to deal with preferred name searching and display, very possible but it will get more complicated
let addToTeamListTemp = searchResultsList || remainingPeopleToAdd || [];
addToTeamListTemp = addToTeamListTemp.filter((person) => person.firstName.length || person.lastName.length);
setAddToTeamList(addToTeamListTemp);
}, [searchResultsList, remainingPeopleToAdd]);

useEffect(() => {
// console.log('== INITIAL useEffect in AddPersonDrawerMainContent');
if (allPeopleCache) {
setAllPeopleList(Object.values(allPeopleCache));
setRemainingPeopleToAdd(Object.values(allPeopleCache)); // handles navigate to issues
}
}, []);

Expand Down Expand Up @@ -84,50 +103,51 @@ const AddPersonDrawerMainContent = () => {
}
};

const addClicked = (person) => {
const addClicked = (incomingPerson) => {
const personId = incomingPerson ? incomingPerson.personId : -1;
const teamId = team ? team.teamId : -1;
const teamName = team ? team.teamName : '';
const plainParams = {
personId: person.id,
teamId: team.teamId,
teamMemberFirstName: person.firstName,
teamMemberLastName: person.lastName,
teamName: team.teamName,
personId,
teamId,
teamMemberFirstName: incomingPerson.firstName,
teamMemberLastName: incomingPerson.lastName,
teamName,
};
mutate(makeRequestParams(plainParams, {}));
// Remove this person from the All People less Adds list (since they were added to the team)
const updatedRemainingPeopleToAdd = remainingPeopleToAdd.filter((person) => person.id !== person.id);
const updatedRemainingPeopleToAdd = remainingPeopleToAdd.filter((person) => person.personId !== incomingPerson.personId);
setRemainingPeopleToAdd(updatedRemainingPeopleToAdd);
if (searchResultsList && searchResultsList.length) {
if (searchResultsList && searchResultsList.length >= 0) {
// also remove them from the searchResultsList if it exists
const updatedSearchResultsList = searchResultsList.filter((person) => person.id !== person.id);
const updatedSearchResultsList = searchResultsList.filter((person) => person.personId !== incomingPerson.personId);
setSearchResultsList(updatedSearchResultsList);
setMatchingCounter(updatedSearchResultsList);
}
};

// TODO: Need to deal with preferred name searching and display, very possible but it will get more complicated
let displayList = searchResultsList || remainingPeopleToAdd || [];
displayList = displayList.filter((person) => person.firstName.length || person.lastName.length);

return (
<AddPersonDrawerMainContentWrapper>
<SearchBarWrapper>
<TextField
id="search_input"
label="Search for team members"
inputRef={searchStringRef}
name="searchByName"
onChange={searchFunction}
placeholder="Search by name"
defaultValue=""
sx={{ minWidth: '250px' }}
/>
<MatchingPerson>{matchingCountText}</MatchingPerson>
</SearchBarWrapper>
{(displayList && displayList.length > 0) && (
{team && team.teamId >= 0 && (
<SearchBarWrapper>
<TextField
id="search_input"
label="Search for team members"
inputRef={searchStringRef}
name="searchByName"
onChange={searchFunction}
placeholder="Search by name"
defaultValue=""
sx={{ minWidth: '250px' }}
/>
<MatchingPerson>{matchingCountText}</MatchingPerson>
</SearchBarWrapper>
)}
{(addToTeamList && addToTeamList.length > 0) && (
<PersonSearchResultsWrapper>
<PersonListTitle>{ searchResultsList ? 'Filtered list of people to add to team: ' : 'Can be added to team: '}</PersonListTitle>
<PersonList>
{displayList.map((person) => (
{addToTeamList.map((person) => (
<PersonItem key={`personResult-${person.id}`}>
{person.firstName}
{' '}
Expand Down
15 changes: 9 additions & 6 deletions src/js/components/Person/AddPersonForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { usePersonSaveMutation } from '../../react-query/mutations';

const AddPersonForm = ({ classes }) => { // classes, teamId
renderLog('AddPersonForm');
const { getAppContextValue } = useConnectAppContext();
const { getAppContextValue, setAppContextValue } = useConnectAppContext();
const { mutate } = usePersonSaveMutation();

const [teamId, setTeamId] = useState(-1);
Expand All @@ -23,10 +23,11 @@ const AddPersonForm = ({ classes }) => { // classes, teamId

useEffect(() => { // Replaces onAppObservableStoreChange and will be called whenever the context value changes
// console.log('AddPersonForm: Context value changed:', true);
setTeamId(getAppContextValue('addPersonDrawerTeam').id);
setTeamName(getAppContextValue('addPersonDrawerTeam').teamName);
}, []);
// }, [getAppContextValue]); // TODO DALE: commented out for now to avoid infinite loop
if (getAppContextValue('addPersonDrawerTeam')) {
setTeamId(getAppContextValue('addPersonDrawerTeam').id);
setTeamName(getAppContextValue('addPersonDrawerTeam').teamName);
}
}, [getAppContextValue]);


const saveNewPerson = () => {
Expand All @@ -41,6 +42,9 @@ const AddPersonForm = ({ classes }) => { // classes, teamId
teamName,
};
mutate(makeRequestParams(plainParams, data));
setAppContextValue('addPersonDrawerOpen', false);
setAppContextValue('addPersonDrawerLabel', '');
setAppContextValue('addPersonDrawerTeam', undefined);
};

const updateSaveButton = () => {
Expand All @@ -53,7 +57,6 @@ const AddPersonForm = ({ classes }) => { // classes, teamId
}
};


return (
<AddPersonFormWrapper>
<FormControl classes={{ root: classes.formControl }}>
Expand Down
15 changes: 1 addition & 14 deletions src/js/components/Person/EditPersonDrawerMainContent.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import styled from 'styled-components';
import { renderLog } from '../../common/utils/logging';
import { useConnectAppContext } from '../../contexts/ConnectAppContext';
import EditPersonForm from './EditPersonForm';


const EditPersonDrawerMainContent = () => {
renderLog('EditPersonDrawerMainContent');
const { getAppContextValue } = useConnectAppContext();

// eslint-disable-next-line no-unused-vars
const [teamId, setTeamId] = useState(-1);

useEffect(() => { // Replaces onAppObservableStoreChange and will be called whenever the context value changes
// console.log('EditPersonDrawerMainContent: Context value changed:', true);
// 2/14/25 warning React Hook useEffect contains a call to 'setTeamId'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [getAppContextValue] as a second argument to the useEffect Hook react-hooks/exhaustive-deps
const teamIdTemp = getAppContextValue('editPersonDrawerTeamId');
setTeamId(teamIdTemp);
});
// }, [getAppContextValue]); // TODO DALE: commented out for now to avoid infinite loop

return (
<EditPersonDrawerMainContentWrapper>
Expand Down
8 changes: 4 additions & 4 deletions src/js/components/Team/AddTeamDrawerMainContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const AddTeamDrawerMainContent = ({ classes }) => { // classes, teamId
const [allTeamsList] = useState(Object.values(allTeamsCache));
const [teamSearchResultsList, setTeamSearchResultsList] = useState([]);

const clearFunction = () => {
setTeamSearchResultsList([]);
};

const searchFunction = (incomingSearchText) => {
// console.log('AddTeamDrawerMainContent searchFunction incomingSearchText: ', incomingSearchText);
const isSearching = (incomingSearchText && incomingSearchText.length > 0);
Expand All @@ -39,10 +43,6 @@ const AddTeamDrawerMainContent = ({ classes }) => { // classes, teamId
}
};

const clearFunction = () => {
setTeamSearchResultsList([]);
};

return (
<AddTeamDrawerMainContentWrapper>
<SearchBarWrapper>
Expand Down
Loading

0 comments on commit 4f957e7

Please sign in to comment.