Skip to content

Commit

Permalink
Merge pull request #583 from Parth18Shah/order_posts
Browse files Browse the repository at this point in the history
added a sort by option on the posts page
  • Loading branch information
akbatra567 authored Aug 10, 2024
2 parents 2913d0a + 2677371 commit 7645861
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 60 deletions.
17 changes: 10 additions & 7 deletions backend/src/routes/post/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
15 changes: 11 additions & 4 deletions frontend/src/hooks/usePosts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,26 @@ const usePosts = ({ initialPage = 1, pageSize = 12 }: Props) => {
const [searchQuery, setSearchQuery] = useState("");
const [tags, setTags] = useState<string[]>([]);
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);
Expand All @@ -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 = () => {
Expand All @@ -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) => {
Expand Down
130 changes: 81 additions & 49 deletions frontend/src/pages/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ const Posts = () => {
const [tagInput, setTagInput] = useState("");
const [filterTags, setFilterTags] = useState<string[]>([]);
const filterRef = useRef<HTMLDivElement>(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)];
Expand All @@ -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()]);
Expand All @@ -79,7 +95,7 @@ const Posts = () => {
};

const handleSearch = () => {
fetchPosts(page, 12, searchQuery, filterTags);
fetchPosts(page, 12, searchQuery, filterTags, sortOrder, sortDirection);
};

if (loading) {
Expand Down Expand Up @@ -162,14 +178,29 @@ const Posts = () => {
</div>
)}
<div className="flex items-center w-full sm:w-auto">
<div className="flex items-center">
<span className="p-2 text-[#5f67de] whitespace-nowrap">Sort by:</span>
<select
value={sortOrder}
onChange={(e) => handleSortChange(e.target.value)}
className="p-2 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 mr-4"
>
<option value="reactions" onClick={() => handleSortChange('reactions')}>
Reactions {sortOrder === 'reactions' && (sortDirection === 'asc' ? '↓' : '↑')}
</option>
<option value="createdAt" onClick={() => handleSortChange('createdAt')}>
Date {sortOrder === 'createdAt' && (sortDirection === 'asc' ? '↓' : '↑')}
</option>
</select>
</div>
<input
type="text"
value={searchQuery}
onChange={(e) => 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()
}
}}
Expand All @@ -185,53 +216,54 @@ const Posts = () => {
{filteredPosts.length === 0 ? (
<div className="text-center text-black dark:text-white">No Posts</div>
) : (
<div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">
{filteredPosts.map((post) => (
<PostCard
key={post.id}
post={post}
currentUser={currentUser}
onDelete={handleDelete}
/>
))}
</div>
<div className="flex justify-center items-center mt-4 w-full space-x-2">
<button
onClick={handlePreviousPage}
disabled={page === 1}
className={`text-white px-4 py-2 rounded ${page === 1
? "bg-gray-600 cursor-not-allowed"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
Previous
</button>
{Array.from({ length: totalPages }, (_, i) => (
<button
key={i}
onClick={() => handlePageClick(i + 1)}
className={`text-white px-4 py-2 rounded ${page === i + 1
? "bg-blue-500 text-white"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
{i + 1}
</button>
))}
<button
onClick={handleNextPage}
disabled={page === totalPages}
className={`text-white px-6 py-2 rounded ${page === totalPages
? "bg-gray-600 cursor-not-allowed"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
Next
</button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 w-full">
{filteredPosts.map((post) => (
<PostCard
key={post.id}
post={post}
currentUser={currentUser}
onDelete={handleDelete}
/>
))}
</div>
)}
<div className="flex justify-center items-center mt-4 w-full space-x-2">
<button
onClick={handlePreviousPage}
disabled={page === 1}
className={`text-white px-4 py-2 rounded ${
page === 1
? "bg-gray-600 cursor-not-allowed"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
Previous
</button>
{Array.from({ length: totalPages }, (_, i) => (
<button
key={i}
onClick={() => handlePageClick(i + 1)}
className={`text-white px-4 py-2 rounded ${
page === i + 1
? "bg-blue-500 text-white"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
{i + 1}
</button>
))}
<button
onClick={handleNextPage}
disabled={page === totalPages}
className={`text-white px-6 py-2 rounded ${
page === totalPages
? "bg-gray-600 cursor-not-allowed"
: "bg-blue-600 hover:bg-blue-700"
}`}
>
Next
</button>
</div>
</div>
</div>
);
Expand Down

0 comments on commit 7645861

Please sign in to comment.