aboutsummaryrefslogtreecommitdiff
path: root/src/components/Header/SearchBar.tsx
blob: 2be8f6f3260b5844ab44ea1ca8c401ebe468f7ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import React, { useState, useEffect } from 'react';
import SearchIcon from '@material-ui/icons/Search';
import {
  InputBase,
  List,
  ListItem,
  Paper,
  Divider,
  ClickAwayListener
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { User } from 'which-types';
import { get } from '../../requests';
import UserStrip from '../UserStrip/UserStrip';

interface PropTypes {
  navigate: (prefix: string, id: string) => void;
}

const INTERVAL = 300;

const useStyles = makeStyles(theme => ({
  root: {
    position: 'relative',
    background: 'rgba(255, 255, 255, 0.5)',
    borderRadius: '2px',
    padding: theme.spacing(0.5),
    display: 'flex',
    alignItems: 'center'
  },
  results: {
    position: 'absolute',
    width: '100%',
    top: theme.spacing(5)
  }
}));

const SearchBar: React.FC<PropTypes> = ({ navigate }) => {
  const [query, setQuery] = useState<string>('');
  const [results, setResults] = useState<User[]>([]);
  const [isReady, setIsReady] = useState<boolean>(true);
  const [shouldRefetch, setShouldRefetch] = useState<boolean>(false);
  const classes = useStyles();

  const sleep = () => {
    setIsReady(false);
    setTimeout(() => setIsReady(true), INTERVAL);
  };

  const fetchPolls = () => {
    sleep();
    get(`/users?username[$regex]=${query}`).then(response => {
      setResults(response.data);
    });
  };

  useEffect(() => {
    if (isReady && shouldRefetch) {
      fetchPolls();
      setShouldRefetch(false);
    }
  }, [isReady]);


  const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
    setQuery(event.target.value);
    if (isReady) fetchPolls();
    else setShouldRefetch(true);
  };

  const handleClose = () => {
    setQuery('');
    setResults([]);
  };

  const handleNavigate = (index: number) => () => {
    navigate('profile', results[index]._id);
    handleClose();
  };

  const SearchResults = (
    <ClickAwayListener onClickAway={handleClose}>
      <Paper className={classes.results}>
        <List>
          {
          results.map((result, index) => (
            <>
              <ListItem button onClick={handleNavigate(index)}>
                <UserStrip user={result} navigate={navigate} />
              </ListItem>
              {(index < results.length - 1) && <Divider />}
            </>
          ))
        }
        </List>
      </Paper>
    </ClickAwayListener>
  );

  return (
    <div className={classes.root}>
      <SearchIcon />
      <InputBase
        placeholder="Search..."
        value={query}
        onChange={handleChange}
      />
      {results.length > 0 && SearchResults}
    </div>
  );
};


export default SearchBar;