From d480325829001c9ac2162e99cfd87c24d1ec0657 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Tue, 28 Feb 2023 10:31:52 +0530 Subject: [PATCH 01/10] chore: cycle validation services and constants added --- apps/app/constants/fetch-keys.ts | 2 ++ apps/app/services/cycles.service.ts | 31 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/apps/app/constants/fetch-keys.ts b/apps/app/constants/fetch-keys.ts index a2831d818..99dcff81f 100644 --- a/apps/app/constants/fetch-keys.ts +++ b/apps/app/constants/fetch-keys.ts @@ -35,6 +35,8 @@ export const PROJECT_GITHUB_REPOSITORY = (projectId: string) => export const CYCLE_LIST = (projectId: string) => `CYCLE_LIST_${projectId}`; export const CYCLE_ISSUES = (cycleId: string) => `CYCLE_ISSUES_${cycleId}`; export const CYCLE_DETAILS = (cycleId: string) => `CYCLE_DETAIL_${cycleId}`; +export const CYCLE_CURRENT_AND_UPCOMING_LIST = (projectId: string) => `CYCLE_CURRENT_AND_UPCOMING_LIST_${projectId}`; +export const CYCLE_COMPLETE_LIST = (projectId: string) => `CYCLE_COMPLETE_LIST_${projectId}`; export const STATE_LIST = (projectId: string) => `STATE_LIST_${projectId}`; export const STATE_DETAIL = "STATE_DETAIL"; diff --git a/apps/app/services/cycles.service.ts b/apps/app/services/cycles.service.ts index 109b62108..fa9769dc8 100644 --- a/apps/app/services/cycles.service.ts +++ b/apps/app/services/cycles.service.ts @@ -87,6 +87,37 @@ class ProjectCycleServices extends APIService { throw error?.response?.data; }); } + + async cycleDateCheck(workspaceSlug: string, projectId: string, data: { + start_date: string, + end_date: string + }): Promise { + return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/date-check/`, data) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + + async getCurrentAndUpcomingCycles(workspaceSlug: string, projectId: string): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/current-upcoming-cycles/` + ) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + + async getCompletedCycles(workspaceSlug: string, projectId: string): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/past-cycles/` + ) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } } export default new ProjectCycleServices(); From 443c9300ddeb236cca6bf29e773ee795fab3e476 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Tue, 28 Feb 2023 14:47:32 +0530 Subject: [PATCH 02/10] chore: cycle type and services updated --- apps/app/services/cycles.service.ts | 8 ++++---- apps/app/types/cycles.d.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/app/services/cycles.service.ts b/apps/app/services/cycles.service.ts index fa9769dc8..42f2f21ae 100644 --- a/apps/app/services/cycles.service.ts +++ b/apps/app/services/cycles.service.ts @@ -1,7 +1,7 @@ // services import APIService from "services/api.service"; // types -import type { ICycle } from "types"; +import type { CompletedCyclesResponse, CurrentAndUpcomingCyclesResponse, ICycle } from "types"; const { NEXT_PUBLIC_API_BASE_URL } = process.env; @@ -99,7 +99,7 @@ class ProjectCycleServices extends APIService { }); } - async getCurrentAndUpcomingCycles(workspaceSlug: string, projectId: string): Promise { + async getCurrentAndUpcomingCycles(workspaceSlug: string, projectId: string): Promise { return this.get( `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/current-upcoming-cycles/` ) @@ -109,9 +109,9 @@ class ProjectCycleServices extends APIService { }); } - async getCompletedCycles(workspaceSlug: string, projectId: string): Promise { + async getCompletedCycles(workspaceSlug: string, projectId: string): Promise { return this.get( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/past-cycles/` + `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/completed-cycles/` ) .then((response) => response?.data) .catch((error) => { diff --git a/apps/app/types/cycles.d.ts b/apps/app/types/cycles.d.ts index dbd7573bf..060fe53f3 100644 --- a/apps/app/types/cycles.d.ts +++ b/apps/app/types/cycles.d.ts @@ -15,8 +15,20 @@ export interface ICycle { project: string; workspace: string; issue: string; + current_cycle: []; + upcoming_cycle: []; + past_cycles: []; } +export interface CurrentAndUpcomingCyclesResponse { + current_cycle : ICycle[]; + upcoming_cycle : ICycle[]; +} + +export interface CompletedCyclesResponse { + completed_cycles : ICycle[]; + } + export interface CycleIssueResponse { id: string; issue_detail: IIssue; From 17e09d70e2e3895145c0f8f77bde41a51591facf Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Tue, 28 Feb 2023 14:53:10 +0530 Subject: [PATCH 03/10] chore: completed cycle dynamic importing and refactor --- .../cycles/completed-cycles-list.tsx | 82 ++++++++ .../{cycles-list-view.tsx => cycles-list.tsx} | 2 +- apps/app/components/cycles/index.ts | 3 +- .../projects/[projectId]/cycles/index.tsx | 192 +++++++----------- 4 files changed, 163 insertions(+), 116 deletions(-) create mode 100644 apps/app/components/cycles/completed-cycles-list.tsx rename apps/app/components/cycles/{cycles-list-view.tsx => cycles-list.tsx} (97%) 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 + + + + + + + + + + + +
+ ); }; From 19e9f510bc7d62cec3ffdbcf579c2f6eb80795cc Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Tue, 28 Feb 2023 14:55:19 +0530 Subject: [PATCH 04/10] feat: cycle modal date validation --- apps/app/components/cycles/form.tsx | 100 +++++++++++++++++++-------- apps/app/components/cycles/modal.tsx | 2 +- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/apps/app/components/cycles/form.tsx b/apps/app/components/cycles/form.tsx index 58f57ba14..d32fd047d 100644 --- a/apps/app/components/cycles/form.tsx +++ b/apps/app/components/cycles/form.tsx @@ -1,11 +1,16 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +// toast +import useToast from "hooks/use-toast"; // react-hook-form import { Controller, useForm } from "react-hook-form"; // ui import { Button, CustomDatePicker, CustomSelect, Input, TextArea } from "components/ui"; // types import { ICycle } from "types"; +// services +import cyclesService from "services/cycles.service"; type Props = { handleFormSubmit: (values: Partial) => Promise; @@ -23,11 +28,19 @@ const defaultValues: Partial = { }; export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, status, data }) => { + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const { setToastAlert } = useToast(); + + const [isDateValid, setIsDateValid] = useState(true); + const { register, formState: { errors, isSubmitting }, handleSubmit, control, + watch, reset, } = useForm({ defaultValues, @@ -41,6 +54,31 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat }); }; + const dateChecker = async (payload: any) => { + await cyclesService + .cycleDateCheck(workspaceSlug as string, projectId as string, payload) + .then((res) => { + if (res.status) { + setIsDateValid(true); + } else { + setIsDateValid(false); + setToastAlert({ + type: "error", + title: "Error!", + message: + "You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates", + }); + } + }) + .catch((err) => { + console.log(err); + }); + }; + + const checkEmptyDate = + (watch("start_date") === "" && watch("end_date") === "") || + (watch("start_date") === null && watch("end_date") === null); + useEffect(() => { reset({ ...defaultValues, @@ -84,30 +122,7 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat register={register} /> -
-
Status
- ( - {field.value ?? "Select Status"}} - input - > - {[ - { label: "Draft", value: "draft" }, - { label: "Started", value: "started" }, - { label: "Completed", value: "completed" }, - ].map((item) => ( - - {item.label} - - ))} - - )} - /> -
+
Start Date
@@ -115,12 +130,19 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat ( { + onChange(val); + watch("end_date") + ? dateChecker({ + start_date: val, + end_date: watch("end_date"), + }) + : ""; + }} error={errors.start_date ? true : false} /> )} @@ -136,12 +158,19 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat ( { + onChange(val); + watch("start_date") + ? dateChecker({ + start_date: watch("start_date"), + end_date: val, + }) + : ""; + }} error={errors.end_date ? true : false} /> )} @@ -158,7 +187,18 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat -
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx index 771387877..e4c1a5e94 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx @@ -34,6 +34,8 @@ import { PROJECT_ISSUES_LIST, PROJECT_DETAILS, CYCLE_DETAILS, + CYCLE_COMPLETE_LIST, + CYCLE_CURRENT_AND_UPCOMING_LIST, } from "constants/fetch-keys"; const SingleCycle: React.FC = (props) => { @@ -78,6 +80,40 @@ const SingleCycle: React.FC = (props) => { : null ); + const { data: currentAndUpcomingCycles } = useSWR( + workspaceSlug && projectId ? CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => + cycleServices.getCurrentAndUpcomingCycles(workspaceSlug as string, projectId as string) + : null + ); + + const { data: completedCycles } = useSWR( + workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => cycleServices.getCompletedCycles(workspaceSlug as string, projectId as string) + : null + ); + + const checkForInProgress = currentAndUpcomingCycles?.current_cycle?.filter( + (c) => c.id === cycleDetails?.id + ); + const checkForUpcoming = currentAndUpcomingCycles?.upcoming_cycle?.filter( + (c) => c.id === cycleDetails?.id + ); + const checkForInCompleted = completedCycles?.completed_cycles?.filter( + (c) => c.id === cycleDetails?.id + ); + + const cycleStatus = + checkForInCompleted && checkForInCompleted.length > 0 + ? "completed" + : checkForInProgress && checkForInProgress.length > 0 + ? "current" + : checkForUpcoming && checkForUpcoming.length > 0 + ? "upcoming" + : "draft"; + const { data: cycleIssues } = useSWR( workspaceSlug && projectId && cycleId ? CYCLE_ISSUES(cycleId as string) : null, workspaceSlug && projectId && cycleId @@ -218,6 +254,7 @@ const SingleCycle: React.FC = (props) => {
)} ( () => import("components/cycles").then((a) => a.CompletedCyclesList), @@ -54,6 +58,13 @@ const ProjectCycles: NextPage = () => { : null ); + const { data: draftCycles } = useSWR( + workspaceSlug && projectId ? CYCLE_DRAFT_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => cycleService.getDraftCycles(workspaceSlug as string, projectId as string) + : null + ); + const { data: currentAndUpcomingCycles } = useSWR( workspaceSlug && projectId ? CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string) : null, workspaceSlug && projectId @@ -112,22 +123,29 @@ const ProjectCycles: NextPage = () => { - `rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` + `w-1/3 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"}` + `w-1/3 rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` } > Completed + + ` w-1/3 rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` + } + > + Draft + @@ -145,6 +163,14 @@ const ProjectCycles: NextPage = () => { /> + + +
From 02e4e58f19f8386fb19d0150de8239dd345beefb Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Fri, 3 Mar 2023 11:32:00 +0530 Subject: [PATCH 09/10] feat: date range status function added --- apps/app/components/cycles/sidebar.tsx | 2 +- apps/app/helpers/date-time.helper.ts | 14 ++++++++ .../projects/[projectId]/cycles/[cycleId].tsx | 36 ++----------------- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/apps/app/components/cycles/sidebar.tsx b/apps/app/components/cycles/sidebar.tsx index ce61afea6..46be61e8b 100644 --- a/apps/app/components/cycles/sidebar.tsx +++ b/apps/app/components/cycles/sidebar.tsx @@ -128,7 +128,7 @@ export const CycleDetailsSidebar: React.FC = ({ {cycleStatus === "current" ? "In Progress" - : cycleStatus === "completed" + : cycleStatus === "past" ? "Completed" : cycleStatus === "upcoming" ? "Upcoming" diff --git a/apps/app/helpers/date-time.helper.ts b/apps/app/helpers/date-time.helper.ts index 4d179ef0d..b7a815cae 100644 --- a/apps/app/helpers/date-time.helper.ts +++ b/apps/app/helpers/date-time.helper.ts @@ -88,3 +88,17 @@ export const timeAgo = (time: any) => { } return time; }; + +export const getDateRangeStatus = (startDate: string , endDate: string ) => { + const now = new Date(); + const start = new Date(startDate); + const end = new Date(endDate); + + if (end < now) { + return "past"; + } else if (start <= now && end >= now) { + return "current"; + } else { + return "upcoming"; + } +} \ No newline at end of file diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx index e4c1a5e94..efafd3ce3 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx @@ -25,6 +25,7 @@ import { CustomMenu, EmptySpace, EmptySpaceItem, Spinner } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; // helpers import { truncateText } from "helpers/string.helper"; +import { getDateRangeStatus } from "helpers/date-time.helper"; // types import { CycleIssueResponse, UserAuth } from "types"; // fetch-keys @@ -34,8 +35,6 @@ import { PROJECT_ISSUES_LIST, PROJECT_DETAILS, CYCLE_DETAILS, - CYCLE_COMPLETE_LIST, - CYCLE_CURRENT_AND_UPCOMING_LIST, } from "constants/fetch-keys"; const SingleCycle: React.FC = (props) => { @@ -80,38 +79,9 @@ const SingleCycle: React.FC = (props) => { : null ); - const { data: currentAndUpcomingCycles } = useSWR( - workspaceSlug && projectId ? CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => - cycleServices.getCurrentAndUpcomingCycles(workspaceSlug as string, projectId as string) - : null - ); - - const { data: completedCycles } = useSWR( - workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => cycleServices.getCompletedCycles(workspaceSlug as string, projectId as string) - : null - ); - - const checkForInProgress = currentAndUpcomingCycles?.current_cycle?.filter( - (c) => c.id === cycleDetails?.id - ); - const checkForUpcoming = currentAndUpcomingCycles?.upcoming_cycle?.filter( - (c) => c.id === cycleDetails?.id - ); - const checkForInCompleted = completedCycles?.completed_cycles?.filter( - (c) => c.id === cycleDetails?.id - ); - const cycleStatus = - checkForInCompleted && checkForInCompleted.length > 0 - ? "completed" - : checkForInProgress && checkForInProgress.length > 0 - ? "current" - : checkForUpcoming && checkForUpcoming.length > 0 - ? "upcoming" + cycleDetails?.start_date && cycleDetails?.end_date + ? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date) : "draft"; const { data: cycleIssues } = useSWR( From f965734f3bf10c05478cb36039dbafcfa4609256 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Fri, 3 Mar 2023 13:49:19 +0530 Subject: [PATCH 10/10] fix: mutation fix and date range helper fn added --- apps/app/components/cycles/modal.tsx | 44 ++++++++++++++++++++++++-- apps/app/components/cycles/sidebar.tsx | 2 +- apps/app/helpers/date-time.helper.ts | 2 +- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/apps/app/components/cycles/modal.tsx b/apps/app/components/cycles/modal.tsx index fc829024b..a83d8ca93 100644 --- a/apps/app/components/cycles/modal.tsx +++ b/apps/app/components/cycles/modal.tsx @@ -12,10 +12,16 @@ import cycleService from "services/cycles.service"; import useToast from "hooks/use-toast"; // components import { CycleForm } from "components/cycles"; +// helper +import { getDateRangeStatus } from "helpers/date-time.helper"; // types import type { ICycle } from "types"; // fetch keys -import { CYCLE_LIST } from "constants/fetch-keys"; +import { + CYCLE_COMPLETE_LIST, + CYCLE_CURRENT_AND_UPCOMING_LIST, + CYCLE_DRAFT_LIST, +} from "constants/fetch-keys"; type CycleModalProps = { isOpen: boolean; @@ -37,7 +43,23 @@ export const CreateUpdateCycleModal: React.FC = ({ await cycleService .createCycle(workspaceSlug as string, projectId as string, payload) .then((res) => { - mutate(CYCLE_LIST(projectId as string)); + switch ( + res?.start_date && res.end_date + ? getDateRangeStatus(res?.start_date, res.end_date) + : "draft" + ) { + case "completed": + mutate(CYCLE_COMPLETE_LIST(projectId as string)); + break; + case "current": + mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); + break; + case "upcoming": + mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); + break; + default: + mutate(CYCLE_DRAFT_LIST(projectId as string)); + } handleClose(); setToastAlert({ @@ -59,7 +81,23 @@ export const CreateUpdateCycleModal: React.FC = ({ await cycleService .updateCycle(workspaceSlug as string, projectId as string, cycleId, payload) .then((res) => { - mutate(CYCLE_LIST(projectId as string)); + switch ( + res?.start_date && res.end_date + ? getDateRangeStatus(res?.start_date, res.end_date) + : "draft" + ) { + case "completed": + mutate(CYCLE_COMPLETE_LIST(projectId as string)); + break; + case "current": + mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); + break; + case "upcoming": + mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); + break; + default: + mutate(CYCLE_DRAFT_LIST(projectId as string)); + } handleClose(); setToastAlert({ diff --git a/apps/app/components/cycles/sidebar.tsx b/apps/app/components/cycles/sidebar.tsx index 46be61e8b..ce61afea6 100644 --- a/apps/app/components/cycles/sidebar.tsx +++ b/apps/app/components/cycles/sidebar.tsx @@ -128,7 +128,7 @@ export const CycleDetailsSidebar: React.FC = ({ {cycleStatus === "current" ? "In Progress" - : cycleStatus === "past" + : cycleStatus === "completed" ? "Completed" : cycleStatus === "upcoming" ? "Upcoming" diff --git a/apps/app/helpers/date-time.helper.ts b/apps/app/helpers/date-time.helper.ts index b7a815cae..1fdd58f58 100644 --- a/apps/app/helpers/date-time.helper.ts +++ b/apps/app/helpers/date-time.helper.ts @@ -95,7 +95,7 @@ export const getDateRangeStatus = (startDate: string , endDate: string ) => { const end = new Date(endDate); if (end < now) { - return "past"; + return "completed"; } else if (start <= now && end >= now) { return "current"; } else {