"use client" import ProjectCard from "./project-card" import { SectionWrapper } from "@/app/components/wrappers/SectionWrapper" import { LABELS } from "@/app/labels" import { useProjects } from "@/app/providers/ProjectsProvider" import { ProjectInterface, ProjectSection, ProjectSectionLabelMapping, ProjectSections, ProjectStatus, ProjectStatusDescriptionMapping, } from "@/lib/types" import { cn } from "@/lib/utils" import NoResultIcon from "@/public/icons/no-result.svg" import Image from "next/image" import React, { useCallback, useEffect, useRef, useState } from "react" const NoResults = () => { return (
No projects found
{LABELS.COMMON.NO_RESULTS} {LABELS.COMMON.NO_RESULTS_DESCRIPTION}
) } const ProjectStatusOrderList = ["active", "maintained", "inactive"] export const ProjectList = () => { const SCROLL_OFFSET = -400 const [activeId, setActiveId] = useState("") const [isManualScroll, setIsManualScroll] = useState(false) const [isMounted, setIsMounted] = useState(false) const { projects, searchQuery, activeFilters } = useProjects() const hasSearchParams = searchQuery?.length > 0 || Object.values({ keywords: activeFilters?.keywords ?? [], builtWith: activeFilters?.builtWith ?? [], themes: activeFilters?.themes ?? [], }).some((arr) => arr.length > 0) const noItems = projects?.length === 0 const sectionsRef = useRef | null>(null) // sections are constant so useRef might be better here useEffect(() => { setIsMounted(true) if (typeof window !== "undefined") { sectionsRef.current = document.querySelectorAll("div[data-section]") const handleScroll = () => { if (isManualScroll) return sectionsRef.current?.forEach((section: any) => { const sectionTop = section.offsetTop - SCROLL_OFFSET if (window.scrollY >= sectionTop && window.scrollY > 0) { setActiveId(section.getAttribute("id")) } }) } window.addEventListener("scroll", handleScroll) return () => window.removeEventListener("scroll", handleScroll) } }, [SCROLL_OFFSET, isManualScroll]) const scrollToId = useCallback((id: string) => { if (typeof window !== "undefined") { const element = document.getElementById(id) const top = element?.offsetTop ?? 0 if (element) { setActiveId(id) // active clicked id setIsManualScroll(true) // tell the window event listener to ignore this scrolling window?.scrollTo({ behavior: "smooth", top: (top ?? 0) - SCROLL_OFFSET, }) } setTimeout(() => setIsManualScroll(false), 800) } }, []) // loading state skeleton if (!isMounted) { return (
) } if (noItems) return const projectsGroupByStatus = projects.reduce((acc, project) => { acc[project.projectStatus] = [ ...(acc[project.projectStatus] || []), project, ] return acc }, {} as Record) if (hasSearchParams) { return (
{projects?.map((project: any) => ( ))}
) } return (
{ProjectStatusOrderList.map((status, index) => { const projects = projectsGroupByStatus[status as ProjectStatus] ?? [] const description = ProjectStatusDescriptionMapping?.[status as ProjectStatus] const hasProjects = projects?.length > 0 if (!hasProjects) return null // no projects for this status, hide the section return (
{projects.map((project: any) => ( ))}
) })}
) }