Skip to content

Commit

Permalink
feat: filter searching stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
chloeelim committed Nov 12, 2024
1 parent 0c0978c commit 1b710b0
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 143 deletions.
23 changes: 19 additions & 4 deletions frontend/app/(authenticated)/articles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const Articles = () => {
const [totalCount, setTotalCount] = useState<number | undefined>(undefined);
const [isSearching, setIsSearching] = useState(false);
const [searchQuery, setSearchQuery] = useState<string | null>(null);
const [isDateFilterCleared, setIsDateFilterCleared] = useState(false);

const { page, pageCount, getPageUrl } = usePagination({
totalCount,
Expand All @@ -72,11 +73,11 @@ const Articles = () => {
refetch: refetchPage,
} = useQuery(
getArticlesPage(
toQueryDate(eventStartDate),
page,
singaporeOnly,
user?.categories.map((category) => category.id),
searchQuery ?? undefined,
isDateFilterCleared ? undefined : toQueryDate(eventStartDate),
),
);

Expand All @@ -91,6 +92,10 @@ const Articles = () => {
router.push(`?${params.toString()}`);
}, [singaporeOnly, router, searchParams]);

useEffect(() => {
refetchPage();
}, [isDateFilterCleared, refetchPage]);

if (!user) {
return;
}
Expand All @@ -111,11 +116,21 @@ const Articles = () => {
className="flex flex-col mb-4 gap-y-2 sm:px-4 md:px-8 xl:px-12"
id="homePage"
>
<div>
<div className="flex items-center">
<span className="text-2xl md:text-4xl 2xl:text-4xl font-bold text-primary-800">
What happened this&nbsp;
{isDateFilterCleared ? "All articles" : "What happened this"}
&nbsp;
</span>
<DateRangeSelector selectedPeriod={eventPeriod} />
<DateRangeSelector
clearFilter={() => {
setIsDateFilterCleared(true);
}}
isFiltered={isDateFilterCleared}
onFilter={() => {
setIsDateFilterCleared(false);
}}
selectedPeriod={eventPeriod}
/>
</div>
<span className="text-primary text-lg">
{parseDate(eventStartDate)} - {parseDate(new Date())}
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(authenticated)/bookmarks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const Page = () => {
),
)}
</div>
{isArticlesLoaded && (
{isArticlesLoaded && pageCount > 0 && (
<Pagination
getPageUrl={getPageUrl}
page={page}
Expand Down
226 changes: 143 additions & 83 deletions frontend/app/(authenticated)/categories/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client";

import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { Search } from "lucide-react";

import { CategoryDTO, MiniArticleDTO } from "@/client";
import Pagination from "@/components/navigation/pagination";
import ScrollToTopButton from "@/components/navigation/scroll-to-top-button";
import ArticleLoading from "@/components/news/article-loading";
import NewsArticle from "@/components/news/news-article";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
Expand All @@ -32,19 +35,32 @@ import { useUserStore } from "@/store/user/user-store-provider";
const Page = ({ params }: { params: { id: string } }) => {
const router = useRouter();
const searchParams = useSearchParams();
const searchBar = useRef<HTMLInputElement>(null);

const categoryId = parseInt(params.id);
const [categoryName, setCategoryName] = useState<string>("");
const [totalCount, setTotalCount] = useState<number | undefined>(undefined);

const [isSearching, setIsSearching] = useState(false);
const [searchQuery, setSearchQuery] = useState<string | null>(null);

const initialSingaporeOnly = searchParams.get("singaporeOnly") === "true";
const [singaporeOnly, setSingaporeOnly] =
useState<boolean>(initialSingaporeOnly);

const user = useUserStore((state) => state.user);
const { page, pageCount, getPageUrl } = usePagination({ totalCount });
const { data: articles, isSuccess: isArticlesLoaded } = useQuery(
getArticlesForCategory(categoryId, page, singaporeOnly),
const {
data: articles,
isSuccess: isArticlesLoaded,
refetch: refetchPage,
} = useQuery(
getArticlesForCategory(
categoryId,
page,
singaporeOnly,
searchQuery ?? undefined,
),
);
const { data: categories, isSuccess: isCategoriesLoaded } =
useQuery(getCategories());
Expand Down Expand Up @@ -88,92 +104,136 @@ const Page = ({ params }: { params: { id: string } }) => {
</span>
</div>
</div>
<div className="flex items-center w-fit sm:px-1 md:px-5 xl:px-9">
<Select
defaultValue={singaporeOnly ? "singapore-only" : "global"}
onValueChange={(value) =>
setSingaporeOnly(value === "singapore-only")
}
>
<SelectTrigger
className={
"border-none focus:ring-0 focus:ring-offset-0 font-medium hover:bg-gray-200/40 rounded-2xl text-primary-900 text-base " +
(singaporeOnly ? "w-[125px]" : "w-[105px]")
<div className="flex items-center w-full sm:px-1 md:px-5 xl:px-9 justify-between">
<div className="flex items-center">
<Select
defaultValue={singaporeOnly ? "singapore-only" : "global"}
onValueChange={(value) =>
setSingaporeOnly(value === "singapore-only")
}
>
<SelectValue />
</SelectTrigger>
<SelectContent className="min-w-[9rem]">
<SelectGroup>
<SelectLabel className="text-base">Event filter</SelectLabel>
<SelectItem className="text-base" value="global">
Global
</SelectItem>
<SelectItem className="text-base" value="singapore-only">
Singapore
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>

<Select
defaultValue={categoryId.toString()}
onValueChange={(catId) => {
if (catId !== categoryId.toString()) {
router.push(
catId === "my" ? "/articles" : `/categories/${catId}`,
);
}
return catId;
}}
>
<SelectTrigger
className={
"border-none focus:ring-0 focus:ring-offset-0 font-medium hover:bg-gray-200/40 rounded-2xl text-primary-900 text-base"
}
<SelectTrigger
className={
"border-none focus:ring-0 focus:ring-offset-0 font-medium hover:bg-gray-200/40 rounded-2xl text-primary-900 text-base " +
(singaporeOnly ? "w-[125px]" : "w-[105px]")
}
>
<SelectValue />
</SelectTrigger>
<SelectContent className="min-w-[9rem]">
<SelectGroup>
<SelectLabel className="text-base">
Event filter
</SelectLabel>
<SelectItem className="text-base" value="global">
Global
</SelectItem>
<SelectItem className="text-base" value="singapore-only">
Singapore
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>

<Select
defaultValue={categoryId.toString()}
onValueChange={(catId) => {
if (catId !== categoryId.toString()) {
router.push(
catId === "my" ? "/articles" : `/categories/${catId}`,
);
}
return catId;
}}
>
<SelectValue />
</SelectTrigger>
<SelectContent className="min-w-[16rem]">
<SelectGroup>
<SelectLabel className="text-sm">Category filter</SelectLabel>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<SelectItem className="mb-3" value="my">
My GP categories ({user?.categories.length})
</SelectItem>
</TooltipTrigger>
<TooltipContent
className="flex max-w-[14rem]"
side="bottom"
<SelectTrigger
className={
"border-none focus:ring-0 focus:ring-offset-0 font-medium hover:bg-gray-200/40 rounded-2xl text-primary-900 text-base"
}
>
<SelectValue />
</SelectTrigger>
<SelectContent className="min-w-[16rem]">
<SelectGroup>
<SelectLabel className="text-sm">
Category filter
</SelectLabel>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<SelectItem className="mb-3" value="my">
My GP categories ({user?.categories.length})
</SelectItem>
</TooltipTrigger>
<TooltipContent
className="flex max-w-[14rem]"
side="bottom"
>
<div className="flex text-wrap">
{user?.categories
.map((category) => category.name)
.join(", ")}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</SelectGroup>
<SelectGroup>
<SelectLabel className="text-sm">
Individual categories
</SelectLabel>
{categories?.map((category) => (
<SelectItem
key={category.id}
value={category.id.toString()}
>
<div className="flex text-wrap">
{user?.categories
.map((category) => category.name)
.join(", ")}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</SelectGroup>
<SelectGroup>
<SelectLabel className="text-sm">
Individual categories
</SelectLabel>
{categories?.map((category) => (
<SelectItem
key={category.id}
value={category.id.toString()}
>
{category.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
{category.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>

{!isSearching && (
<div onClick={() => setIsSearching(true)}>
<Button size="icon" variant="ghost">
<Search size={24} />
</Button>
</div>
)}
</div>

{isSearching && (
<div className="flex items-center w-full px-4 md:px-8 xl:px-12 gap-x-2 mt-2">
<Input
className="mr-2"
placeholder="Search for article titles..."
ref={searchBar}
/>
<Button
onClick={() => {
setSearchQuery(searchBar.current?.value ?? null);
refetchPage();
}}
size="sm"
>
Search
</Button>
<Button
onClick={() => {
setIsSearching(false);
setSearchQuery(null);
refetchPage();
}}
size="sm"
variant="outline"
>
Cancel
</Button>
</div>
)}

<div className="flex flex-col w-full">
{!isArticlesLoaded ? (
<div className="flex flex-col w-full">
Expand Down
Loading

0 comments on commit 1b710b0

Please sign in to comment.