"use client"; import { useState } from "react"; import { useParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Select } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { useListProjectsProjectsGet } from "@/api/generated/projects/projects"; import { useListEmployeesEmployeesGet } from "@/api/generated/org/org"; import { useCreateTaskTasksPost, useListTasksTasksGet, useUpdateTaskTasksTaskIdPatch, useDeleteTaskTasksTaskIdDelete, useCreateTaskCommentTaskCommentsPost, useListTaskCommentsTaskCommentsGet, } from "@/api/generated/work/work"; import { useListProjectMembersProjectsProjectIdMembersGet, useAddProjectMemberProjectsProjectIdMembersPost, useRemoveProjectMemberProjectsProjectIdMembersMemberIdDelete, } from "@/api/generated/projects/projects"; const STATUSES = [ "backlog", "ready", "in_progress", "review", "done", "blocked", ] as const; export default function ProjectDetailPage() { const params = useParams(); const projectId = Number(params?.id); const projects = useListProjectsProjectsGet(); const project = (projects.data ?? []).find((p) => p.id === projectId); const employees = useListEmployeesEmployeesGet(); const members = useListProjectMembersProjectsProjectIdMembersGet(projectId); const addMember = useAddProjectMemberProjectsProjectIdMembersPost({ mutation: { onSuccess: () => members.refetch() }, }); const removeMember = useRemoveProjectMemberProjectsProjectIdMembersMemberIdDelete({ mutation: { onSuccess: () => members.refetch() }, }); const tasks = useListTasksTasksGet({ projectId }); const createTask = useCreateTaskTasksPost({ mutation: { onSuccess: () => tasks.refetch() }, }); const updateTask = useUpdateTaskTasksTaskIdPatch({ mutation: { onSuccess: () => tasks.refetch() }, }); const deleteTask = useDeleteTaskTasksTaskIdDelete({ mutation: { onSuccess: () => tasks.refetch() }, }); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [assigneeId, setAssigneeId] = useState(""); const [reviewerId, setReviewerId] = useState(""); const [commentTaskId, setCommentTaskId] = useState(null); const [commentBody, setCommentBody] = useState(""); const comments = useListTaskCommentsTaskCommentsGet( { taskId: commentTaskId ?? 0 }, { query: { enabled: Boolean(commentTaskId) } }, ); const addComment = useCreateTaskCommentTaskCommentsPost({ mutation: { onSuccess: () => { comments.refetch(); setCommentBody(""); }, }, }); const tasksByStatus = (() => { const map = new Map(); for (const s of STATUSES) map.set(s, []); for (const t of tasks.data ?? []) { map.get(t.status)?.push(t); } return map; })(); const employeeName = (id: number | null | undefined) => employees.data?.find((e) => e.id === id)?.name ?? "—"; const projectMembers = members.data ?? []; return (

{project?.name ?? `Project #${projectId}`}

Project detail: staffing + tasks.

Create task Project-scoped tasks setTitle(e.target.value)} />