diff --git a/apps/web/src/components/dashboard/ProjectsContainer.tsx b/apps/web/src/components/dashboard/ProjectsContainer.tsx index be004035..26c90fbc 100644 --- a/apps/web/src/components/dashboard/ProjectsContainer.tsx +++ b/apps/web/src/components/dashboard/ProjectsContainer.tsx @@ -15,7 +15,8 @@ import { DashboardProjectsProps } from "@/types"; import Image from "next/image"; import { useFilterStore } from "@/store/useFilterStore"; import { usePathname } from "next/navigation"; -import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { MagnifyingGlassIcon, FunnelIcon } from "@heroicons/react/24/outline"; +import { useState, useMemo } from "react"; type ProjectsContainerProps = { projects: DashboardProjectsProps[] }; @@ -58,6 +59,53 @@ export default function ProjectsContainer({ const { projectTitle } = useProjectTitleStore(); const { setShowFilters } = useFilterStore(); const isProjectsPage = pathname === "/dashboard/projects"; + const [searchQuery, setSearchQuery] = useState(""); + + // Client-side filtering of projects based on search query + // Memoized for performance optimization + const filteredProjects = useMemo(() => { + // Return all projects if no search query or empty projects array + if (!searchQuery.trim() || !projects || projects.length === 0) { + return projects || []; + } + + const query = searchQuery.toLowerCase().trim(); + + // Filter projects by checking all searchable fields + return projects.filter((project) => { + // Search in project name + const nameMatch = project.name?.toLowerCase().includes(query) ?? false; + + // Search in description + const descriptionMatch = project.description?.toLowerCase().includes(query) ?? false; + + // Search in primary language + const languageMatch = project.primaryLanguage?.toLowerCase().includes(query) ?? false; + + // Search in stage + const stageMatch = project.stage?.toLowerCase().includes(query) ?? false; + + // Search in popularity + const popularityMatch = project.popularity?.toLowerCase().includes(query) ?? false; + + // Search in competition level + const competitionMatch = project.competition?.toLowerCase().includes(query) ?? false; + + // Search in activity level + const activityMatch = project.activity?.toLowerCase().includes(query) ?? false; + + // Return true if any field matches the query + return ( + nameMatch || + descriptionMatch || + languageMatch || + stageMatch || + popularityMatch || + competitionMatch || + activityMatch + ); + }); + }, [projects, searchQuery]); return (
+ Showing {filteredProjects.length} of {projects.length} project{projects.length !== 1 ? 's' : ''} +
+ )} +No projects found
++ Try adjusting your search query or{" "} + +
+Find Your Next Project
- Click the 'Find projects' button above to discover open + Click the 'Filter Projects' button above to discover open source projects that match your interests