diff --git a/apps/app/components/cycles/completed-cycles-list.tsx b/apps/app/components/cycles/completed-cycles-list.tsx new file mode 100644 index 000000000..b283e3da6 --- /dev/null +++ b/apps/app/components/cycles/completed-cycles-list.tsx @@ -0,0 +1,82 @@ +// react +import { useState } from "react"; +// next +import { useRouter } from "next/router"; +import useSWR from "swr"; + +// components +import { DeleteCycleModal, SingleCycleCard } from "components/cycles"; +// types +import { ICycle, SelectCycleType } from "types"; +import { CompletedCycleIcon } from "components/icons"; +import cyclesService from "services/cycles.service"; +import { CYCLE_COMPLETE_LIST } from "constants/fetch-keys"; + +type Props = { + setCreateUpdateCycleModal: React.Dispatch>; + setSelectedCycle: React.Dispatch>; +}; + +export const CompletedCyclesList: React.FC = ({ + setCreateUpdateCycleModal, + setSelectedCycle, +}) => { + const [cycleDeleteModal, setCycleDeleteModal] = useState(false); + const [selectedCycleForDelete, setSelectedCycleForDelete] = useState(); + + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const { data: completedCycles } = useSWR( + workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => cyclesService.getCompletedCycles(workspaceSlug as string, projectId as string) + : null + ); + + const handleDeleteCycle = (cycle: ICycle) => { + setSelectedCycleForDelete({ ...cycle, actionType: "delete" }); + setCycleDeleteModal(true); + }; + + const handleEditCycle = (cycle: ICycle) => { + setSelectedCycle({ ...cycle, actionType: "edit" }); + setCreateUpdateCycleModal(true); + }; + + return ( + <> + {completedCycles && ( + <> + + {completedCycles?.completed_cycles.length > 0 ? ( + completedCycles.completed_cycles.map((cycle) => ( + handleDeleteCycle(cycle)} + handleEditCycle={() => handleEditCycle(cycle)} + /> + )) + ) : ( +
+ +

+ No completed cycles yet. Create with{" "} +
Q
. +

+
+ )} + + )} + + ); +}; diff --git a/apps/app/components/cycles/cycles-list-view.tsx b/apps/app/components/cycles/cycles-list.tsx similarity index 97% rename from apps/app/components/cycles/cycles-list-view.tsx rename to apps/app/components/cycles/cycles-list.tsx index 8491190e8..e55f0e6f1 100644 --- a/apps/app/components/cycles/cycles-list-view.tsx +++ b/apps/app/components/cycles/cycles-list.tsx @@ -13,7 +13,7 @@ type TCycleStatsViewProps = { type: "current" | "upcoming" | "completed"; }; -export const CyclesListView: React.FC = ({ +export const CyclesList: React.FC = ({ cycles, setCreateUpdateCycleModal, setSelectedCycle, diff --git a/apps/app/components/cycles/index.ts b/apps/app/components/cycles/index.ts index 77dcb06a9..d1fd0d6b6 100644 --- a/apps/app/components/cycles/index.ts +++ b/apps/app/components/cycles/index.ts @@ -1,4 +1,5 @@ -export * from "./cycles-list-view"; +export * from "./completed-cycles-list"; +export * from "./cycles-list"; export * from "./delete-cycle-modal"; export * from "./form"; export * from "./modal"; diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index df18ba620..78229fc54 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -1,30 +1,47 @@ import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; +import dynamic from "next/dynamic"; import useSWR from "swr"; import { PlusIcon } from "@heroicons/react/24/outline"; import { Tab } from "@headlessui/react"; // lib import { requiredAuth } from "lib/auth"; -import { CyclesIcon } from "components/icons"; + // services import cycleService from "services/cycles.service"; import projectService from "services/project.service"; -import workspaceService from "services/workspace.service"; + // layouts import AppLayout from "layouts/app-layout"; // components -import { CreateUpdateCycleModal, CyclesListView } from "components/cycles"; +import { CreateUpdateCycleModal, CyclesList } from "components/cycles"; // ui -import { HeaderButton, EmptySpace, EmptySpaceItem, Loader } from "components/ui"; +import { HeaderButton, Loader } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; // icons // types -import { ICycle, SelectCycleType } from "types"; +import { SelectCycleType } from "types"; import type { NextPage, GetServerSidePropsContext } from "next"; // fetching keys -import { CYCLE_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys"; +import { + CYCLE_COMPLETE_LIST, + CYCLE_CURRENT_AND_UPCOMING_LIST, + PROJECT_DETAILS, +} from "constants/fetch-keys"; + +const CompletedCyclesList = dynamic( + () => import("components/cycles").then((a) => a.CompletedCyclesList), + { + ssr: false, + loading: () => ( + + + + ), + } +); const ProjectCycles: NextPage = () => { const [selectedCycle, setSelectedCycle] = useState(); @@ -34,22 +51,17 @@ const ProjectCycles: NextPage = () => { query: { workspaceSlug, projectId }, } = useRouter(); - const { data: activeWorkspace } = useSWR( - workspaceSlug ? WORKSPACE_DETAILS(workspaceSlug as string) : null, - () => (workspaceSlug ? workspaceService.getWorkspace(workspaceSlug as string) : null) - ); - const { data: activeProject } = useSWR( - activeWorkspace && projectId ? PROJECT_DETAILS(projectId as string) : null, - activeWorkspace && projectId - ? () => projectService.getProject(activeWorkspace.slug, projectId as string) + workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null, + workspaceSlug && projectId + ? () => projectService.getProject(workspaceSlug as string, projectId as string) : null ); - const { data: cycles } = useSWR( - activeWorkspace && projectId ? CYCLE_LIST(projectId as string) : null, - activeWorkspace && projectId - ? () => cycleService.getCycles(activeWorkspace.slug, projectId as string) + const { data: currentAndUpcomingCycles } = useSWR( + workspaceSlug && projectId ? CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => cycleService.getCurrentAndUpcomingCycles(workspaceSlug as string, projectId as string) : null ); @@ -61,18 +73,6 @@ const ProjectCycles: NextPage = () => { else return "current"; }; - const currentCycles = cycles?.filter( - (c) => getCycleStatus(c.start_date, c.end_date) === "current" - ); - - const upcomingCycles = cycles?.filter( - (c) => getCycleStatus(c.start_date, c.end_date) === "upcoming" - ); - - const completedCycles = cycles?.filter( - (c) => getCycleStatus(c.start_date, c.end_date) === "completed" - ); - useEffect(() => { if (createUpdateCycleModal) return; const timer = setTimeout(() => { @@ -110,92 +110,56 @@ const ProjectCycles: NextPage = () => { handleClose={() => setCreateUpdateCycleModal(false)} data={selectedCycle} /> - {cycles ? ( - cycles.length > 0 ? ( -
-

Current Cycle

-
- -
-
- - - - `rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` - } - > - Upcoming - - - `rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` - } - > - Completed - - - - - - - - - - - -
-
- ) : ( -
- +

Current Cycle

+
+ +
+
+ + - - Use
Q
shortcut to - create a new cycle - + + `rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` } - Icon={PlusIcon} - action={() => { - const e = new KeyboardEvent("keydown", { - key: "q", - }); - document.dispatchEvent(e); - }} - /> - -
- ) - ) : ( - - - - - )} + > + Upcoming + + + `rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` + } + > + Completed + + + + + + + + + + + +
+ ); };