import { FC, useState } from "react"; import { mutate } from "swr"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // ui icons import { DiceIcon, DoubleCircleIcon, UserGroupIcon } from "@plane/ui"; import { CalendarDays, ContrastIcon, Link2, Plus, Signal, Tag, Triangle, User2 } from "lucide-react"; import { SidebarAssigneeSelect, SidebarCycleSelect, SidebarEstimateSelect, SidebarLabelSelect, SidebarModuleSelect, SidebarParentSelect, SidebarPrioritySelect, SidebarStateSelect, } from "../sidebar-select"; // hooks import useToast from "hooks/use-toast"; // components import { CustomDatePicker } from "components/ui"; import { LinkModal, LinksList } from "components/core"; // types import { IIssue, IIssueLink, TIssuePriorities, linkDetails } from "types"; import { ISSUE_DETAILS } from "constants/fetch-keys"; // services import { IssueService } from "services/issue"; interface IPeekOverviewProperties { issue: IIssue; issueUpdate: (issue: Partial) => void; disableUserActions: boolean; } const issueService = new IssueService(); export const PeekOverviewProperties: FC = observer((props) => { const { issue, issueUpdate, disableUserActions } = props; // states const [linkModal, setLinkModal] = useState(false); const [selectedLinkToUpdate, setSelectedLinkToUpdate] = useState(null); const { user: userStore, cycleIssue: cycleIssueStore, moduleIssue: moduleIssueStore } = useMobxStore(); const userRole = userStore.currentProjectRole; const router = useRouter(); const { workspaceSlug, projectId } = router.query; const { setToastAlert } = useToast(); const handleState = (_state: string) => { issueUpdate({ ...issue, state: _state }); }; const handlePriority = (_priority: TIssuePriorities) => { issueUpdate({ ...issue, priority: _priority }); }; const handleAssignee = (_assignees: string[]) => { issueUpdate({ ...issue, assignees: _assignees }); }; const handleEstimate = (_estimate: number | null) => { issueUpdate({ ...issue, estimate_point: _estimate }); }; const handleStartDate = (_startDate: string | null) => { issueUpdate({ ...issue, start_date: _startDate }); }; const handleTargetDate = (_targetDate: string | null) => { issueUpdate({ ...issue, target_date: _targetDate }); }; const handleParent = (_parent: string) => { issueUpdate({ ...issue, parent: _parent }); }; const addIssueToCycle = async (cycleId: string) => { if (!workspaceSlug || !issue || !cycleId) return; cycleIssueStore.addIssueToCycle(workspaceSlug.toString(), issue.project_detail.id, cycleId, [issue.id]); }; const addIssueToModule = async (moduleId: string) => { if (!workspaceSlug || !issue || !moduleId) return; moduleIssueStore.addIssueToModule(workspaceSlug.toString(), issue.project_detail.id, moduleId, [issue.id]); }; const handleLabels = (formData: Partial) => { issueUpdate({ ...issue, ...formData }); }; const handleCreateLink = async (formData: IIssueLink) => { if (!workspaceSlug || !projectId || !issue) return; const payload = { metadata: {}, ...formData }; await issueService .createIssueLink(workspaceSlug as string, projectId as string, issue.id, payload) .then(() => mutate(ISSUE_DETAILS(issue.id))) .catch((err) => { if (err.status === 400) setToastAlert({ type: "error", title: "Error!", message: "This URL already exists for this issue.", }); else setToastAlert({ type: "error", title: "Error!", message: "Something went wrong. Please try again.", }); }); }; const handleUpdateLink = async (formData: IIssueLink, linkId: string) => { if (!workspaceSlug || !projectId || !issue) return; const payload = { metadata: {}, ...formData }; const updatedLinks = issue.issue_link.map((l) => l.id === linkId ? { ...l, title: formData.title, url: formData.url, } : l ); mutate( ISSUE_DETAILS(issue.id), (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), false ); await issueService .updateIssueLink(workspaceSlug as string, projectId as string, issue.id, linkId, payload) .then(() => { mutate(ISSUE_DETAILS(issue.id)); }) .catch((err) => { console.log(err); }); }; const handleEditLink = (link: linkDetails) => { setSelectedLinkToUpdate(link); setLinkModal(true); }; const handleDeleteLink = async (linkId: string) => { if (!workspaceSlug || !projectId || !issue) return; const updatedLinks = issue.issue_link.filter((l) => l.id !== linkId); mutate( ISSUE_DETAILS(issue.id), (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), false ); await issueService .deleteIssueLink(workspaceSlug as string, projectId as string, issue.id, linkId) .then(() => { mutate(ISSUE_DETAILS(issue.id)); }) .catch((err) => { console.log(err); }); }; const minDate = issue.start_date ? new Date(issue.start_date) : null; minDate?.setDate(minDate.getDate()); const maxDate = issue.target_date ? new Date(issue.target_date) : null; maxDate?.setDate(maxDate.getDate()); return ( <> { setLinkModal(false); setSelectedLinkToUpdate(null); }} data={selectedLinkToUpdate} status={selectedLinkToUpdate ? true : false} createIssueLink={handleCreateLink} updateIssueLink={handleUpdateLink} />
{/* state */}

State

{/* assignee */}

Assignees

{/* priority */}

Priority

{/* estimate */}

Estimate

{/* start date */}

Start date

{/* due date */}

Due date

{/* parent */}

Parent

Cycle

Module

Label

Links

{!disableUserActions && ( )}
{issue?.issue_link && issue.issue_link.length > 0 ? ( ) : null}
); });