import { FC, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import useSWR, { mutate } from "swr"; // headless ui import { Disclosure, Transition } from "@headlessui/react"; // services import issuesService from "services/issues.service"; // components import { ExistingIssuesListModal } from "components/core"; import { CreateUpdateIssueModal } from "components/issues"; // ui import { CustomMenu } from "components/ui"; // icons import { ChevronRightIcon, PlusIcon, XMarkIcon } from "@heroicons/react/24/outline"; // helpers import { orderArrayBy } from "helpers/array.helper"; // types import { IIssue, UserAuth } from "types"; // fetch-keys import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys"; type Props = { parentIssue: IIssue; userAuth: UserAuth; }; export const SubIssuesList: FC = ({ parentIssue, userAuth }) => { // states const [createIssueModal, setCreateIssueModal] = useState(false); const [subIssuesListModal, setSubIssuesListModal] = useState(false); const [preloadedData, setPreloadedData] = useState | null>(null); const router = useRouter(); const { workspaceSlug, projectId, issueId } = router.query; const { data: subIssues } = useSWR( workspaceSlug && projectId && issueId ? SUB_ISSUES(issueId as string) : null, workspaceSlug && projectId && issueId ? () => issuesService.subIssues(workspaceSlug as string, projectId as string, issueId as string) : null ); const { data: issues } = useSWR( workspaceSlug && projectId ? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string) : null, workspaceSlug && projectId ? () => issuesService.getIssues(workspaceSlug as string, projectId as string) : null ); const addAsSubIssue = async (data: { issues: string[] }) => { if (!workspaceSlug || !projectId) return; await issuesService .addSubIssues(workspaceSlug as string, projectId as string, parentIssue?.id ?? "", { sub_issue_ids: data.issues, }) .then((res) => { mutate( SUB_ISSUES(parentIssue?.id ?? ""), (prevData) => { let newSubIssues = [...(prevData as IIssue[])]; data.issues.forEach((issueId: string) => { const issue = issues?.find((i) => i.id === issueId); if (issue) newSubIssues.push(issue); }); newSubIssues = orderArrayBy(newSubIssues, "created_at", "descending"); return newSubIssues; }, false ); mutate( PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), (prevData) => (prevData ?? []).map((p) => { if (data.issues.includes(p.id)) return { ...p, parent: parentIssue.id, }; return p; }), false ); mutate(PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)); }) .catch((err) => { console.log(err); }); }; const handleSubIssueRemove = (issueId: string) => { if (!workspaceSlug || !projectId) return; mutate( SUB_ISSUES(parentIssue.id ?? ""), (prevData) => prevData?.filter((i) => i.id !== issueId), false ); issuesService .patchIssue(workspaceSlug as string, projectId as string, issueId, { parent: null }) .then((res) => { mutate(SUB_ISSUES(parentIssue.id ?? "")); mutate( PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), (prevData) => (prevData ?? []).map((p) => { if (p.id === res.id) return { ...p, ...res, }; return p; }), false ); }) .catch((e) => { console.error(e); }); }; const handleCreateIssueModal = () => { setCreateIssueModal(true); setPreloadedData({ parent: parentIssue.id, }); }; const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( <> setCreateIssueModal(false)} /> setSubIssuesListModal(false)} issues={ issues?.filter( (i) => (i.parent === "" || i.parent === null) && i.id !== parentIssue?.id && i.id !== parentIssue?.parent ) ?? [] } handleOnSubmit={addAsSubIssue} /> {subIssues && subIssues.length > 0 ? ( {({ open }) => ( <>
Sub-issues {subIssues.length} {open && !isNotAllowed ? (
setSubIssuesListModal(true)}> Add an existing issue
) : null}
{subIssues.map((issue) => (
{issue.project_detail.identifier}-{issue.sequence_id} {issue.name}
{!isNotAllowed && ( )}
))}
)}
) : ( !isNotAllowed && ( Add sub-issue } optionsPosition="left" noBorder > Create new setSubIssuesListModal(true)}> Add an existing issue ) )} ); };