wip: search page

This commit is contained in:
2025-07-21 14:38:02 +01:00
parent 5d0fa51e01
commit 251e2bc553
6 changed files with 103 additions and 44 deletions

View File

@@ -4,3 +4,4 @@ export * from "./image";
export * from "./settings";
export * from "./login";
export * from "./entity";
export * from "./search";

View File

@@ -0,0 +1,48 @@
import { Component, createSignal } from "solid-js";
import { Search } from "@kobalte/core/search";
import { IconSearch } from "@tabler/icons-solidjs";
import { useSearch } from "./search";
import { UserImage } from "@network/index";
export const SearchPage: Component = () => {
const fuse = useSearch();
const [searchItems, setSearchItems] = createSignal<UserImage[]>([]);
return (
<Search
options={searchItems()}
onInputChange={(e) => {
const items = fuse().search(e);
setSearchItems(items.map((i) => i.item.image));
}}
itemComponent={(props) => (
<Search.Item item={props.item}>
<Search.ItemLabel>
{JSON.stringify(props.item.rawValue)}
</Search.ItemLabel>
</Search.Item>
)}
>
<Search.Label />
<Search.Control class="flex">
<Search.Indicator class="bg-neutral-200 p-4 rounded-l-xl">
<Search.Icon>
<IconSearch />
</Search.Icon>
</Search.Indicator>
<Search.Input
class="w-full p-4 font-bold text-xl rounded-r-xl"
placeholder="Woking Station..."
/>
</Search.Control>
<Search.Portal>
<Search.Content class="w-full rounded-xl bg-white p-4">
<Search.Arrow />
<Search.Listbox />
<Search.NoResult>No result found</Search.NoResult>
</Search.Content>
</Search.Portal>
</Search>
);
};

View File

@@ -0,0 +1,47 @@
import { useSearchImageContext } from "@contexts/SearchImageContext";
import { UserImage } from "@network/index";
import { createMemo } from "solid-js";
import Fuse from "fuse.js";
const getSearchTerms = (image: UserImage): Array<string> => {
switch (image.type) {
case "location":
return [
image.data.Name,
image.data.Description,
image.data.Address,
image.data.CreatedAt,
].filter((i) => i != null);
case "event":
return [
image.data.Name,
image.data.Description,
image.data.CreatedAt,
].filter((i) => i != null);
case "contact":
return [
image.data.Name,
image.data.Description,
image.data.CreatedAt,
image.data.Email,
image.data.PhoneNumber,
].filter((i) => i != null);
case "note":
return [
image.data.Name,
image.data.Description,
image.data.CreatedAt,
image.data.Content,
].filter((i) => i != null);
}
};
export const useSearch = () => {
const { images } = useSearchImageContext();
const searchTerms = createMemo(() =>
images().map((i) => ({ image: i, searchTerms: getSearchTerms(i) })),
);
return () => new Fuse(searchTerms(), { keys: ["searchTerms"] });
};