diff --git a/app/[slug]/[board]/(main)/layout.tsx b/app/[slug]/[board]/(main)/layout.tsx index a77f719..dbe8cdb 100644 --- a/app/[slug]/[board]/(main)/layout.tsx +++ b/app/[slug]/[board]/(main)/layout.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; @@ -11,6 +12,7 @@ import { CreatePost } from "@/components/posts/create"; import { Input } from "@/components/ui/input"; import { BoardOptions } from "@/components/boards/options"; import { Board } from "@/types/board"; +import Search from "./search"; import PrivateBoard from "../../private"; @@ -53,13 +55,9 @@ export default async function BoardLayout({
- + - + {hasAccess && } {session ? ( { + const [searchQuery, setSearchQuery] = React.useState(); + const router = useRouter(); + const searchParams = useSearchParams(); + const SearchQueryUpdate = debounce((searchQuery) => { + const params = new URLSearchParams(searchParams); + if (searchQuery) { + params.set("search", searchQuery); + } else { + params.delete("search"); + } + router.push(`?${params}`, { scroll: false }); + }, 300); + + // retrieving state from url, could be useful to share the filtered posts + useEffect(() => { + setSearchQuery(searchParams.get("search") || ""); + }, []); + + // calling filter upon change in search keyword + useEffect(() => { + SearchQueryUpdate(searchQuery); + }, [searchQuery]); + return ( +
+ setSearchQuery(e.target.value as string)} + value={searchQuery} + /> +
+ ); +}; + +export default Search; diff --git a/components/posts/create.tsx b/components/posts/create.tsx index 5d3b618..eb34038 100644 --- a/components/posts/create.tsx +++ b/components/posts/create.tsx @@ -81,6 +81,7 @@ export const CreatePostSheet = ({ onSuccess: () => { toast.success("Feature Request Added"); queryClient.invalidateQueries({ queryKey: ["posts", boardId] }); + form.reset(); setOpen(false); }, onError: (error) => { diff --git a/components/posts/list.tsx b/components/posts/list.tsx index de80a64..dda38b4 100644 --- a/components/posts/list.tsx +++ b/components/posts/list.tsx @@ -1,11 +1,12 @@ "use client"; -import React from "react"; +import React, { useEffect, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import Link from "next/link"; import { BoardPostType, PostStatus } from "@prisma/client"; import { JsonValue } from "@prisma/client/runtime/library"; import { motion } from "framer-motion"; +import Fuse from "fuse.js"; import Spinner from "@/components/common/spinner"; @@ -17,6 +18,7 @@ interface PostsListProps { currentUserId: string; cols?: number; hasAccess: boolean; + searchKeyword: string; } interface Post { @@ -53,7 +55,9 @@ export function PostsList({ currentUserId, cols = 2, hasAccess, + searchKeyword, }: PostsListProps) { + const [isSearching, setIsSearching] = useState(false); const { data, isLoading } = useQuery<{ posts: Post[] }>({ queryKey: ["posts", boardId], queryFn: async () => { @@ -67,7 +71,24 @@ export function PostsList({ }, }); - if (isLoading) { + const posts = data?.posts || []; + const [filteredPosts, setFilteredPosts] = useState(posts); + useEffect(() => { + if (searchKeyword) { + setIsSearching(true); + const fuseOptions = { + keys: ["title", "description"], + }; + + const fuse = new Fuse(posts, fuseOptions); + const results = fuse.search(searchKeyword); + setIsSearching(false); + setFilteredPosts(results.map((result) => result.item)); + } else { + setFilteredPosts(posts); + } + }, [searchKeyword, data]); + if (isLoading || isSearching) { return (
@@ -75,10 +96,8 @@ export function PostsList({ ); } - const posts = data?.posts || []; - // Sort posts by createdAt in descending order - const sortedPosts = [...posts].sort( + const sortedPosts = [...filteredPosts].sort( (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), ); @@ -111,10 +130,10 @@ export function PostsList({ currentUserId={currentUserId} hasAccess={hasAccess} layout={view} - // @ts-ignore + // @ts-expect-error: will improve ts later post={post} postType={post.postType} - // @ts-ignore + // @ts-expect-error: will improve ts later user={post.user!} /> diff --git a/package.json b/package.json index 72735ce..12c2e91 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "cmdk": "1.0.0", "date-fns": "4.0.0-beta.1", "framer-motion": "~11.1.1", + "fuse.js": "^7.0.0", "geist": "^1.3.1", "intl-messageformat": "^10.5.0", "jsonwebtoken": "^9.0.2",