mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 23:15:46 +01:00
✨ Add autocomplete to Search Module
Suggestions when searching with the search bar Fixes #12
This commit is contained in:
@@ -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(<Search />);
|
||||
const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q=';
|
||||
const textInput = useRef<HTMLInputElement>();
|
||||
// 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<any[]>([]);
|
||||
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 (
|
||||
<form
|
||||
onChange={() => {
|
||||
@@ -115,40 +102,31 @@ export default function SearchBar(props: any) {
|
||||
})}
|
||||
>
|
||||
<Popover
|
||||
opened={results}
|
||||
opened={opened}
|
||||
position="bottom"
|
||||
placement="start"
|
||||
width={260}
|
||||
withArrow
|
||||
radius="md"
|
||||
trapFocus={false}
|
||||
transition="pop-bottom-right"
|
||||
onFocusCapture={() => setOpened(true)}
|
||||
onBlurCapture={() => setOpened(false)}
|
||||
target={
|
||||
<Popover
|
||||
opened={opened}
|
||||
position="bottom"
|
||||
placement="start"
|
||||
width={260}
|
||||
withArrow
|
||||
<Autocomplete
|
||||
variant="filled"
|
||||
data={autocompleteData}
|
||||
icon={icon}
|
||||
ref={textInput}
|
||||
rightSectionWidth={90}
|
||||
rightSection={rightSection}
|
||||
radius="md"
|
||||
trapFocus={false}
|
||||
transition="pop-bottom-right"
|
||||
onFocusCapture={() => setOpened(true)}
|
||||
onBlurCapture={() => setOpened(false)}
|
||||
target={
|
||||
<TextInput
|
||||
variant="filled"
|
||||
icon={icon}
|
||||
ref={textInput}
|
||||
rightSectionWidth={90}
|
||||
rightSection={rightSection}
|
||||
radius="md"
|
||||
size="md"
|
||||
styles={{ rightSection: { pointerEvents: 'none' } }}
|
||||
placeholder="Search the web..."
|
||||
{...props}
|
||||
{...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>
|
||||
size="md"
|
||||
styles={{ rightSection: { pointerEvents: 'none' } }}
|
||||
placeholder="Search the web..."
|
||||
{...props}
|
||||
{...form.getInputProps('query')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
|
||||
Reference in New Issue
Block a user