|
4 | 4 |
|
5 | 5 | // Dependencies
|
6 | 6 | import React, { useEffect, useState } from 'react';
|
7 |
| -import { useLocation, useSearchParams, } from 'react-router-dom'; |
| 7 | +import { useSearchParams, } from 'react-router-dom'; |
8 | 8 | import Data from '../utils/data';
|
9 | 9 |
|
10 | 10 | // MUI
|
11 |
| -import { Box, styled, Typography, Divider, TextField, Checkbox } from '@mui/material'; |
| 11 | +import { Box, styled, Typography, Divider, TextField, Checkbox, Container, FormControlLabel, InputAdornment } from '@mui/material'; |
12 | 12 | import SearchIcon from '@mui/icons-material/Search';
|
13 | 13 |
|
14 | 14 | const Search = () => {
|
15 |
| - const [searchParams] = useSearchParams(); |
| 15 | + const [searchParams, setSearchParams] = useSearchParams(); |
16 | 16 | const [searchText, setSearchText] = useState(searchParams.get('q') || '');
|
17 |
| - const location = useLocation(); |
| 17 | + const [results, setResults] = useState([]); |
| 18 | + const [filter, searchFilter] = useState([]); |
18 | 19 |
|
19 |
| - useEffect(() => { }, []) |
| 20 | + useEffect(() => { |
| 21 | + const searchQuery = searchText.replace(/W+/g, '+'); |
| 22 | + searchParams.set('q', searchQuery) |
| 23 | + setSearchParams(searchParams) |
| 24 | + }, [searchText, searchParams, setSearchParams]); |
| 25 | + |
| 26 | + useEffect(() => { |
| 27 | + const filterQuery = filter.join(',').replace(/W+/g, ''); |
| 28 | + searchParams.set('filter', filterQuery) |
| 29 | + setSearchParams(searchParams) |
| 30 | + }, [filter, searchParams, setSearchParams]); |
| 31 | + |
| 32 | + useEffect(() => { |
| 33 | + const searchQuery = searchParams.get('q'); |
| 34 | + const filterQuery = searchParams.get('filter').split(","); |
| 35 | + setSearchText(searchQuery.replace('+', ' ')); |
| 36 | + searchFilter(filterQuery); |
| 37 | + }, [searchParams]); |
| 38 | + |
| 39 | + useEffect(() => { |
| 40 | + const handleSearchResources = async () => { |
| 41 | + try { |
| 42 | + let excluded = ['allSemesters', 'extraNotes']; |
| 43 | + if (!filter.includes('allSemesters')) excluded.splice(excluded.indexOf('allSemesters', 1)); |
| 44 | + if (!filter.includes('extraNotes')) excluded.splice(excluded.indexOf('extraNotes', 1)); |
| 45 | + const data = await Data.All.searchAllNotes(searchText, { excludes: excluded }); |
| 46 | + setResults(data); |
| 47 | + } catch (error) { |
| 48 | + setResults([]); |
| 49 | + } |
| 50 | + } |
| 51 | + if (searchText.length !== 0) handleSearchResources(); |
| 52 | + }, [searchText, filter]); |
| 53 | + |
| 54 | + const handleSearchInput = (e) => { |
| 55 | + setSearchText(e.target.value); |
| 56 | + } |
| 57 | + |
| 58 | + const handleFilter = (field) => (e) => { |
| 59 | + if (e.target.checked) searchFilter((prev) => prev.concat(field)) |
| 60 | + else searchFilter((prev) => prev.filter(val => val !== field)) |
| 61 | + } |
| 62 | + |
| 63 | + const handleClearSearch = () => { |
| 64 | + setSearchText(''); |
| 65 | + searchFilter([]); |
| 66 | + setResults([]); |
| 67 | + } |
20 | 68 |
|
21 | 69 | return (
|
22 | 70 | <Main>
|
23 | 71 | <Typography variant='h1' fontSize='4rem'>Search</Typography>
|
24 | 72 | <Divider />
|
| 73 | + <Container sx={{ display: 'flex', flexDirection: 'column', }}> |
| 74 | + <TextField |
| 75 | + type='text' |
| 76 | + label='Search resources' |
| 77 | + placeholder='Type to search relevant notes' |
| 78 | + onChange={handleSearchInput} |
| 79 | + value={searchText} |
| 80 | + fullWidth |
| 81 | + variant='filled' |
| 82 | + sx={{ my: 2, mx: 'auto', width: '80%' }} |
| 83 | + InputProps={{ |
| 84 | + endAdornment: (<InputAdornment position='end'> |
| 85 | + <SearchIcon /> |
| 86 | + </InputAdornment>) |
| 87 | + }} |
| 88 | + |
| 89 | + /> |
| 90 | + <Box sx={{ mb: 2, mx: 'auto', width: '80%' }}> |
| 91 | + <Typography>Search With:</Typography> |
| 92 | + <FormControlLabel control={<Checkbox onChange={handleFilter('allSemesters')} />} label='Semesters' /> |
| 93 | + <FormControlLabel control={<Checkbox onChange={handleFilter('extraNotes')} />} label='Extra Notes' /> |
| 94 | + {searchText.length > 0 && <Typography variant='caption' onClick={handleClearSearch} sx={{ color: 'red', textDecoration: 'underline', cursor: 'pointer' }}>Clear Search</Typography>} |
| 95 | + </Box> |
| 96 | + </Container> |
25 | 97 | </Main>
|
26 | 98 | )
|
27 | 99 | }
|
|
0 commit comments