Newer
Older
My-Portfolio / frontend / src / components / sections / Work.jsx
//React
import { useState, useEffect, useContext } from "react";

//Framer Motion
import { motion } from "framer-motion";

//Components
import ProjectCard from "../ProjectCard";

//Utils
import Heading from "../Heading";
import { LoadingContext } from "../utils/LoadingContext";
import NavigationDots from "../utils/NavigationDots";

//Assets
import { tag_icon, all_tags } from "../../assets";

//CSS
import "./Work.css";

const Work = ({ isVisible, work }) => {
  const [activeCategory, setActiveCategory] = useState({
    category_id: "All",
    category_name: "All",
    category_logo: all_tags,
    tags: [],
  });
  const [selectedTags, setSelectedTags] = useState([]);
  const [hoveredProjectId, setHoveredProjectId] = useState(null);
  const [filteredProjects, setFilteredProjects] = useState([]);

  const { isLoading } = useContext(LoadingContext);

  if (!work.categories) {
    return <div>Loading...</div>;
  }

  if (isLoading) return <div>Loading...</div>;

  const allCategory = {
    category_id: "All",
    category_name: "All",
    category_logo: all_tags,
    tags: [],
  };

  const categoriesWithAll = [allCategory, ...work.categories];

  useEffect(() => {
    const filterProjectsByTags = () => {
      const filtered = work.projects.filter((project) => {
        const matchesCategory =
          activeCategory.category_name === "All" ||
          project.category === activeCategory.category_name;

        const matchesTags =
          selectedTags.length === 0 ||
          selectedTags.every(
            (tag) => project.tags?.includes(tag) || project.tech?.includes(tag)
          );

        return matchesCategory && matchesTags;
      });
      setFilteredProjects(filtered);
    };

    filterProjectsByTags();
  }, [work.projects, activeCategory, selectedTags]);

  const handleCategoryClick = (category) => {
    setActiveCategory(category);
    setSelectedTags([]);
  };

  const handleTagClick = (tag) => {
    setSelectedTags((prev) =>
      prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
    );
  };

  return (
    <motion.div
      className="relative min-h-screen z-2 pt-2 sm:pt-10 sm:px-4"
      id="work"
      initial={{ opacity: 0, y: 100 }} // Start off-screen
      animate={isVisible ? { opacity: 1, y: 0 } : { opacity: 0, y: 100 }} // Slide-in when visible
      transition={{ duration: 0.2, ease: "easeOut" }}
    >
      <Heading
        title="My Portfolio"
        highlightWords={[{ word: "Portfolio", color: "text-orange-500" }]}
      />
      <NavigationDots currentSectionId="work" />

      <div className="flex flex-col items-center">
        <motion.div
          className="flex flex-wrap gap-8 mb-6 justify-center"
          initial="hidden"
          animate="visible"
          variants={{
            hidden: { opacity: 0, y: 50 },
            visible: { opacity: 1, y: 0 },
          }}
          transition={{ staggerChildren: 0.1 }}
        >
          {categoriesWithAll.map((category) => (
            <motion.button
              key={category.category_id}
              onClick={() => handleCategoryClick(category)}
              whileHover={{ scale: 1.1 }}
              whileTap={{ scale: 0.9 }}
              className={`flex items-center gap-2 px-6 lg:px-10 py-4 text-xl rounded-lg transition-all duration-200 ${
                activeCategory.category_id === category.category_id
                  ? "bg-orange-500 text-white font-bold"
                  : "bg-black text-gray-200 hover:bg-gray-600"
              }`}
            >
              {category.category_logo && ( // Only render the logo if it exists
                <img
                  src={category.category_logo}
                  alt={`${category.category_name} Logo`}
                  className="w-6 h-6 lg:w-8 lg:h-8"
                />
              )}
              {category.category_name}
            </motion.button>
          ))}
        </motion.div>

        {activeCategory.category_name !== "All" &&
          work.categories.find(
            (cat) => cat.category_id === activeCategory.category_id
          )?.tags?.length > 0 && (
            <motion.div
              className="flex flex-wrap gap-4 mb-10 justify-center"
              initial="hidden"
              animate="visible"
              variants={{
                hidden: { opacity: 0, y: 50 },
                visible: { opacity: 1, y: 0 },
              }}
              transition={{ staggerChildren: 0.1 }}
            >
              {work.categories
                .find((cat) => cat.category_id === activeCategory.category_id)
                ?.tags?.map(
                  (
                    tag // Map over its tags
                  ) => (
                    <motion.button
                      key={tag}
                      onClick={() => handleTagClick(tag)}
                      whileHover={{ scale: 1.1 }}
                      whileTap={{ scale: 0.9 }}
                      className={`flex items-center px-4 py-1 rounded-lg transition-all duration-200 ${
                        selectedTags.includes(tag)
                          ? "bg-orange-500 text-white"
                          : "bg-black text-gray-200 hover:bg-gray-600"
                      }`}
                    >
                      <img
                        src={tag_icon}
                        alt="Tag Logo"
                        className="mr-2 w-4 h-4"
                      />
                      {tag}
                    </motion.button>
                  )
                )}
            </motion.div>
          )}

        <motion.div
          className="flex flex-wrap justify-center gap-8 px-8 mt-5"
          initial="hidden"
          animate="visible"
          variants={{
            hidden: { opacity: 0 },
            visible: { opacity: 1, transition: { staggerChildren: 0.2 } },
          }}
        >
          {filteredProjects.map((project) => (
            <ProjectCard
              key={project.id}
              project={project}
              hoveredProjectId={hoveredProjectId}
              setHoveredProjectId={setHoveredProjectId}
            />
          ))}
        </motion.div>
      </div>
    </motion.div>
  );
};

export default Work;