|
@@ -1,5 +1,6 @@
|
|
import React, { useEffect, useState } from 'react';
|
|
import React, { useEffect, useState } from 'react';
|
|
-import { AppBar, InputBase, Avatar, Divider, List, ListItem, ListItemAvatar, ListItemText, TextField, Toolbar, Typography } from '@material-ui/core';
|
|
|
|
|
|
+import { InputBase, Avatar, Divider, List, ListItem, ListItemAvatar, ListItemText, ListItemSecondaryAction, IconButton, Collapse, Toolbar, Typography } from '@material-ui/core';
|
|
|
|
+import { PersonAdd, PersonAddDisabled } from '@material-ui/icons';
|
|
import axios from 'axios';
|
|
import axios from 'axios';
|
|
import { useAuth0, withAuthenticationRequired } from "@auth0/auth0-react";
|
|
import { useAuth0, withAuthenticationRequired } from "@auth0/auth0-react";
|
|
import { makeStyles } from '@material-ui/styles';
|
|
import { makeStyles } from '@material-ui/styles';
|
|
@@ -8,7 +9,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import { faUser } from "@fortawesome/free-solid-svg-icons";
|
|
import { faUser } from "@fortawesome/free-solid-svg-icons";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useTranslation } from "react-i18next";
|
|
import SimpleCloseX from "../Buttons/SimpleCloseX";
|
|
import SimpleCloseX from "../Buttons/SimpleCloseX";
|
|
-import { func } from "prop-types";
|
|
|
|
|
|
+import { array, arrayOf, bool, func, shape } from "prop-types";
|
|
|
|
+import { SlidingTransitionLeft } from "../util";
|
|
|
|
|
|
const useStyles = makeStyles(theme => ({
|
|
const useStyles = makeStyles(theme => ({
|
|
userSearchBox: {
|
|
userSearchBox: {
|
|
@@ -18,6 +20,7 @@ const useStyles = makeStyles(theme => ({
|
|
top: 0,
|
|
top: 0,
|
|
left: 0,
|
|
left: 0,
|
|
width: '100%',
|
|
width: '100%',
|
|
|
|
+ height: 'calc(100% - ' + process.env.REACT_APP_NAV_BOTTOM_HEIGHT + 'px)',
|
|
},
|
|
},
|
|
navBarTextInput: {
|
|
navBarTextInput: {
|
|
backgroundColor: theme.palette.primary.main,
|
|
backgroundColor: theme.palette.primary.main,
|
|
@@ -50,9 +53,25 @@ const useStyles = makeStyles(theme => ({
|
|
display: 'flex',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
},
|
|
|
|
+ searchInput: {
|
|
|
|
+ color: '#ffffff',
|
|
|
|
+ },
|
|
|
|
+ listItemText: {
|
|
|
|
+ overflow: "hidden",
|
|
|
|
+ textOverflow: "ellipsis",
|
|
|
|
+ paddingRight: '0.5rem',
|
|
|
|
+ },
|
|
|
|
+ addFriend: {
|
|
|
|
+ color: theme.palette.primary.main,
|
|
|
|
+ },
|
|
|
|
+ removeFriend: {
|
|
|
|
+ color: theme.palette.error.main,
|
|
|
|
+ },
|
|
|
|
+ resultList: {
|
|
|
|
+ height: 'calc(100% - ' + process.env.REACT_APP_NAV_BOTTOM_HEIGHT + 'px)',
|
|
|
|
+ }
|
|
}));
|
|
}));
|
|
|
|
|
|
-const domain = process.env.REACT_APP_AUTH0_DOMAIN;
|
|
|
|
const serverURL = process.env.REACT_APP_SERVER_URL;
|
|
const serverURL = process.env.REACT_APP_SERVER_URL;
|
|
|
|
|
|
const UserSearch = (props) => {
|
|
const UserSearch = (props) => {
|
|
@@ -60,22 +79,50 @@ const UserSearch = (props) => {
|
|
const { user } = useAuth0();
|
|
const { user } = useAuth0();
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
|
|
|
|
|
+ const [, updateState] = React.useState();
|
|
|
|
+ const forceUpdate = React.useCallback(() => updateState({}), []);
|
|
|
|
+
|
|
const [userList, setUserList] = useState([]);
|
|
const [userList, setUserList] = useState([]);
|
|
const [query, setQuery] = useState('');
|
|
const [query, setQuery] = useState('');
|
|
- const { closeSearch } = props;
|
|
|
|
|
|
+
|
|
|
|
+ const { closeSearch, open, contacts, updateContacts, openContact } = props;
|
|
|
|
|
|
const getUsers = () => {
|
|
const getUsers = () => {
|
|
- if(!query) setUserList([]);
|
|
|
|
- axios.get(serverURL + '/users/fromQuery/' + query)
|
|
|
|
- .then(res => {
|
|
|
|
- console.log('result', res);
|
|
|
|
- let usersFound = res.data;
|
|
|
|
- usersFound = usersFound.filter(u => u.user_id !== user.sub);
|
|
|
|
- setUserList(usersFound);
|
|
|
|
- })
|
|
|
|
- .catch(err => {
|
|
|
|
- console.log(err.message);
|
|
|
|
- });
|
|
|
|
|
|
+ if (query) {
|
|
|
|
+ axios.get(serverURL + '/users/fromQuery/' + query)
|
|
|
|
+ .then(res => {
|
|
|
|
+ console.log('result', res);
|
|
|
|
+ let usersFound = res.data;
|
|
|
|
+ usersFound = usersFound.filter(u => u.user_id !== user.sub);
|
|
|
|
+ setUserList(usersFound);
|
|
|
|
+ })
|
|
|
|
+ .catch(err => {
|
|
|
|
+ console.log(err.message);
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ axios.get(serverURL + '/users/all/')
|
|
|
|
+ .then(res => {
|
|
|
|
+ console.log('result', res);
|
|
|
|
+ let usersFound = res.data;
|
|
|
|
+ usersFound = usersFound.filter(u => u.user_id !== user.sub);
|
|
|
|
+ setUserList(usersFound);
|
|
|
|
+ })
|
|
|
|
+ .catch(err => {
|
|
|
|
+ console.log(err.message);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const addFriend = (user) => {
|
|
|
|
+ const newFriends = contacts;
|
|
|
|
+ newFriends.push(user);
|
|
|
|
+ updateContacts(newFriends);
|
|
|
|
+ // forceUpdate();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const removeFriend = (userId) => {
|
|
|
|
+ const newFriends = contacts.filter(u => u.user_id !== userId);
|
|
|
|
+ updateContacts(newFriends);
|
|
}
|
|
}
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -84,6 +131,8 @@ const UserSearch = (props) => {
|
|
|
|
|
|
const getListItems = () => {
|
|
const getListItems = () => {
|
|
return userList.map(u => {
|
|
return userList.map(u => {
|
|
|
|
+ const userId = u.user_id;
|
|
|
|
+ const isContact = contacts.some(c => c.user_id === userId);
|
|
let avatar;
|
|
let avatar;
|
|
if (u.picture) {
|
|
if (u.picture) {
|
|
avatar = <Avatar alt={'profile picture of ' + user.name} src={u.picture} />;
|
|
avatar = <Avatar alt={'profile picture of ' + user.name} src={u.picture} />;
|
|
@@ -91,12 +140,19 @@ const UserSearch = (props) => {
|
|
avatar = (<Avatar><FontAwesomeIcon icon={faUser} /></Avatar>);
|
|
avatar = (<Avatar><FontAwesomeIcon icon={faUser} /></Avatar>);
|
|
}
|
|
}
|
|
return (
|
|
return (
|
|
- <div key={u.user_id}>
|
|
|
|
- <ListItem button onClick={() => {}}>
|
|
|
|
|
|
+ <div key={userId}>
|
|
|
|
+ <ListItem button onClick={() => {if (openContact) openContact(userId)}}>
|
|
<ListItemAvatar>
|
|
<ListItemAvatar>
|
|
{avatar}
|
|
{avatar}
|
|
</ListItemAvatar>
|
|
</ListItemAvatar>
|
|
- <ListItemText primary={u.name} />
|
|
|
|
|
|
+ <ListItemText primary={u.name} primaryTypographyProps={{ className: classes.listItemText }} />
|
|
|
|
+ <ListItemSecondaryAction>
|
|
|
|
+ <IconButton edge="end" onClick={() => isContact ? removeFriend(userId) : addFriend(u)}>
|
|
|
|
+ {isContact
|
|
|
|
+ ? <PersonAddDisabled className={classes.removeFriend} />
|
|
|
|
+ : <PersonAdd className={classes.addFriend} />}
|
|
|
|
+ </IconButton>
|
|
|
|
+ </ListItemSecondaryAction>
|
|
</ListItem>
|
|
</ListItem>
|
|
<Divider />
|
|
<Divider />
|
|
</div>
|
|
</div>
|
|
@@ -106,31 +162,33 @@ const UserSearch = (props) => {
|
|
|
|
|
|
return (
|
|
return (
|
|
<div className={classes.userSearchBox}>
|
|
<div className={classes.userSearchBox}>
|
|
-
|
|
|
|
<Toolbar className={classes.topNav}>
|
|
<Toolbar className={classes.topNav}>
|
|
<div className={classes.flexdiv}>
|
|
<div className={classes.flexdiv}>
|
|
- <InputBase value={query} name="query" onChange={e => setQuery(e.target.value)} label="Query" autoFocus />
|
|
|
|
- {/*<TextField value={query} name="query" />*/}
|
|
|
|
|
|
+ <InputBase value={query} name="query" className={classes.searchInput} onChange={e => setQuery(e.target.value)} label="Query" autoFocus />
|
|
</div>
|
|
</div>
|
|
<div className={classes.rightSide}>
|
|
<div className={classes.rightSide}>
|
|
<SimpleCloseX onClick={closeSearch} />
|
|
<SimpleCloseX onClick={closeSearch} />
|
|
</div>
|
|
</div>
|
|
</Toolbar>
|
|
</Toolbar>
|
|
|
|
|
|
-
|
|
|
|
- {userList.length === 0 ? <Typography className={classes.infoText}>{query ? t("No results") : ''} </Typography> :
|
|
|
|
- <List component="nav" className={classes.root} aria-label="u list">
|
|
|
|
- {getListItems()}
|
|
|
|
- <div />
|
|
|
|
- </List>
|
|
|
|
- }
|
|
|
|
|
|
+ <Collapse in={open && userList} className={classes.resultList}>
|
|
|
|
+ {userList.length === 0 ? <Typography className={classes.infoText}>{query ? t("No results") : ''} </Typography> :
|
|
|
|
+ <List component="nav" className={classes.root} aria-label="u list">
|
|
|
|
+ {getListItems()}
|
|
|
|
+ <div />
|
|
|
|
+ </List>
|
|
|
|
+ }
|
|
|
|
+ </Collapse>
|
|
</div>
|
|
</div>
|
|
- )
|
|
|
|
- ;
|
|
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
UserSearch.propTypes = {
|
|
UserSearch.propTypes = {
|
|
closeSearch: func.isRequired,
|
|
closeSearch: func.isRequired,
|
|
|
|
+ open: bool.isRequired,
|
|
|
|
+ contacts: arrayOf(shape({})),
|
|
|
|
+ updateContacts: func.isRequired,
|
|
|
|
+ openContact: func,
|
|
}
|
|
}
|
|
|
|
|
|
export default withAuthenticationRequired(UserSearch, {
|
|
export default withAuthenticationRequired(UserSearch, {
|