import React, { useCallback, useEffect, useState } from "react"; // next import Link from "next/link"; import dynamic from "next/dynamic"; import type { NextPage } from "next"; import { useRouter } from "next/router"; // swr import { mutate } from "swr"; // react hook form import { useForm } from "react-hook-form"; // headless ui import { Disclosure, Menu, Tab, Transition } from "@headlessui/react"; // fetch keys import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; // services import issuesServices from "lib/services/issues.service"; // common import { debounce } from "constants/common"; // hooks import useUser from "lib/hooks/useUser"; // hoc import withAuth from "lib/hoc/withAuthWrapper"; // layouts import AppLayout from "layouts/app-layout"; // components import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-issue"; import CreateUpdateIssuesModal from "components/project/issues/create-update-issue-modal"; import IssueDetailSidebar from "components/project/issues/issue-detail/issue-detail-sidebar"; import IssueCommentSection from "components/project/issues/issue-detail/comment/IssueCommentSection"; const IssueActivitySection = dynamic( () => import("components/project/issues/issue-detail/activity"), { loading: () => (
), ssr: false, } ); // ui import { Spinner, TextArea, HeaderButton, Breadcrumbs } from "ui"; // icons import { ChevronLeftIcon, ChevronRightIcon, EllipsisHorizontalIcon, PlusIcon, } from "@heroicons/react/24/outline"; // types import { IIssue, IssueResponse } from "types"; const RichTextEditor = dynamic(() => import("components/lexical/editor"), { ssr: false, }); const defaultValues = { name: "", description: "", state: "", assignees_list: [], priority: "low", blockers_list: [], blocked_list: [], target_date: new Date().toString(), issue_cycle: null, labels_list: [], }; const IssueDetail: NextPage = () => { const router = useRouter(); const { issueId, projectId } = router.query; const { activeWorkspace, activeProject, issues, mutateIssues } = useUser(); const issueDetail = issues?.results?.find((issue) => issue.id === issueId); const prevIssue = issues?.results[issues?.results.findIndex((issue) => issue.id === issueId) - 1]; const nextIssue = issues?.results[issues?.results.findIndex((issue) => issue.id === issueId) + 1]; const subIssues = (issues && issues.results.filter((i) => i.parent === issueId)) ?? []; const siblingIssues = issueDetail && issues?.results.filter((i) => i.parent === issueDetail.parent && i.id !== issueId); const [isOpen, setIsOpen] = useState(false); const [isAddAsSubIssueOpen, setIsAddAsSubIssueOpen] = useState(false); const [preloadedData, setPreloadedData] = useState< (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined >(undefined); const [issueDescriptionValue, setIssueDescriptionValue] = useState(""); const handleDescriptionChange: any = (value: any) => { console.log(value); setIssueDescriptionValue(value); }; const { register, formState: { errors }, handleSubmit, reset, control, watch, } = useForm({ defaultValues, }); const submitChanges = useCallback( (formData: Partial) => { if (!activeWorkspace || !activeProject || !issueId) return; mutateIssues( (prevData) => ({ ...(prevData as IssueResponse), results: (prevData?.results ?? []).map((issue) => { if (issue.id === issueId) { return { ...issue, ...formData }; } return issue; }), }), false ); const payload = { ...formData, // description: formData.description ? JSON.parse(formData.description) : null, }; issuesServices .patchIssue(activeWorkspace.slug, projectId as string, issueId as string, payload) .then((response) => { mutateIssues((prevData) => ({ ...(prevData as IssueResponse), results: (prevData?.results ?? []).map((issue) => { if (issue.id === issueId) { return { ...issue, ...response }; } return issue; }), })); }) .catch((error) => { console.log(error); }); }, [activeProject, activeWorkspace, issueId, projectId, mutateIssues] ); useEffect(() => { if (issueDetail) reset({ ...issueDetail, // description: JSON.stringify(issueDetail.description), blockers_list: issueDetail.blockers_list ?? issueDetail.blocker_issues?.map((issue) => issue.blocker_issue_detail?.id), blocked_list: issueDetail.blocked_list ?? issueDetail.blocked_issues?.map((issue) => issue.blocked_issue_detail?.id), assignees_list: issueDetail.assignees_list ?? issueDetail.assignee_details?.map((user) => user.id), labels_list: issueDetail.labels_list ?? issueDetail.labels, labels: issueDetail.labels_list ?? issueDetail.labels, }); }, [issueDetail, reset]); const handleSubIssueRemove = (issueId: string) => { if (activeWorkspace && activeProject) { issuesServices .patchIssue(activeWorkspace.slug, activeProject.id, issueId, { parent: null }) .then((res) => { mutate( PROJECT_ISSUES_LIST(activeWorkspace.slug, activeProject.id), (prevData) => ({ ...(prevData as IssueResponse), results: (prevData?.results ?? []).map((p) => p.id === issueId ? { ...p, ...res } : p ), }), false ); }) .catch((e) => { console.log(e); }); } }; return ( } right={
{ if (!prevIssue) return; router.push(`/projects/${prevIssue.project}/issues/${prevIssue.id}`); }} /> { if (!nextIssue) return; router.push(`/projects/${nextIssue.project}/issues/${nextIssue?.id}`); }} position="reverse" />
} > {isOpen && ( )} {isAddAsSubIssueOpen && ( )} {issueDetail && activeProject ? (
{issueDetail.parent !== null && issueDetail.parent !== "" ? ( ) : null}