feat: search feature working well!
This commit is contained in:
@ -26,7 +26,7 @@ export const SearchCard = (props: { item: UserImage }) => {
|
||||
return (
|
||||
<A
|
||||
href={`/entity/${props.item.data.ID}`}
|
||||
class="h-[144px] border relative border-neutral-200 cursor-pointer overflow-hidden rounded-xl"
|
||||
class="w-full h-[144px] border relative border-neutral-200 cursor-pointer overflow-hidden rounded-xl"
|
||||
>
|
||||
<UnwrappedSearchCard item={props.item} />
|
||||
</A>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { Component, createSignal } from "solid-js";
|
||||
import { Component, createSignal, For } from "solid-js";
|
||||
import { Search } from "@kobalte/core/search";
|
||||
import { IconSearch } from "@tabler/icons-solidjs";
|
||||
import { useSearch } from "./search";
|
||||
import { UserImage } from "@network/index";
|
||||
import { SearchCard } from "@components/search-card/SearchCard";
|
||||
|
||||
export const SearchPage: Component = () => {
|
||||
const fuse = useSearch();
|
||||
@ -13,16 +14,12 @@ export const SearchPage: Component = () => {
|
||||
<Search
|
||||
options={searchItems()}
|
||||
onInputChange={(e) => {
|
||||
const items = fuse().search(e);
|
||||
setSearchItems(items.map((i) => i.item.image));
|
||||
setSearchItems(
|
||||
fuse()
|
||||
.search(e)
|
||||
.map((i) => i.item),
|
||||
);
|
||||
}}
|
||||
itemComponent={(props) => (
|
||||
<Search.Item item={props.item}>
|
||||
<Search.ItemLabel>
|
||||
{JSON.stringify(props.item.rawValue)}
|
||||
</Search.ItemLabel>
|
||||
</Search.Item>
|
||||
)}
|
||||
>
|
||||
<Search.Label />
|
||||
<Search.Control class="flex">
|
||||
@ -37,9 +34,9 @@ export const SearchPage: Component = () => {
|
||||
/>
|
||||
</Search.Control>
|
||||
<Search.Portal>
|
||||
<Search.Content class="w-full rounded-xl bg-white p-4">
|
||||
<Search.Content class="container relative w-full rounded-xl bg-white p-4 grid grid-cols-3 gap-4">
|
||||
<Search.Arrow />
|
||||
<Search.Listbox />
|
||||
<For each={searchItems()}>{(item) => <SearchCard item={item} />}</For>
|
||||
<Search.NoResult>No result found</Search.NoResult>
|
||||
</Search.Content>
|
||||
</Search.Portal>
|
||||
|
@ -1,47 +1,45 @@
|
||||
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
||||
import { UserImage } from "@network/index";
|
||||
import { createMemo } from "solid-js";
|
||||
import Fuse from "fuse.js";
|
||||
import { createEffect } from "solid-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);
|
||||
}
|
||||
// This language is stupid. `keyof` only returns common keys but this somehow doesnt.
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||
|
||||
const weightedTerms: Record<
|
||||
KeysOfUnion<UserImage["data"]>,
|
||||
number | undefined
|
||||
> = {
|
||||
ID: undefined,
|
||||
LocationID: undefined,
|
||||
OrganizerID: undefined,
|
||||
Images: undefined,
|
||||
|
||||
Name: 5,
|
||||
Description: 2,
|
||||
Address: 2,
|
||||
|
||||
PhoneNumber: 2,
|
||||
Email: 2,
|
||||
|
||||
CreatedAt: 1,
|
||||
StartDateTime: 1,
|
||||
EndDateTime: 1,
|
||||
|
||||
Content: 1,
|
||||
};
|
||||
|
||||
export const useSearch = () => {
|
||||
const { images } = useSearchImageContext();
|
||||
|
||||
const searchTerms = createMemo(() =>
|
||||
images().map((i) => ({ image: i, searchTerms: getSearchTerms(i) })),
|
||||
);
|
||||
|
||||
return () => new Fuse(searchTerms(), { keys: ["searchTerms"] });
|
||||
return () =>
|
||||
new Fuse(images(), {
|
||||
shouldSort: true,
|
||||
keys: Object.entries(weightedTerms)
|
||||
.filter(([, w]) => w != null)
|
||||
.map(([name, weight]) => ({
|
||||
name: `data.${name}`,
|
||||
weight,
|
||||
})),
|
||||
});
|
||||
};
|
||||
|
Reference in New Issue
Block a user