feat: implement site filter

This commit is contained in:
Derrick Hammer 2023-12-23 06:42:46 -05:00
parent 0ad37ad433
commit 0c404bd3b1
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
3 changed files with 49 additions and 33 deletions

View File

@ -7,21 +7,14 @@ import React, {
useRef, useRef,
useState, useState,
} from "react"; } 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 { flushSync } from "react-dom";
import { import { Link, useFetcher, useSearchParams } from "@remix-run/react";
Link, import { FILTER_TIMES, formatDate } from "@/utils";
useFetcher,
useLocation,
useNavigate,
useSearchParams,
} from "@remix-run/react";
import { FILTER_TIMES, formatDate, getResults } from "@/utils";
import { import {
Select, Select,
SelectContent, SelectContent,
SelectItem, SelectItem,
SelectLabel,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "./ui/select"; } from "./ui/select";
@ -31,8 +24,6 @@ import { SearchResult, SiteList } from "@/types.js";
type Props = {}; type Props = {};
const SearchBar = ({ sites }: { sites: SiteList }) => { const SearchBar = ({ sites }: { sites: SiteList }) => {
let navigate = useNavigate();
let { pathname } = useLocation();
let [searchParams] = useSearchParams(); let [searchParams] = useSearchParams();
const [query, setQuery] = useState(searchParams.get("q") ?? ""); const [query, setQuery] = useState(searchParams.get("q") ?? "");
const inputRef = useRef<HTMLInputElement>(); const inputRef = useRef<HTMLInputElement>();
@ -40,29 +31,36 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
const [activeInput, setActiveInput] = useState(true); const [activeInput, setActiveInput] = useState(true);
const [dirtyInput, setDirtyInput] = useState(false); const [dirtyInput, setDirtyInput] = useState(false);
const [results, setResults] = useState<SearchResult[]>([]); const [results, setResults] = useState<SearchResult[]>([]);
const [selectedSite, setSelectedSite] = useState(null);
const fetcher = useFetcher(); const fetcher = useFetcher({ key: "seach" });
const handleSearch = useCallback( const handleSearch = useCallback(
async (event: FormEvent<HTMLFormElement>) => { (event: FormEvent<HTMLFormElement>) => {
event.preventDefault(); event.preventDefault();
setIsLoading(true); doSearch();
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}`);
}, },
[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(() => { useEffect(() => {
if (fetcher.data) { if (fetcher.data) {
setResults(fetcher.data as SearchResult[]); setResults(fetcher.data as SearchResult[]);
@ -71,6 +69,10 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
} }
}, [fetcher.data]); }, [fetcher.data]);
useEffect(() => {
doSearch();
}, [selectedSite]);
const isActive = results.length > 0 || dirtyInput; const isActive = results.length > 0 || dirtyInput;
return ( return (
@ -155,7 +157,7 @@ const SearchBar = ({ sites }: { sites: SiteList }) => {
) : ( ) : (
<div className="justify-self-end min-w-[220px] flex justify-end gap-2"> <div className="justify-self-end min-w-[220px] flex justify-end gap-2">
{/* Dropdown component should be here */} {/* Dropdown component should be here */}
<SitesCombobox siteList={sites} /> <SitesCombobox siteList={sites} onSiteSelect={setSelectedSite} />
{/* Dropdown component should be here */} {/* Dropdown component should be here */}
<Select defaultValue={"0"}> <Select defaultValue={"0"}>
<SelectTrigger className="hover:bg-muted w-auto"> <SelectTrigger className="hover:bg-muted w-auto">

View File

@ -17,8 +17,15 @@ import {
import { ChevronDownIcon } from "@heroicons/react/24/solid"; import { ChevronDownIcon } from "@heroicons/react/24/solid";
import { SelectOptions, SiteList } from "@/types.js"; import { SelectOptions, SiteList } from "@/types.js";
import slugify from "slugify"; 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) => { const sites = Object.entries(siteList).map((item) => {
return { return {
label: item[1].name, label: item[1].name,
@ -30,6 +37,10 @@ export function SitesCombobox({ siteList }: { siteList: SiteList }) {
null null
); );
useEffect(() => {
onSiteSelect(selectedSite?.value as any);
}, [selectedSite]);
return ( return (
<div className="flex flex- items-center space-x-4"> <div className="flex flex- items-center space-x-4">
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
@ -55,8 +66,7 @@ export function SitesCombobox({ siteList }: { siteList: SiteList }) {
value={status.value} value={status.value}
onSelect={(value) => { onSelect={(value) => {
setSelectedSite( setSelectedSite(
sites.find((priority) => priority.value === value) || sites.find((site) => site.value === value) || null
null
); );
setOpen(false); setOpen(false);
}} }}

View File

@ -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 results.hits.map((item) => {
return { return {