-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathSearch.tsx
More file actions
97 lines (86 loc) · 2.7 KB
/
Search.tsx
File metadata and controls
97 lines (86 loc) · 2.7 KB
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
import { AutoComplete, Form as AntForm, Input, Popover as AntPopover } from "antd";
import debounce from "lodash.debounce";
import React, { useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import type { SearchQuery } from "../types";
import { useDb } from "../utils/useDb";
const autoCompleteStyle: React.CSSProperties = {
width: "100%",
};
const Hint = styled(AntPopover)`
margin-top: 25px;
margin-left: auto;
margin-right: auto;
display: block;
font-family: var(--font-family);
color: #95989a;
`;
const Popover = styled.div`
font-family: var(--font-family);
width: 375px;
`;
interface SearchProps {
onSubmit: (query: SearchQuery) => void;
initialSearchValue?: string;
}
export default function Search({ onSubmit, initialSearchValue: initialSearch = "" }: SearchProps) {
const hintContent = (
<Popover>
<p>You can search for:</p>
<ul>
<li>A specific section: CS 1337.002</li>
<li>A whole course: CS 1337</li>
<li>A professor's name: Jason Smith</li>
<li>A specific semester: CS 1337 Fall 2021</li>
<li>Everything together: CS 1337.002 Fall 2021 Jason Smith</li>
</ul>
</Popover>
);
const [searchValue, setSearchValue] = useState(initialSearch);
const [options, setOptions] = useState<{ value: string }[]>([]);
const { data: db } = useDb();
const fetchOptions = useMemo(
() =>
debounce((partialQuery: string) => {
if (db && partialQuery) {
const strings = db.getSectionStrings(partialQuery);
setOptions(strings.map((value) => ({ value })));
}
}, 300),
[db]
);
// Set search value to initialSearch when it gets populated in Router
useEffect(() => {
setSearchValue(initialSearch);
}, [initialSearch]);
function onChange(value: string) {
setSearchValue(value);
fetchOptions(value);
}
return (
<AntForm>
<AutoComplete
options={options}
style={autoCompleteStyle}
// TODO: find a better type than unknown
onSelect={(value: unknown) => onSubmit({ search: value as string })}
onChange={(value: unknown) => onChange(value as string)}
value={searchValue}
>
<Input.Search
id="search-bar"
onSearch={(search) => onSubmit({ search })}
name="search"
size="large"
placeholder="ex. CS 1337 Fall 2017 Smith"
/>
</AutoComplete>
<Hint content={hintContent} placement="bottom">
<span style={{ textAlign: "center" }}>
Need to know what you can enter?{" "}
<span style={{ textDecoration: "underline" }}>Pretty much anything.</span>
</span>
</Hint>
</AntForm>
);
}