Add autocomplete to Search Module

Suggestions when searching with the search bar Fixes #12
This commit is contained in:
ajnart
2022-06-06 20:02:21 +02:00
parent c50e11c75b
commit 39d66faf4e
2 changed files with 51 additions and 54 deletions

View File

@@ -1,10 +1,4 @@
import { import { Kbd, createStyles, Text, Popover, Autocomplete } from '@mantine/core';
Kbd,
createStyles,
Text,
Popover,
TextInput,
} from '@mantine/core';
import { useDebouncedValue, useForm, useHotkeys } from '@mantine/hooks'; import { useDebouncedValue, useForm, useHotkeys } from '@mantine/hooks';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { import {
@@ -36,13 +30,10 @@ export const SearchModule: IModule = {
export default function SearchBar(props: any) { export default function SearchBar(props: any) {
const { config, setConfig } = useConfig(); const { config, setConfig } = useConfig();
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
const [results, setOpenedResults] = useState(false);
const [icon, setIcon] = useState(<Search />); const [icon, setIcon] = useState(<Search />);
const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q='; const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q=';
const textInput = useRef<HTMLInputElement>(); const textInput = useRef<HTMLInputElement>();
// Find a service with the type of 'Overseerr' // Find a service with the type of 'Overseerr'
const service = config.services.find((s) => s.type === 'Overseerr');
const form = useForm({ const form = useForm({
initialValues: { initialValues: {
query: '', query: '',
@@ -50,19 +41,12 @@ export default function SearchBar(props: any) {
}); });
const [debounced, cancel] = useDebouncedValue(form.values.query, 250); const [debounced, cancel] = useDebouncedValue(form.values.query, 250);
const [data, setData] = useState([]); const [results, setResults] = useState<any[]>([]);
useEffect(() => { useEffect(() => {
if (form.values.query !== debounced || form.values.query === '') return; if (form.values.query !== debounced || form.values.query === '') return;
setOpened(false);
setOpenedResults(true);
if (service) {
const serviceUrl = new URL(service.url);
axios axios
.post(`/api/modules/overseerr?query=${form.values.query}`, { .get(`/api/modules/search?q=${form.values.query}`)
service, .then((res) => setResults(res.data ?? []));
})
.then((res) => setData(res.data.results ?? []));
}
}, [debounced]); }, [debounced]);
useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]); useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]);
const { classes, cx } = useStyles(); const { classes, cx } = useStyles();
@@ -82,7 +66,10 @@ export default function SearchBar(props: any) {
return null; return null;
} }
// Data with label as item.name const autocompleteData = results.map((result) => ({
label: result.phrase,
value: result.phrase,
}));
return ( return (
<form <form
onChange={() => { onChange={() => {
@@ -114,9 +101,6 @@ export default function SearchBar(props: any) {
}, 20); }, 20);
})} })}
> >
<Popover
opened={results}
target={
<Popover <Popover
opened={opened} opened={opened}
position="bottom" position="bottom"
@@ -129,8 +113,9 @@ export default function SearchBar(props: any) {
onFocusCapture={() => setOpened(true)} onFocusCapture={() => setOpened(true)}
onBlurCapture={() => setOpened(false)} onBlurCapture={() => setOpened(false)}
target={ target={
<TextInput <Autocomplete
variant="filled" variant="filled"
data={autocompleteData}
icon={icon} icon={icon}
ref={textInput} ref={textInput}
rightSectionWidth={90} rightSectionWidth={90}
@@ -143,13 +128,6 @@ export default function SearchBar(props: any) {
{...form.getInputProps('query')} {...form.getInputProps('query')}
/> />
} }
>
<Text>
tip: Use the prefixes <b>!yt</b> and <b>!t</b> in front of your query to search on
YouTube or for a Torrent respectively.
</Text>
</Popover>
}
> >
<Text> <Text>
Tip: Use the prefixes <b>!yt</b> and <b>!t</b> in front of your query to search on YouTube Tip: Use the prefixes <b>!yt</b> and <b>!t</b> in front of your query to search on YouTube

View File

@@ -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',
});
};