import { FC, MouseEvent, useState } from "react"; import Link from "next/link"; // hooks import useToast from "hooks/use-toast"; // components import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles"; // ui import { CustomMenu, RadialProgressBar, Tooltip, LinearProgressIndicator, ContrastIcon, RunningIcon } from "@plane/ui"; // icons import { AlarmClock, AlertTriangle, ArrowRight, CalendarDays, LinkIcon, Pencil, Star, Target, Trash2, } from "lucide-react"; // helpers import { getDateRangeStatus, renderShortDateWithYearFormat, findHowManyDaysLeft } from "helpers/date-time.helper"; import { copyTextToClipboard } from "helpers/string.helper"; // types import { ICycle } from "types"; import { useMobxStore } from "lib/mobx/store-provider"; type TCyclesListItem = { cycle: ICycle; handleEditCycle?: () => void; handleDeleteCycle?: () => void; handleAddToFavorites?: () => void; handleRemoveFromFavorites?: () => void; workspaceSlug: string; projectId: string; }; const stateGroups = [ { key: "backlog_issues", title: "Backlog", color: "#dee2e6", }, { key: "unstarted_issues", title: "Unstarted", color: "#26b5ce", }, { key: "started_issues", title: "Started", color: "#f7ae59", }, { key: "cancelled_issues", title: "Cancelled", color: "#d687ff", }, { key: "completed_issues", title: "Completed", color: "#09a953", }, ]; export const CyclesListItem: FC = (props) => { const { cycle, workspaceSlug, projectId } = props; // store const { cycle: cycleStore } = useMobxStore(); // toast const { setToastAlert } = useToast(); // states const [updateModal, setUpdateModal] = useState(false); const [deleteModal, setDeleteModal] = useState(false); // computed const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date); const isCompleted = cycleStatus === "completed"; const endDate = new Date(cycle.end_date ?? ""); const startDate = new Date(cycle.start_date ?? ""); const handleCopyText = () => { const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`).then(() => { setToastAlert({ type: "success", title: "Link Copied!", message: "Cycle link copied to clipboard.", }); }); }; const progressIndicatorData = stateGroups.map((group, index) => ({ id: index, name: group.title, value: cycle.total_issues > 0 ? ((cycle[group.key as keyof ICycle] as number) / cycle.total_issues) * 100 : 0, color: group.color, })); const handleAddToFavorites = (e: MouseEvent) => { e.preventDefault(); if (!workspaceSlug || !projectId) return; cycleStore.addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycle.id).catch(() => { setToastAlert({ type: "error", title: "Error!", message: "Couldn't add the cycle to favorites. Please try again.", }); }); }; const handleRemoveFromFavorites = (e: MouseEvent) => { e.preventDefault(); if (!workspaceSlug || !projectId) return; cycleStore.removeCycleFromFavorites(workspaceSlug?.toString(), projectId.toString(), cycle.id).catch(() => { setToastAlert({ type: "error", title: "Error!", message: "Couldn't add the cycle to favorites. Please try again.", }); }); }; return ( <>
{/* left content */}
{/* cycle state */}
{/* cycle title and description */}
{cycle.name}
{cycle.description && (
{cycle.description}
)}
{/* right content */}
{/* cycle status */}
{cycleStatus === "current" ? ( {findHowManyDaysLeft(cycle.end_date ?? new Date())} days left ) : cycleStatus === "upcoming" ? ( {findHowManyDaysLeft(cycle.start_date ?? new Date())} days left ) : cycleStatus === "completed" ? ( {cycle.total_issues - cycle.completed_issues > 0 && ( )}{" "} Completed ) : ( cycleStatus )}
{/* cycle start_date and target_date */} {cycleStatus !== "draft" && (
{renderShortDateWithYearFormat(startDate)}
{renderShortDateWithYearFormat(endDate)}
)} {/* cycle created by */}
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? ( {cycle.owned_by.display_name} ) : ( {cycle.owned_by.display_name.charAt(0)} )}
{/* cycle progress */} Progress
} > {cycleStatus === "current" ? ( {cycle.total_issues > 0 ? ( <> {Math.floor((cycle.completed_issues / cycle.total_issues) * 100)} % ) : ( No issues present )} ) : cycleStatus === "upcoming" ? ( Yet to start ) : cycleStatus === "completed" ? ( {100} % ) : ( {cycleStatus} )} {/* cycle favorite */} {cycle.is_favorite ? ( ) : ( )}
{!isCompleted && ( setUpdateModal(true)}> Edit Cycle )} {!isCompleted && ( setDeleteModal(true)}> Delete cycle )} Copy cycle link
setUpdateModal(false)} workspaceSlug={workspaceSlug} projectId={projectId} /> setDeleteModal(false)} workspaceSlug={workspaceSlug} projectId={projectId} /> ); };