feat: implement site filter
This commit is contained in:
parent
0ad37ad433
commit
0c404bd3b1
|
@ -7,21 +7,14 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { ChevronDownIcon, ChevronRightIcon } from "@heroicons/react/24/outline"; // Assuming usage of Heroicons for icons
|
||||
import { ChevronRightIcon } from "@heroicons/react/24/outline"; // Assuming usage of Heroicons for icons
|
||||
import { flushSync } from "react-dom";
|
||||
import {
|
||||
Link,
|
||||
useFetcher,
|
||||
useLocation,
|
||||
useNavigate,
|
||||
useSearchParams,
|
||||
} from "@remix-run/react";
|
||||
import { FILTER_TIMES, formatDate, getResults } from "@/utils";
|
||||
import { Link, useFetcher, useSearchParams } from "@remix-run/react";
|
||||
import { FILTER_TIMES, formatDate } from "@/utils";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "./ui/select";
|
||||
|
@ -31,8 +24,6 @@ import { SearchResult, SiteList } from "@/types.js";
|
|||
type Props = {};
|
||||
|
||||
const SearchBar = ({ sites }: { sites: SiteList }) => {
|
||||
let navigate = useNavigate();
|
||||
let { pathname } = useLocation();
|
||||
let [searchParams] = useSearchParams();
|
||||
const [query, setQuery] = useState(searchParams.get("q") ?? "");
|
||||
const inputRef = useRef<HTMLInputElement>();
|
||||
|
@ -40,29 +31,36 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
|
|||
const [activeInput, setActiveInput] = useState(true);
|
||||
const [dirtyInput, setDirtyInput] = useState(false);
|
||||
const [results, setResults] = useState<SearchResult[]>([]);
|
||||
const [selectedSite, setSelectedSite] = useState(null);
|
||||
|
||||
const fetcher = useFetcher();
|
||||
const fetcher = useFetcher({ key: "seach" });
|
||||
|
||||
const handleSearch = useCallback(
|
||||
async (event: FormEvent<HTMLFormElement>) => {
|
||||
(event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
setIsLoading(true);
|
||||
let newSearchParams = new URLSearchParams(searchParams.toString());
|
||||
|
||||
if (query) {
|
||||
newSearchParams.set("q", query);
|
||||
} else {
|
||||
newSearchParams.delete("q");
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(`${pathname}?${newSearchParams.toString()}`);
|
||||
|
||||
fetcher.load(`/api/search?${newSearchParams}`);
|
||||
doSearch();
|
||||
},
|
||||
[query, searchParams, navigate, pathname]
|
||||
[query, selectedSite]
|
||||
);
|
||||
|
||||
function doSearch() {
|
||||
setIsLoading(true);
|
||||
let newSearchParams = new URLSearchParams(searchParams.toString());
|
||||
|
||||
if (query) {
|
||||
newSearchParams.set("q", query);
|
||||
} else {
|
||||
newSearchParams.delete("q");
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedSite) {
|
||||
newSearchParams.set("site", selectedSite);
|
||||
}
|
||||
|
||||
fetcher.load(`/api/search?${newSearchParams}`);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (fetcher.data) {
|
||||
setResults(fetcher.data as SearchResult[]);
|
||||
|
@ -71,6 +69,10 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
|
|||
}
|
||||
}, [fetcher.data]);
|
||||
|
||||
useEffect(() => {
|
||||
doSearch();
|
||||
}, [selectedSite]);
|
||||
|
||||
const isActive = results.length > 0 || dirtyInput;
|
||||
|
||||
return (
|
||||
|
@ -155,7 +157,7 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
|
|||
) : (
|
||||
<div className="justify-self-end min-w-[220px] flex justify-end gap-2">
|
||||
{/* Dropdown component should be here */}
|
||||
<SitesCombobox siteList={sites} />
|
||||
<SitesCombobox siteList={sites} onSiteSelect={setSelectedSite} />
|
||||
{/* Dropdown component should be here */}
|
||||
<Select defaultValue={"0"}>
|
||||
<SelectTrigger className="hover:bg-muted w-auto">
|
||||
|
|
|
@ -17,8 +17,15 @@ import {
|
|||
import { ChevronDownIcon } from "@heroicons/react/24/solid";
|
||||
import { SelectOptions, SiteList } from "@/types.js";
|
||||
import slugify from "slugify";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export function SitesCombobox({ siteList }: { siteList: SiteList }) {
|
||||
export function SitesCombobox({
|
||||
siteList,
|
||||
onSiteSelect,
|
||||
}: {
|
||||
siteList: SiteList;
|
||||
onSiteSelect: React.Dispatch<React.SetStateAction<any>>;
|
||||
}) {
|
||||
const sites = Object.entries(siteList).map((item) => {
|
||||
return {
|
||||
label: item[1].name,
|
||||
|
@ -30,6 +37,10 @@ export function SitesCombobox({ siteList }: { siteList: SiteList }) {
|
|||
null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
onSiteSelect(selectedSite?.value as any);
|
||||
}, [selectedSite]);
|
||||
|
||||
return (
|
||||
<div className="flex flex- items-center space-x-4">
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
|
@ -55,8 +66,7 @@ export function SitesCombobox({ siteList }: { siteList: SiteList }) {
|
|||
value={status.value}
|
||||
onSelect={(value) => {
|
||||
setSelectedSite(
|
||||
sites.find((priority) => priority.value === value) ||
|
||||
null
|
||||
sites.find((site) => site.value === value) || null
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
|
|
|
@ -12,7 +12,11 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||
});
|
||||
}
|
||||
|
||||
const results = await search.index("articles").search(query);
|
||||
const site = searchParams.get("site");
|
||||
|
||||
const results = await search.index("articles").search(query, {
|
||||
filter: site ? `siteKey = ${site}` : undefined,
|
||||
});
|
||||
|
||||
return results.hits.map((item) => {
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue