"use client";
import { useState, useEffect } from "react";
import SafeImage from "./SafeImage";
interface Task {
name: string;
description: string;
status: string;
technologies: string[];
}
interface ProjectLink {
name: string;
url: string;
}
interface Project {
name: string;
description: string;
logo?: string;
links?: ProjectLink[];
tasks: Task[];
}
interface ProjectsProps {
projects: Project[];
}
function ProjectRow({
project,
index,
isOpen,
onToggle
}: {
project: Project;
index: number;
isOpen: boolean;
onToggle: () => void;
}) {
const allTechs = Array.from(
new Set(project.tasks.flatMap((t) => t.technologies))
);
const doneCount = project.tasks.filter((t) => t.status === "Done").length;
return (
{/* Header bar (always visible) */}
{/* Expandable Content */}
{/* Top part: Description & Links & Techs */}
{project.description}
{allTechs.map((tech) => (
{tech}
))}
Development Status
{doneCount}/{project.tasks.length}
Tasks Completed
{/* Bottom part: Tasks Grid */}
Project Milestones
{project.tasks.map((task) => (
{task.name}
{task.status}
{task.description}
))}
);
}
export default function Projects({ projects }: ProjectsProps) {
const [openIndex, setOpenIndex] = useState(0);
useEffect(() => {
const handleOpenProject = (e: CustomEvent) => {
if (typeof e.detail?.index === "number") {
setOpenIndex(e.detail.index);
}
};
window.addEventListener("openProject", handleOpenProject as EventListener);
return () => window.removeEventListener("openProject", handleOpenProject as EventListener);
}, []);
return (
{/* Section header */}
Selected Work
Projects
{String(projects.length).padStart(2, "0")} total
{/* List */}
{projects.map((project, i) => (
setOpenIndex(openIndex === i ? null : i)}
/>
))}
);
}