From 39d66faf4eb4098f12f23700b7cb4e2a568df660 Mon Sep 17 00:00:00 2001 From: ajnart Date: Mon, 6 Jun 2022 20:02:21 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20autocomplete=20to=20Search=20?= =?UTF-8?q?Module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggestions when searching with the search bar Fixes #12 --- .../modules/search/SearchModule.tsx | 86 +++++++------------ src/pages/api/modules/search.ts | 19 ++++ 2 files changed, 51 insertions(+), 54 deletions(-) create mode 100644 src/pages/api/modules/search.ts diff --git a/src/components/modules/search/SearchModule.tsx b/src/components/modules/search/SearchModule.tsx index df46ce75d..85ca6adf5 100644 --- a/src/components/modules/search/SearchModule.tsx +++ b/src/components/modules/search/SearchModule.tsx @@ -1,10 +1,4 @@ -import { - Kbd, - createStyles, - Text, - Popover, - TextInput, -} from '@mantine/core'; +import { Kbd, createStyles, Text, Popover, Autocomplete } from '@mantine/core'; import { useDebouncedValue, useForm, useHotkeys } from '@mantine/hooks'; import { useEffect, useRef, useState } from 'react'; import { @@ -36,13 +30,10 @@ export const SearchModule: IModule = { export default function SearchBar(props: any) { const { config, setConfig } = useConfig(); const [opened, setOpened] = useState(false); - const [results, setOpenedResults] = useState(false); const [icon, setIcon] = useState(); const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q='; const textInput = useRef(); // Find a service with the type of 'Overseerr' - const service = config.services.find((s) => s.type === 'Overseerr'); - const form = useForm({ initialValues: { query: '', @@ -50,19 +41,12 @@ export default function SearchBar(props: any) { }); const [debounced, cancel] = useDebouncedValue(form.values.query, 250); - const [data, setData] = useState([]); + const [results, setResults] = useState([]); useEffect(() => { if (form.values.query !== debounced || form.values.query === '') return; - setOpened(false); - setOpenedResults(true); - if (service) { - const serviceUrl = new URL(service.url); - axios - .post(`/api/modules/overseerr?query=${form.values.query}`, { - service, - }) - .then((res) => setData(res.data.results ?? [])); - } + axios + .get(`/api/modules/search?q=${form.values.query}`) + .then((res) => setResults(res.data ?? [])); }, [debounced]); useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]); const { classes, cx } = useStyles(); @@ -82,7 +66,10 @@ export default function SearchBar(props: any) { return null; } - // Data with label as item.name + const autocompleteData = results.map((result) => ({ + label: result.phrase, + value: result.phrase, + })); return (
{ @@ -115,40 +102,31 @@ export default function SearchBar(props: any) { })} > setOpened(true)} + onBlurCapture={() => setOpened(false)} target={ - setOpened(true)} - onBlurCapture={() => setOpened(false)} - target={ - - } - > - - tip: Use the prefixes !yt and !t in front of your query to search on - YouTube or for a Torrent respectively. - - + size="md" + styles={{ rightSection: { pointerEvents: 'none' } }} + placeholder="Search the web..." + {...props} + {...form.getInputProps('query')} + /> } > diff --git a/src/pages/api/modules/search.ts b/src/pages/api/modules/search.ts new file mode 100644 index 000000000..e5dfd1309 --- /dev/null +++ b/src/pages/api/modules/search.ts @@ -0,0 +1,19 @@ +import axios from 'axios'; +import { NextApiRequest, NextApiResponse } from 'next'; + +async function Get(req: NextApiRequest, res: NextApiResponse) { + const { q } = req.query; + const response = await axios.get(`https://duckduckgo.com/ac/?q=${q}`); + res.status(200).json(response.data); +} + +export default async (req: NextApiRequest, res: NextApiResponse) => { + // Filter out if the reuqest is a POST or a GET + if (req.method === 'GET') { + return Get(req, res); + } + return res.status(405).json({ + statusCode: 405, + message: 'Method not allowed', + }); +};