mnisyif_frontend/src/components/projects/Projects.jsx

59 lines
1.9 KiB
JavaScript

import React, { useState, useCallback, useMemo } from "react";
import ProjectCard from "./projectCard/ProjectCard";
import ProjectModal from "./projectModal/ProjectModal";
import styles from "./Projects.module.css";
function Projects({ title, data }) {
const [selectedProject, setSelectedProject] = useState(null);
const [activeFilter, setActiveFilter] = useState("All");
const [animatingOut, setAnimatingOut] = useState(false);
const openModal = (project) => {
setSelectedProject(project);
};
const closeModal = useCallback(() => {
setSelectedProject(null);
}, []);
const categories = useMemo(() => {
const cats = new Set(data.map((project) => project.category));
return ["All", ...Array.from(cats)];
}, [data]);
const filteredProjects = useMemo(() => {
if (activeFilter === "All") return data;
return data.filter((project) => project.category === activeFilter);
}, [data, activeFilter]);
const handleFilterClick = (category) => {
if (category !== activeFilter) {
setAnimatingOut(true);
setTimeout(() => {
setActiveFilter(category);
setAnimatingOut(false);
}, 300); // This should match the CSS animation duration
}
};
return (
<section className={styles.projects}>
<h2 className={styles.sectionTitle}>{title}</h2>
<div className={styles.filterContainer}>
{categories.map((category) => (
<button key={category} className={`${styles.filterButton} ${activeFilter === category ? styles.active : ""}`} onClick={() => handleFilterClick(category)}>
{category}
</button>
))}
</div>
<div className={styles.projectGrid}>
{filteredProjects.map((project) => (
<ProjectCard key={project.id} project={project} onClick={openModal} className={animatingOut ? styles.fadeOut : styles.fadeIn} />
))}
</div>
{selectedProject && <ProjectModal project={selectedProject} onClose={closeModal} />}
</section>
);
}
export default Projects;