diff --git a/src/frontend/next/src/pages/search.tsx b/src/frontend/next/src/pages/search.tsx new file mode 100644 index 0000000000..5d3bfacedb --- /dev/null +++ b/src/frontend/next/src/pages/search.tsx @@ -0,0 +1,63 @@ +import { FormEvent, useState } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { useRouter } from 'next/router'; + +import SearchResults from '../components/SearchResults'; +import SearchBar from '../components/SearchBar'; +import BackToTopButton from '../components/BackToTopButton'; + +type FilterProp = { + filter: 'post' | 'author'; +}; + +const useStyles = makeStyles(() => ({ + anchor: { + position: 'absolute', + top: 0, + }, +})); + +const SearchPage = () => { + const classes = useStyles(); + const router = useRouter(); + // We synchronize the `text` and `filter` values to the URL's query string + // Router query object for a query can be an array if url becomes text=123&text=456 + // https://stackoverflow.com/questions/60110364/type-string-string-is-not-assignable-to-type-string + const [textParam = '', setTextParam] = useState( + Array.isArray(router.query.text) ? router.query.text[0] : router.query.text + ); + const [filterParam = 'post', setFilterParam] = useState( + router.query.filter === 'post' ? 'post' : 'author' + ); + + // We manage the state of `text` and `filter` internally, and update URL on + // form submit only. These are used in the , and the user can change them. + const [text, setText] = useState(''); + const [filter, setFilter] = useState('post'); + + // Form was submitted, so go ahead and sync to URL, (re)triggering search. + function onSubmitHandler(event: FormEvent) { + event.preventDefault(); + setTextParam(text); + setFilterParam(filter); + router.push(`/search?text=${text}&filter=${filter}`); + } + + return ( +
+
+ setText(value)} + filter={filter} + onFilterChange={(value: FilterProp['filter']) => setFilter(value)} + onSubmit={onSubmitHandler} + /> +
+ + +
+ ); +}; + +export default SearchPage;