From 26773719703966e2d3baea13b7bada6d1cd1995e Mon Sep 17 00:00:00 2001 From: Parth Virendrakumar Shah Date: Thu, 8 Aug 2024 16:16:34 -0700 Subject: [PATCH] added a sort by option on the posts page+ merged the upstream main --- backend/src/routes/post/controller.ts | 17 ++-- frontend/src/hooks/usePosts.tsx | 15 ++- frontend/src/pages/Posts.tsx | 130 ++++++++++++++++---------- 3 files changed, 102 insertions(+), 60 deletions(-) diff --git a/backend/src/routes/post/controller.ts b/backend/src/routes/post/controller.ts index e309c5ea..d1ea781b 100644 --- a/backend/src/routes/post/controller.ts +++ b/backend/src/routes/post/controller.ts @@ -250,7 +250,8 @@ export const getPostsWithPagination = async (req: Request, res: Response) => { const pageSize = parseInt(req.query.pageSize as string); const searchQuery = req.query.searchQuery as string || ""; const tags = req.query.tags ? (req.query.tags as string).split(',') : []; - + const sortOrder = req.query.sortOrder as string || 'reactions'; + const sortDirection = req.query.sortDirection as string || 'desc'; const totalPosts = await prisma.post.count({ where: { AND: [ @@ -265,7 +266,13 @@ export const getPostsWithPagination = async (req: Request, res: Response) => { } }); const totalPages = Math.ceil(totalPosts / pageSize); - + const orderPosts = sortOrder === 'reactions' ? { + reactions: { + _count: sortDirection as 'asc' | 'desc' + } as const + } : { + createdAt: sortDirection as 'asc' | 'desc' + } as const ; const posts = await prisma.post.findMany({ skip: (page - 1) * pageSize, take: pageSize, @@ -294,11 +301,7 @@ export const getPostsWithPagination = async (req: Request, res: Response) => { tags.length > 0 ? { tags: { hasSome: tags } } : {} ] }, - orderBy: { - reactions: { - _count: "desc" - } - } + orderBy: orderPosts, }); res.status(200).json({ posts, diff --git a/frontend/src/hooks/usePosts.tsx b/frontend/src/hooks/usePosts.tsx index f9cbab60..0dcbd880 100644 --- a/frontend/src/hooks/usePosts.tsx +++ b/frontend/src/hooks/usePosts.tsx @@ -17,19 +17,26 @@ const usePosts = ({ initialPage = 1, pageSize = 12 }: Props) => { const [searchQuery, setSearchQuery] = useState(""); const [tags, setTags] = useState([]); const [searchParams, setSearchParams] = useSearchParams(); + const [sortOrder, setSortOrder] = useState("reactions"); + const [sortDirection, setSortDirection] = useState("desc"); const fetchPosts = async ( page: number, pageSize: number, searchQuery: string, - tags: string[] + tags: string[], + sortOrder: string, + sortDirection: string ) => { + + setSortOrder(sortOrder); + setSortDirection(sortDirection); setLoading(true); try { const response = await axios.get( `/api/v1/posts?page=${page}&pageSize=${pageSize}&searchQuery=${searchQuery}&tags=${tags.join( "," - )}` + )}&sortOrder=${sortOrder}&sortDirection=${sortDirection}` ); setPosts(response.data.posts); setTotalPages(response.data.totalPages); @@ -44,7 +51,7 @@ const usePosts = ({ initialPage = 1, pageSize = 12 }: Props) => { const tagsFromParams = searchParams.get("tags"); const initialTags = tagsFromParams ? tagsFromParams.split(",") : []; setTags(initialTags); - fetchPosts(page, pageSize, searchQuery, initialTags); + fetchPosts(page, pageSize, searchQuery, initialTags, sortOrder, sortDirection); }, [page, searchParams]); const handlePreviousPage = () => { @@ -64,7 +71,7 @@ const usePosts = ({ initialPage = 1, pageSize = 12 }: Props) => { }; const handleDelete = () => { - fetchPosts(page, pageSize, searchQuery, tags); + fetchPosts(page, pageSize, searchQuery, tags, sortOrder, sortDirection); }; const addTag = (tagInput: string) => { diff --git a/frontend/src/pages/Posts.tsx b/frontend/src/pages/Posts.tsx index e91a37d7..04c0b886 100644 --- a/frontend/src/pages/Posts.tsx +++ b/frontend/src/pages/Posts.tsx @@ -33,6 +33,9 @@ const Posts = () => { const [tagInput, setTagInput] = useState(""); const [filterTags, setFilterTags] = useState([]); const filterRef = useRef(null); + const [sortOrder, setSortOrder] = useState("reactions"); + const [sortDirection, setSortDirection] = useState('desc'); + const filteredPosts = posts; const allTags = filteredPosts.map(post => post.tags).flat(); const uniqueTags = [...new Set(allTags)]; @@ -47,17 +50,30 @@ const Posts = () => { }; document.title = "Style Share | Our Posts 📃"; - + document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, []); + useEffect(() => { + fetchPosts(page, 12, searchQuery, filterTags, sortOrder, sortDirection); + }, [sortOrder, sortDirection]); + const toggleFilterDialog = () => { setShowFilterDialog(!showFilterDialog); }; + const handleSortChange = (selectedSort: any) => { + if (selectedSort === sortOrder) { + setSortDirection(prevDirection => (prevDirection === 'desc' ? 'asc' : 'desc')); + } else { + setSortOrder(selectedSort); + setSortDirection('desc'); + } + }; + const addTag = () => { if (tagInput && !filterTags.includes(tagInput.toLowerCase())) { setFilterTags([...filterTags, tagInput.toLowerCase()]); @@ -79,7 +95,7 @@ const Posts = () => { }; const handleSearch = () => { - fetchPosts(page, 12, searchQuery, filterTags); + fetchPosts(page, 12, searchQuery, filterTags, sortOrder, sortDirection); }; if (loading) { @@ -162,14 +178,29 @@ const Posts = () => { )}
+
+ Sort by: + +
setSearchQuery(e.target.value)} placeholder="🔍 Search anything" className="p-2 w-full max-w-xs rounded-md text-[#000435] bg-white dark:text-white dark:bg-[#000435] border border-sky-400 focus:outline-none focus:ring-2 focus:ring-blue-500" - onKeyDown={(event)=>{ - if(event.key == "Enter"){ + onKeyDown={(event) => { + if (event.key == "Enter") { handleSearch() } }} @@ -185,53 +216,54 @@ const Posts = () => { {filteredPosts.length === 0 ? (
No Posts
) : ( -
-
- {filteredPosts.map((post) => ( - - ))} -
-
- - {Array.from({ length: totalPages }, (_, i) => ( - - ))} - -
+
+ {filteredPosts.map((post) => ( + + ))}
)} +
+ + {Array.from({ length: totalPages }, (_, i) => ( + + ))} + +
);