"use client"; import { useEffect, useMemo, useState } from "react"; import { motion } from "framer-motion"; import { ExternalLink, Github, Calendar, ArrowLeft, Search } from "lucide-react"; import Link from "next/link"; export type ProjectListItem = { id: number; slug: string; title: string; description: string; content: string; tags: string[]; featured: boolean; category: string; date: string; github?: string | null; live?: string | null; imageUrl?: string | null; }; export default function ProjectsPageClient({ projects, locale, }: { projects: ProjectListItem[]; locale: string; }) { const [selectedCategory, setSelectedCategory] = useState("All"); const [searchQuery, setSearchQuery] = useState(""); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); const categories = useMemo(() => { const unique = Array.from(new Set(projects.map((p) => p.category))).filter(Boolean); return ["All", ...unique]; }, [projects]); const filteredProjects = useMemo(() => { let result = projects; if (selectedCategory !== "All") { result = result.filter((project) => project.category === selectedCategory); } if (searchQuery) { const query = searchQuery.toLowerCase(); result = result.filter( (project) => project.title.toLowerCase().includes(query) || project.description.toLowerCase().includes(query) || project.tags.some((tag) => tag.toLowerCase().includes(query)), ); } return result; }, [projects, selectedCategory, searchQuery]); if (!mounted) return null; return (
Explore my portfolio of projects, from web applications to mobile apps. Each project showcases different skills and technologies.
{project.description}
No projects found matching your criteria.