Seeking Guidance: Implementing Filter by Category Feature
Answered
Collared Plover posted this in #help-forum
Collared PloverOP
I'm currently working on implementing a filter-by-category feature for my project, but I'm unsure of how to proceed and whether it should be implemented on the client side or server side. I'm hoping to receive some guidance or examples on how to approach this effectively.
Answered by Anay-208
Thats why I told you to check the api i.e. open localhost:3000/api/route in the browser
81 Replies
Collared PloverOP
@Anay-208
@Collared Plover I'm currently working on implementing a filter-by-category feature for my project, but I'm unsure of how to proceed and whether it should be implemented on the client side or server side. I'm hoping to receive some guidance or examples on how to approach this effectively.
In mongodb schema, you can create a new field called category, and find those items with that category
@Anay-208 In mongodb schema, you can create a new field called category, and find those items with that category
Collared PloverOP
Oh, yeah, I have a 'type' field included in my data.
Filter by that. Thats the same thing I've done in a ecomm app!
@Anay-208 In mongodb schema, you can create a new field called category, and find those items with that category
Collared PloverOP
Could you please provide a code snippet for implementing this function? I'm struggling with how to implement it.
make sure there is a property called
type(as you said) with value of what you want to filterand filter documents by type
Collared PloverOP
Is there anything salvageable in here?😆
'use client';
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { useSearchParams, usePathname, useRouter } from 'next/navigation';
import { useDebouncedCallback } from 'use-debounce';
export default function Search({ placeholder }: { placeholder: string }) {
const searchParams = useSearchParams();
const pathname = usePathname();
const { replace } = useRouter();
const handleSearch = useDebouncedCallback((term) => {
console.log(`Searching... ${term}`);
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
}, 300);
return (
<div className="relative flex flex-1 flex-shrink-0">
<label htmlFor="search" className="sr-only">
Search
</label>
<input
className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
placeholder={placeholder}
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
<MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" />
</div>
);
}@Anay-208
@Anay-208 oh wait, so do you want to add a search feature or category
Collared PloverOP
Yes category, not search feature
@Anay-208 oh wait, so do you want to add a search feature or category
Collared PloverOP
Will perhaps use search in future Project
I use something like this:
const products = await this.Products.find({
type: "t-shirt"
})@Anay-208 I use something like this:
js
const products = await this.Products.find({
type: "t-shirt"
})
Collared PloverOP
Is it possible to set predefined categories or dynamically assign categories based on the different types found in my database collection?
I’m not sure about that
@Anay-208 I’m not sure about that
Collared PloverOP
Was away, So the filtering happens from the server side then
@Anay-208 I’m not sure about that
Collared PloverOP
export async function getCategories() {
try {
const categories = await project.distinct("type");
return categories;
} catch (error) {
console.error("Error fetching categories:", error);
return []; // Return an empty array in case of error
}
}Collared PloverOP
@Anay-208 This is how far I've come, and it sort of works, but is there a way to avoid using useEffect or useState? I want the page to remain a server component.
"use client";
import Link from "next/link";
import { useState, useEffect } from "react";
import { fetchProjects, filteredProjects, getCategories } from "@/app/lib/data";
import { Projects } from "@/app/ui/project/category/Projects";
import { Project } from "@/app/lib/definitions";
export default function CategoryPage() {
const [projects, setProjects] = useState<Project[]>([]);
const [categories, setCategories] = useState<string[]>([]);
const [activeCategory, setActiveCategory] = useState<string>("All");
useEffect(() => {
const fetchData = async () => {
try {
const projectsData = await fetchProjects();
setProjects(projectsData.result || []);
const categoriesData = await getCategories();
setCategories(categoriesData || []);
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchData();
}, []);
const fetchProjectsByCategory = async (category: string) => {
setActiveCategory(category);
if (category === "All") {
const projectsData = await fetchProjects();
setProjects(projectsData.result || []);
} else {
const filteredProject = await filteredProjects(category);
setProjects(filteredProject);
}
};
return (
<main>
<article className="py-16">
<div className="relative mx-32 flex flex-col justify-between lg:mx-14 md:mx-12 xs:mx-4">
<h1 className="mb-8 block w-max text-purpledark dark:text-purple md:w-full md:text-center xs:text-3xl">
{"#" + activeCategory}
</h1>
............@Anay-208 Seems good to me
Collared PloverOP
Rest of code:
<header className="flex w-full flex-col items-start justify-center">
<nav className="flex w-full flex-wrap items-center justify-start md:justify-center">
<Link
key="All"
href="" // Assuming the category is part of the URL path
className={`border-solid p-2 px-3 border-purpledark mr-6 mb-4 rounded font-medium capitalize ${
activeCategory === "All" ? "bg-indigo-50" : ""
} last:mr-0 hover:bg-transparent hover:border-purpledark border bg-purple/25 dark:bg-purple text-purpledark dark:text-dark dark:border-purple lg:mr-4 md:mb-2 md:mr-2 dark:hover:bg-dark dark:hover:text-light`}
onClick={() => fetchProjectsByCategory("All")}>
<h2>All</h2>
</Link>
{categories.map((category) => (
<Link
key={category}
href={""} // Assuming the category is part of the URL path
className={`border-solid p-2 px-3 border-purpledark mr-6 mb-4 rounded font-medium capitalize ${
activeCategory === category ? "bg-indigo-50" : ""
} last:mr-0 hover:bg-transparent hover:border-purpledark border bg-purple/25 dark:bg-purple text-purpledark dark:text-dark dark:border-purple lg:mr-4 md:mb-2 md:mr-2 dark:hover:bg-dark dark:hover:text-light`}
onClick={() => fetchProjectsByCategory(category)}>
<h2>{category}</h2>
</Link>
))}
</nav>
</header>
<Projects projects={projects} />
</div>
</article>
</main>
);@Anay-208 Seems good to me
Collared PloverOP
Seems way too messy, and I'm sure theres a way to improve it and get Category page to run on server just like the other pages
@Collared Plover Seems way too messy, and I'm sure theres a way to improve it and get Category page to run on server just like the other pages
I’ll review it properly when I’m free
Collared PloverOP
Thanks🙌
@Collared Plover <@755810867878297610> This is how far I've come, and it sort of works, but is there a way to avoid using useEffect or useState? I want the page to remain a server component.tsx
"use client";
import Link from "next/link";
import { useState, useEffect } from "react";
import { fetchProjects, filteredProjects, getCategories } from "@/app/lib/data";
import { Projects } from "@/app/ui/project/category/Projects";
import { Project } from "@/app/lib/definitions";
export default function CategoryPage() {
const [projects, setProjects] = useState<Project[]>([]);
const [categories, setCategories] = useState<string[]>([]);
const [activeCategory, setActiveCategory] = useState<string>("All");
useEffect(() => {
const fetchData = async () => {
try {
const projectsData = await fetchProjects();
setProjects(projectsData.result || []);
const categoriesData = await getCategories();
setCategories(categoriesData || []);
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchData();
}, []);
const fetchProjectsByCategory = async (category: string) => {
setActiveCategory(category);
if (category === "All") {
const projectsData = await fetchProjects();
setProjects(projectsData.result || []);
} else {
const filteredProject = await filteredProjects(category);
setProjects(filteredProject);
}
};
return (
<main>
<article className="py-16">
<div className="relative mx-32 flex flex-col justify-between lg:mx-14 md:mx-12 xs:mx-4">
<h1 className="mb-8 block w-max text-purpledark dark:text-purple md:w-full md:text-center xs:text-3xl">
{"#" + activeCategory}
</h1>
............
Here are my recommendations to improve this code:
- In first useEffect, instead of using async, use
- Instead of using a function, you can use a
- In first useEffect, instead of using async, use
.then- Instead of using a function, you can use a
useEffect hook, with [activeCategory], and directly setActiveCategory from a function@Anay-208 Here are my recommendations to improve this code:
- In first useEffect, instead of using async, use `.then`
- Instead of using a function, you can use a `useEffect` hook, with `[activeCategory]`, and directly `setActiveCategory` from a function
Collared PloverOP
Thank you very much, let me try and apply your suggestion.
@Collared Plover Thank you very much, let me try and apply your suggestion.
If your issue is resolved, mark my message as a solution
@Anay-208 If your issue is resolved, mark my message as a solution
Collared PloverOP
Hello there! I'm still working on finding a solution. I'm considering separating the category filter and turning it into a client component. Then, I could pass data to it from a server component, like marking my category page as a server component. I wasn't ignoring you, just busy with other tasks. Now, I'm here trying to find a better way to handle this issue.
@Anay-208 If your issue is resolved, mark my message as a solution
Collared PloverOP
Hi there, I need some help, please.
import { fetchProjects, filteredProjects, getCategories } from "@/app/lib/data";
import { Project } from "@/app/lib/definitions";
import { FilteredProjects } from "@/app/lib/filter";
async function fetchData(): Promise<Project[]> {
try {
// Fetch projects data from your API or database
const { result, error } = await fetchProjects();
if (error || !result) {
// If there's an error or no result, throw an error to activate the error boundary
throw new Error("Failed to fetch data");
}
// Return the projects data as props
return result; // Assuming `result` is an array of projects data
} catch (error) {
// Catch any errors and log them
console.error("Error fetching data:", error);
// Return an empty object if there's an error
return [];
}
}
export default async function CategoryPage() {
const data = await fetchData();
const category = await getCategories();
const selectedCategory = await filteredProjects; //"filteredProjects()" is supposed to receive a "category" prop and retrieves data from MongoDB that matches the specified category. But no idea how to pass data to it once client requests a specific category.
return (
<main>
<article className="py-16">
<FilteredProjects
data={data}
fetchProjectsByCategory={selectedCategory}
availableCategories={category}
/>
</article>
</main>
);
}useStateand in client component,
useEffect to look for changes@Anay-208 If your issue is resolved, mark my message as a solution
Collared PloverOP
Here's the filteredProjects component which is a client component
"use client";
import { useState, useEffect } from "react";
..........................
interface FilterProps {
data: Project[];
fetchProjectsByCategory: any;
availableCategories: any;
}
export function FilteredProjects({ data, availableCategories }: FilterProps) {
const [activeCategory, setActiveCategory] = useState<string>("All");
const handleClick = async (category: string) => {
setActiveCategory(category);
};
return (
<div className="relative mx-32 flex flex-col justify-between lg:mx-14 md:mx-12 xs:mx-4">
<h1 className="mb-8 block w-max font-ot text-4xl font-semibold capitalize leading-tight tracking-wide text-purpledark dark:text-purple md:w-full md:text-center xs:text-3xl">
{"#" + activeCategory}
</h1>
<header className="flex w-full flex-col items-start justify-center">
<nav className="flex w-full flex-wrap items-center justify-start md:justify-center">
<Link
key="All"
href="" // Assuming the category is part of the URL path
className={`border-solid p-2 px-3 border-purpledark mr-6 mb-4 rounded font-medium capitalize ${
activeCategory === "All" ? "bg-indigo-50" : ""
} last:mr-0 hover:bg-transparent hover:border-purpledark border bg-purple/25 dark:bg-purple text-purpledark dark:text-dark dark:border-purple lg:mr-4 md:mb-2 md:mr-2 dark:hover:bg-dark dark:hover:text-light`}
onClick={() => handleClick("All")}>
<h2>All</h2>
</Link>
{availableCategories.map((category: string) => (
<Link
key={category}
..............................
onClick={() => handleClick(category)}>
<h2>{category}</h2>
</Link>
))}
</nav>
</header>
<Projects projects={data} />
</div>
);
}@Anay-208 and in client component, `useEffect` to look for changes
Collared PloverOP
but I thought You can't use
tsx import { useState, useEffect } from "react"; in a server component?oh umm
let me think
You'll have to create a api route for that
Client would need to send the api request to that path to filter it
@Collared Plover
@Anay-208 You'll have to create a api route for that
Collared PloverOP
So, in this API route, it will handle passing the specified prop to the function that fetches projects by category?
@Collared Plover So, in this API route, it will handle passing the specified prop to the function that fetches projects by category?
It will return the response, and rest will be handled by client only
@Anay-208 It will return the response, and rest will be handled by client only
Collared PloverOP
By the way, thank you very much for your assistance. I truly appreciate your patience, and I'm eager to learn.
@Anay-208 It will return the response, and rest will be handled by client only
Collared PloverOP
This is my function that handles the fetching will I need to modify anything?
export async function filteredProjects(category) {
try {
const projects = await project.find({ category }).toArray();
return projects;
} catch (error) {
console.error("Error fetching projects:", error);
return []; // Return an empty array in case of error
}
};@Anay-208 No problem
Collared PloverOP
Here's my api route currently
import { NextResponse } from "next/server";
import { fetchFeaturedProjects, fetchProjects } from "../../lib/data";
export async function GET() {
try {
const { result: projects, error: projectsError } = await fetchProjects();
const { result: featuredProjects, error: featuredProjectsError } =
await fetchFeaturedProjects();
if (projectsError || featuredProjectsError) {
throw new Error("Error fetching projects");
}
return NextResponse.json({ projects, featuredProjects }, { status: 200 });
} catch (error) {
return NextResponse.json(
{ message: "Error fetching projects:", error },
{ status: 500 }
);
}
}I’ll check when I’m free. You can try it out!
Collared PloverOP
Yes, I'll try it out and get back to you.
seems good to me!
Collared PloverOP
Hi there, could you please take a look at this? Please correct any errors you find.
import { NextResponse } from "next/server";
import {
fetchFeaturedProjects,
fetchProjects,
filteredProjects,
} from "../../lib/data";
export async function GET(request) {
try {
const category = await request.query.json();
const projectsByCategory = await filteredProjects(category);
const { result: projects, error: projectsError } = await fetchProjects();
const { result: featuredProjects, error: featuredProjectsError } =
await fetchFeaturedProjects();
if (projectsError || featuredProjectsError || projectsByCategory) {
throw new Error("Error fetching projects");
}
return NextResponse.json(
{ projects, featuredProjects, projectsByCategory },
{ status: 200 }
);
} catch (error) {
return NextResponse.json(
{ message: "Error fetching projects:", error },
{ status: 500 }
);
}
};@Anay-208
if you get any errors, send console ss
Collared PloverOP
Main concern is by how I'm making a request to the api
export function FilteredProjects({ availableCategories }: FilterProps) {
const [projects, setProjects] = useState<Project[]>([]);
const [activeCategory, setActiveCategory] = useState<string>("All");
const fetchProjectsByCategory = async (category: string) => {
try {
const response = await fetch(`/api/projects?category=${category}`);
if (!response.ok) {
throw new Error("Failed to fetch projects");
}
const data = await response.json();
setProjects(data);
} catch (error) {
console.error("Error fetching projects:", error);
}
};
// Function to handle category change
const handleCategoryChange = (category: string) => {
setActiveCategory(category);
fetchProjectsByCategory(category);
};@Anay-208
what is the error
Collared PloverOP
Api is sending back rubbish I mean nothing😆
@Anay-208
console.log projects, featuredProjects, projectsByCategory on api
@Anay-208 console.log projects, featuredProjects, projectsByCategory on api
Collared PloverOP
projects:1 Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
projects:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error);@Anay-208 First, try directly requesting this route using browser
Collared PloverOP
The route was working fine before I introduced these changes:
export async function GET(request) {
try {
const category = await request.query.json(); // Probably causing erros
const projectsByCategory = await filteredProjects(category); // Probably causing errors
const { result: projects, error: projectsError } = await fetchProjects();
const { result: featuredProjects, error: featuredProjectsError } =
await fetchFeaturedProjects();
if (projectsError || featuredProjectsError || projectsByCategory) {
throw new Error("Error fetching projects");
}
console.log(projectsByCategory);
return NextResponse.json(
{ projects, featuredProjects, projectsByCategory },
{ status: 200 }
);
} catch (error) {
return NextResponse.json(
{ message: "Error fetching projects:", error },
{ status: 500 }
);
}
};@Collared Plover The route was working fine before I introduced these changes:
tsx
export async function GET(request) {
try {
const category = await request.query.json(); // Probably causing erros
const projectsByCategory = await filteredProjects(category); // Probably causing errors
const { result: projects, error: projectsError } = await fetchProjects();
const { result: featuredProjects, error: featuredProjectsError } =
await fetchFeaturedProjects();
if (projectsError || featuredProjectsError || projectsByCategory) {
throw new Error("Error fetching projects");
}
console.log(projectsByCategory);
return NextResponse.json(
{ projects, featuredProjects, projectsByCategory },
{ status: 200 }
);
} catch (error) {
return NextResponse.json(
{ message: "Error fetching projects:", error },
{ status: 500 }
);
}
}
;
see this on how to get url query: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#url-query-parameters
@Anay-208 see this on how to get url query: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#url-query-parameters
Collared PloverOP
Sure will get back to you.
@Anay-208 see this on how to get url query: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#url-query-parameters
Collared PloverOP
I believe I'm close to resolving the issue, but the data still isn't being sent to the API. I attempted to manually add data to the server function in the API, and it worked. However, I'm still struggling to send data from the client. Thank you for your patience. I'll attach send the code:
@Anay-208 see this on how to get url query: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#url-query-parameters
Collared PloverOP
export async function filteredProjects({ categories }: any) {
try {
if (!project) await connectToCollection();
if (!project) throw new Error("featuredProjects not initialized.");
const result = await project.find({ category: `${categories}` }).toArray();
const serializedResult = result.map((item) =>
JSON.parse(JSON.stringify(item))
);
return { result: serializedResult };
} catch (error) {
console.error("Error fetching projects:", error);
return []; // Return an empty array in case of error
}
}import { filteredProjects } from "@/app/lib/data";
import { NextRequest, NextResponse } from "next/server";
export async function GET() {
try {
const { categories } = NextRequest.query;
if (!categories) {
throw new Error("Categories parameter is missing");
}
const { result } = await filteredProjects({ categories });
if (!result) {
throw new Error("No projects found for the given category");
}
return NextResponse.json({ result }, { status: 200 });
} catch (error) {
console.error("Error fetching projects:", error);
return NextResponse.json(
{ message: "Error fetching projects", error: error.message },
{ status: 500 }
);
}
}const [projects, setProjects] = useState<Project[]>(data);
const [activeCategory, setActiveCategory] = useState<string>("All");
async function fetchData(category: string): Promise<Project[]> {
try {
// Fetch projects data from your API or database
const response = await fetch(
`/api/projects/category/categories=${category}`
);
const result = await response.json();
if (!result || !Array.isArray(result)) {
// If there's an error or no result, throw an error to activate the error boundary
throw new Error("Failed to fetch data");
}
// Return the projects data as props
return result;
} catch (error) {
// Catch any errors and log them
console.error("Error fetching data:", error);
// Return an empty array if there's an error
return [];
}
}
// Function to handle category change
async function handleCategoryChange(category: string) {
setActiveCategory(category);
if (category === "All") {
setProjects(data);
} else {
const fetchedProjects = await fetchData(category);
setProjects(fetchedProjects);
}
}what do you see when you open that page in browser?
api route
Collared PloverOP
{
"message": "Error fetching projects",
"error": "Cannot destructure property 'categories' of 'next_server__WEBPACK_IMPORTED_MODULE_1__.NextRequest.query' as it is undefined."
};@Anay-208
@Anay-208 … add a argument to fucntion GET of type NextRequest
Collared PloverOP
export async function GET(req: NextRequest) {
try {
const { categories } = req.query;
if (!categories) {
throw new Error("Categories parameter is missing");
}
const { result } = await filteredProjects({ categories });
if (!result) {
throw new Error("No projects found for the given category");
}
return NextResponse.json({ result }, { status: 200 });
} catch (error) {
console.error("Error fetching projects:", error);
return NextResponse.json(
{ message: "Error fetching projects", error: error.message },
{ status: 500 }
);
}
};@Anay-208 See this
Collared PloverOP
Encountering the error 'TypeError: projects.map is not a function'. However, when selecting the 'All' category, all categories are successfully displayed. Additionally, I finally figured out the API query, though it took some time.
"use client";
import { useState, useEffect } from "react";
import { Project } from "./definitions";
import Link from "next/link";
import { Projects } from "../ui/project/category/Projects";
interface FilterProps {
data: Project[];
availableCategories: string[];
}
export function FilteredProjects({ availableCategories, data }: FilterProps) {
const [projects, setProjects] = useState<Project[]>(data);
const [activeCategory, setActiveCategory] = useState<string>("All");
async function fetchData(category: string): Promise<void> {
try {
const response = await fetch(
`/api/projects/category?categories=${category}`
);
if (!response.ok) {
throw new Error("Failed to fetch data");
}
const projectsData = await response.json();
console.log(projectsData);
setProjects(projectsData); // Update projects state with fetched data
} catch (error) {
console.error("Error fetching data:", error);
setProjects([]);
}
}
async function handleCategoryChange(category: string): Promise<void> {
setActiveCategory(category);
if (category === "All") {
setProjects(data);
} else {
await fetchData(category);
}
}@Anay-208 first check the api if it is working right
Collared PloverOP
I made progress: when I console.log the result in the API and select a category, the projects from the selected category are logged in the console. Therefore, it's receiving data. I believe the issue lies in sending back data or displaying it on my API route once it has been converted into JSON.
import { filteredProjects } from "@/app/lib/data";
import { NextResponse } from "next/server";
import { type NextRequest } from "next/server";
export async function GET(request: NextRequest) {
try {
// if (!result) {
// throw new Error("No projects found for the given category");
// }
const searchParams = request.nextUrl.searchParams;
const query = searchParams.get("categories");
const { result }: any = await filteredProjects({ categories: query });
return NextResponse.json({ result }, { status: 200 });
} catch (error) {
console.error("Error fetching projects:", error);
return NextResponse.json(
{ message: "Error fetching projects" },
{ status: 500 }
);
}
};@Anay-208 first check the api if it is working right
Collared PloverOP
const [projects, setProjects] = useState<Project[]>(data);
const [activeCategory, setActiveCategory] = useState<string>("All");
async function fetchData(category: string): Promise<void> {
try {
const response = await fetch(
`/api/projects/category?categories=${category}`
);
if (!response.ok) {
throw new Error("Failed to fetch data");
}
const projectsData = await response.json();
console.log(projectsData);
setProjects(projectsData); // Update projects state with fetched data
} catch (error) {
console.error("Error fetching data:", error);
setProjects([]);
}
}
function handleCategoryChange(category: string): void {
setActiveCategory(category);
if (category === "All") {
setProjects(data);
} else {
fetchData(category);
}
}@Anay-208 first check the api if it is working right
Collared PloverOP
Second part of the code:
return (
<div className="relative mx-32 flex flex-col justify-between lg:mx-14 md:mx-12 xs:mx-4">
<h1 className="mb-8 block w-max font-ot text-4xl font-semibold capitalize leading-tight tracking-wide">
{"#" + activeCategory}
</h1>
<header className="flex w-full flex-col items-start justify-center">
<nav className="flex w-full flex-wrap items-center justify-start md:justify-center">
<Link
key="All"
href="" // Add correct href value
className={`border-solid p-2 px-3 border-purpledark mr-6 mb-4 rounded font-medium capitalize ${
activeCategory === "All"
? "bg-purpledark text-light pointer-events-none"
: "bg-purple/25 text-purpledark hover:bg-transparent hover:border-purpledark dark:bg-purple border dark:text-darkmode"
} last:mr-0 dark:border-purple font-medium lg:mr-4 md:mb-2 md:mr-2 dark:hover:bg-dark dark:hover:text-light`}
onClick={() => handleCategoryChange("All")}>
<h2>All</h2>
</Link>
{availableCategories.map((category: string) => (
<Link
key={category}
href="" // Add correct href value
className={`border-solid p-2 px-3 border-purpledark mr-6 mb-4 rounded font-medium capitalize ${
activeCategory === category
? "bg-purpledark text-light pointer-events-none"
: "bg-purple/25 text-purpledark hover:bg-transparent hover:border-purpledark dark:bg-purple border dark:text-darkmode"
} last:mr-0 dark:border-purple font-medium lg:mr-4 md:mb-2 md:mr-2 dark:hover:bg-dark dark:hover:text-light`}
onClick={() => handleCategoryChange(category)}>
<h2>{category}</h2>
</Link>
))}
</nav>
</header>
<Projects projects={projects} />
</div>
);
}hi guys, could we extend the discussion about filtering by category a bit, I'm stuck on a similar problem, so I think you could help me with that.
@Anay-208 @Collared Plover