search
This commit is contained in:
parent
a7e4e82765
commit
66a770faec
2 changed files with 87 additions and 7 deletions
|
@ -6,10 +6,15 @@
|
|||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
min-width: 500px;
|
||||
width: 500px;
|
||||
min-height: 200px;
|
||||
|
||||
padding: 12px;
|
||||
padding: 6px;
|
||||
|
||||
text-wrap: wrap;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.entry {
|
||||
|
@ -18,4 +23,31 @@
|
|||
border-radius: 4px;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.searchResults {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.searchResult {
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
text-align: left;
|
||||
background-color: unset;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: .75rem;
|
||||
}
|
||||
}
|
|
@ -11,10 +11,18 @@ import {
|
|||
useFocus,
|
||||
useInteractions,
|
||||
} from "@floating-ui/react";
|
||||
import { useState } from "react";
|
||||
import { useDebounce } from "use-debounce";
|
||||
import { useEffect, useState } from "react";
|
||||
import { atom, useAtom, useSetAtom } from "jotai";
|
||||
import { nodesOpenedAtom } from "../App";
|
||||
|
||||
const searchQueryAtom = atom("");
|
||||
const showMenuAtom = atom(false);
|
||||
|
||||
export default function SearchBar() {
|
||||
const [showMenu, setShowMenu] = useState(() => false);
|
||||
const [showMenu, setShowMenu] = useAtom(showMenuAtom);
|
||||
const [searchQuery, setSearchQuery] = useAtom(searchQueryAtom);
|
||||
const [searchResults, setSearchResults] = useState([]);
|
||||
|
||||
const { refs, context, floatingStyles } = useFloating({
|
||||
placement: "bottom-start",
|
||||
|
@ -29,6 +37,22 @@ export default function SearchBar() {
|
|||
useDismiss(context),
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setSearchResults([]);
|
||||
const trimmed = searchQuery.trim();
|
||||
if (trimmed === "") return;
|
||||
|
||||
(async () => {
|
||||
const params = new URLSearchParams();
|
||||
params.set("query", trimmed);
|
||||
const resp = await fetch(
|
||||
`http://localhost:5195/node/search?${params.toString()}`,
|
||||
);
|
||||
const data = await resp.json();
|
||||
setSearchResults(data.results);
|
||||
})();
|
||||
}, [searchQuery]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
|
@ -38,6 +62,8 @@ export default function SearchBar() {
|
|||
placeholder="Search..."
|
||||
onFocus={() => setShowMenu(true)}
|
||||
ref={refs.setReference}
|
||||
value={searchQuery}
|
||||
onChange={(evt) => setSearchQuery(evt.target.value)}
|
||||
{...getReferenceProps()}
|
||||
/>
|
||||
</div>
|
||||
|
@ -51,7 +77,7 @@ export default function SearchBar() {
|
|||
style={{ ...floatingStyles }}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
<SearchMenu />
|
||||
<SearchMenu results={searchResults} />
|
||||
</div>
|
||||
</FloatingOverlay>
|
||||
</FloatingPortal>
|
||||
|
@ -60,6 +86,28 @@ export default function SearchBar() {
|
|||
);
|
||||
}
|
||||
|
||||
function SearchMenu() {
|
||||
return <>Search suggestions...</>;
|
||||
function SearchMenu({ results }) {
|
||||
const setNodesOpened = useSetAtom(nodesOpenedAtom);
|
||||
const setSearchQuery = useSetAtom(searchQueryAtom);
|
||||
const setShowMenu = useSetAtom(showMenuAtom);
|
||||
|
||||
return (
|
||||
<div className={styles.searchResults}>
|
||||
{results.map((result) => (
|
||||
<button
|
||||
type="button"
|
||||
key={result.score.toString()}
|
||||
className={styles.searchResult}
|
||||
onClick={() => {
|
||||
setSearchQuery("");
|
||||
setShowMenu(false);
|
||||
setNodesOpened((prev) => [result.node_id, ...prev]);
|
||||
}}
|
||||
>
|
||||
<div className={styles.title}>{result.title}</div>
|
||||
<div className={styles.subtitle}>{result.score}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue