Skip to content

Commit

Permalink
Implement fuse (#91)
Browse files Browse the repository at this point in the history
* initial commit with comments

* installed fuse.js

* YIPPEE

* h

* feat: add fuzzy searching to reviews

* fix: add fuzzy search integration on roles page

* fix: return early if no search

* fix: remove unnecessary check

* feat: set search bar contents to search param

* fixed bug with updated selected view

implemented with useEffect, looking for alternative solution

* functional fuse

* remove unnecessary params

* reformatted

---------

Co-authored-by: Rishikesh Kanabar <[email protected]>
  • Loading branch information
suxls and RishikeshNK authored Nov 23, 2024
1 parent e8a303d commit 65750da
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 11 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@trpc/react-query": "11.0.0-rc.441",
"@trpc/server": "11.0.0-rc.441",
"dayjs": "^1.11.13",
"fuse.js": "^7.0.0",
"geist": "^1.3.0",
"lucide-react": "^0.436.0",
"next": "^14.2.4",
Expand Down
10 changes: 9 additions & 1 deletion apps/web/src/app/(pages)/(dashboard)/roles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function Roles({
searchParams,
}: {
searchParams?: {
search?: string;
cycle?: WorkTermType;
term?: WorkEnvironmentType;
};
Expand Down Expand Up @@ -67,16 +68,23 @@ export default function Roles({
]);

const reviews = api.review.list.useQuery({
search: searchParams?.search,
options: validationResult.success ? validationResult.data : {},
});

const [selectedReview, setSelectedReview] = useState<ReviewType | undefined>(
reviews.data ? reviews.data[0] : undefined,
);

useEffect(() => {
if (reviews.data) {
setSelectedReview(reviews.data[0]);
}
}, [reviews.data]);

return (
<>
<SearchFilter />
<SearchFilter search={searchParams?.search} />
{reviews.data && (
<div className="mb-8 grid h-[70dvh] w-4/5 grid-cols-5 gap-4 lg:w-3/4">
<div className="col-span-2 gap-3 overflow-scroll pr-4">
Expand Down
13 changes: 11 additions & 2 deletions apps/web/src/app/_components/search/search-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@ const formSchema = z.object({

export type SearchFilterFormType = typeof formSchema;

export default function SearchFilter() {
interface SearchFilterProps {
search?: string;
}

/**
* Handles searching logic, updates the search param base on user search and passes the text to backend with fuzzy searching.
* @param param0 user input text that's passed to the fuzzy search
* @returns the search bar with the user inputted text
*/
export default function SearchFilter({ search }: SearchFilterProps) {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
searchText: "",
searchText: search ?? "",
},
});

Expand Down
18 changes: 16 additions & 2 deletions packages/api/src/router/review.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { TRPCRouterRecord } from "@trpc/server";
import Fuse from "fuse.js";
import { z } from "zod";

import { and, desc, eq } from "@cooper/db";
Expand All @@ -10,6 +11,7 @@ export const reviewRouter = {
list: publicProcedure
.input(
z.object({
search: z.string().optional(),
options: z
.object({
cycle: z.enum(["SPRING", "FALL", "SUMMER"]).optional(),
Expand All @@ -18,18 +20,30 @@ export const reviewRouter = {
.optional(),
}),
)
.query(({ ctx, input }) => {
.query(async ({ ctx, input }) => {
const { options } = input;

const conditions = [
options?.cycle && eq(Review.workTerm, options.cycle),
options?.term && eq(Review.workEnvironment, options.term),
].filter(Boolean);

return ctx.db.query.Review.findMany({
const reviews = await ctx.db.query.Review.findMany({
orderBy: desc(Review.id),
where: conditions.length > 0 ? and(...conditions) : undefined,
});

if (!input.search) {
return reviews;
}

const fuseOptions = {
keys: ["reviewHeadline", "textReview", "location"],
};

const fuse = new Fuse(reviews, fuseOptions);

return fuse.search(input.search).map((result) => result.item);
}),

getByRole: publicProcedure
Expand Down
13 changes: 7 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 65750da

Please sign in to comment.