use fuse.js instead of query to search for filters

This commit is contained in:
Lucas Oliveira 2025-12-12 15:13:44 -03:00
parent 8ca0f84cd8
commit f22f479b1f

View file

@ -1,3 +1,4 @@
import Fuse from "fuse.js";
import { ArrowRight, Check, Funnel, Loader2, Plus } from "lucide-react"; import { ArrowRight, Check, Funnel, Loader2, Plus } from "lucide-react";
import { AnimatePresence, motion } from "motion/react"; import { AnimatePresence, motion } from "motion/react";
import { import {
@ -19,7 +20,7 @@ import {
} from "@/components/ui/popover"; } from "@/components/ui/popover";
import { useFileDrag } from "@/hooks/use-file-drag"; import { useFileDrag } from "@/hooks/use-file-drag";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useGetFiltersSearchQuery } from "../../api/queries/useGetFiltersSearchQuery"; import { useGetAllFiltersQuery } from "../../api/queries/useGetAllFiltersQuery";
import type { KnowledgeFilterData } from "../_types/types"; import type { KnowledgeFilterData } from "../_types/types";
import { FilePreview } from "./file-preview"; import { FilePreview } from "./file-preview";
import { SelectedKnowledgeFilter } from "./selected-knowledge-filter"; import { SelectedKnowledgeFilter } from "./selected-knowledge-filter";
@ -80,19 +81,27 @@ export const ChatInput = forwardRef<ChatInputHandle, ChatInputProps>(
y: number; y: number;
} | null>(null); } | null>(null);
// Fetch filters using the query hook // Fetch all filters once when dropdown opens
const { data: availableFilters = [] } = useGetFiltersSearchQuery( const { data: allFilters = [] } = useGetAllFiltersQuery({
filterSearchTerm, enabled: isFilterDropdownOpen,
20, });
{ enabled: isFilterDropdownOpen },
);
// Filter available filters based on search term // Use fuse.js for fuzzy search on client side
const filteredFilters = useMemo(() => { const filteredFilters = useMemo(() => {
return availableFilters.filter((filter) => if (!filterSearchTerm) {
filter.name.toLowerCase().includes(filterSearchTerm.toLowerCase()), return allFilters.slice(0, 20); // Return first 20 when no search term
); }
}, [availableFilters, filterSearchTerm]);
const fuse = new Fuse(allFilters, {
keys: ["name", "description"],
threshold: 0.3, // 0.0 = perfect match, 1.0 = match anything
includeScore: true,
minMatchCharLength: 1,
});
const results = fuse.search(filterSearchTerm);
return results.map((result) => result.item).slice(0, 20);
}, [allFilters, filterSearchTerm]);
const { getRootProps, getInputProps } = useDropzone({ const { getRootProps, getInputProps } = useDropzone({
accept: { accept: {
@ -534,7 +543,7 @@ export const ChatInput = forwardRef<ChatInputHandle, ChatInputProps>(
Searching: @{filterSearchTerm} Searching: @{filterSearchTerm}
</div> </div>
)} )}
{availableFilters.length === 0 ? ( {allFilters.length === 0 ? (
<div className="px-2 py-3 text-sm text-muted-foreground"> <div className="px-2 py-3 text-sm text-muted-foreground">
No knowledge filters available No knowledge filters available
</div> </div>