import React, { useEffect, useState } from "react"; import { useParams, useNavigate, Link } from "react-router-dom"; import { PencilSquareIcon, TrashIcon, FolderIcon, Squares2X2Icon, } from "@heroicons/react/24/outline"; import TaskList from "../Task/TaskList"; import ProjectModal from "../Project/ProjectModal"; import ConfirmDialog from "../Shared/ConfirmDialog"; import { useDataContext } from "../../contexts/DataContext"; import NewTask from "../Task/NewTask"; import { Project } from "../../entities/Project"; import { PriorityType, Task } from "../../entities/Task"; type PriorityStyles = Record & { default: string }; const priorityStyles: PriorityStyles = { high: 'bg-red-500', medium: 'bg-yellow-500', low: 'bg-green-500', default: 'bg-gray-400', }; const ProjectDetails: React.FC = () => { const { updateTask, deleteTask, updateProject, deleteProject } = useDataContext(); const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { areas } = useDataContext(); const [project, setProject] = useState(undefined); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false); const projectTitle = project?.name || "Project"; const [isCompletedOpen, setIsCompletedOpen] = useState(false); useEffect(() => { const fetchProject = async () => { try { const response = await fetch(`/api/project/${id}`, { credentials: "include", headers: { Accept: "application/json" }, }); const data = await response.json(); if (response.ok) { setProject(data); setTasks(data.tasks || []); } else { throw new Error(data.error || "Failed to fetch project."); } } catch (error) { setError((error as Error).message); } finally { setLoading(false); } }; fetchProject(); }, [id]); const handleTaskCreate = async (taskName: string) => { if (!project || project.id === undefined) { console.error("Cannot create task: Project or Project ID is missing"); return; } const taskPayload = { name: taskName, status: "not_started", project_id: project.id, }; try { const response = await fetch(`/api/task`, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, credentials: "include", body: JSON.stringify(taskPayload), }); const newTask = await response.json(); if (response.ok) { setTasks([...tasks, newTask]); } else { throw new Error(newTask.error || "Failed to create task"); } } catch (err) { console.error("Error creating task:", err); } }; const handleTaskUpdate = async (updatedTask: Task) => { if (updatedTask.id === undefined) { console.error("Cannot update task: Task ID is missing"); return; } try { await updateTask(updatedTask.id, updatedTask); setTasks((prevTasks) => prevTasks.map((task) => task.id === updatedTask.id ? updatedTask : task ) ); } catch (err) { console.error("Error updating task:", err); } }; const handleTaskDelete = async (taskId: number | undefined) => { if (taskId === undefined) { console.error("Cannot delete task: Task ID is missing"); return; } try { await deleteTask(taskId); setTasks((prevTasks) => prevTasks.filter((task) => task.id !== taskId)); } catch (err) { console.error("Error deleting task:", err); } }; const handleEditProject = () => { setIsModalOpen(true); }; const handleSaveProject = async (updatedProject: Project) => { if (!updatedProject || updatedProject.id === undefined) { console.error("Cannot save project: Project or Project ID is missing"); return; } try { const savedProject = await updateProject(updatedProject.id, updatedProject); setProject(savedProject); setIsModalOpen(false); } catch (err) { console.error("Error saving project:", err); } }; const handleDeleteProject = async () => { if (!project || project.id === undefined) { console.error("Cannot delete project: Project or Project ID is missing"); return; } try { await deleteProject(project.id); navigate("/projects"); } catch (err) { console.error("Error deleting project:", err); } }; if (loading) { return (
Loading project details...
); } if (error) { return (
{error}
); } if (!project) { return (
Project not found.
); } const activeTasks = tasks.filter(task => task.status !== 'done'); const completedTasks = tasks.filter(task => task.status === 'done'); const toggleCompleted = () => { setIsCompletedOpen(!isCompletedOpen); }; return (
{/* Project Header */}

{projectTitle}

{/* Priority Circle placed after the title */} {project.priority && (
)}
{/* Edit Project Button */} {/* Delete Project Button */}
{/* Project Area */} {project.area && (
{project.area.name.toUpperCase()}
)} {/* Project Description */} {project.description && (

{project.description}

)} {/* New Task Form */} {/* Active Tasks */}
{activeTasks.length > 0 ? ( ) : (

No active tasks.

)}
{/* Collapsible Completed Tasks */}
{isCompletedOpen && (
{completedTasks.length > 0 ? ( ) : (

No completed tasks.

)}
)}
{/* Modals */} setIsModalOpen(false)} onSave={handleSaveProject} project={project} areas={areas} /> {/* Confirm Delete Dialog */} {isConfirmDialogOpen && ( setIsConfirmDialogOpen(false)} /> )}
); }; const priorityLabel = (priority: PriorityType) => { switch (priority) { case 'high': return 'High'; case 'medium': return 'Medium'; case 'low': return 'Low'; default: return ''; } }; export default ProjectDetails;