diff --git a/apps/app/components/cycles/completed-cycles-list.tsx b/apps/app/components/cycles/completed-cycles-list.tsx index 899a17bb2..09020e9d8 100644 --- a/apps/app/components/cycles/completed-cycles-list.tsx +++ b/apps/app/components/cycles/completed-cycles-list.tsx @@ -1,15 +1,18 @@ -// react import { useState } from "react"; -// next + import { useRouter } from "next/router"; + import useSWR from "swr"; +// services +import cyclesService from "services/cycles.service"; // components import { DeleteCycleModal, SingleCycleCard } from "components/cycles"; +// icons +import { CompletedCycleIcon } from "components/icons"; // types import { ICycle, SelectCycleType } from "types"; -import { CompletedCycleIcon } from "components/icons"; -import cyclesService from "services/cycles.service"; +// fetch-keys import { CYCLE_COMPLETE_LIST } from "constants/fetch-keys"; export interface CompletedCyclesListProps { @@ -58,14 +61,16 @@ export const CompletedCyclesList: React.FC = ({ data={selectedCycleForDelete} /> {completedCycles?.completed_cycles.length > 0 ? ( - completedCycles.completed_cycles.map((cycle) => ( - handleDeleteCycle(cycle)} - handleEditCycle={() => handleEditCycle(cycle)} - /> - )) +
+ {completedCycles.completed_cycles.map((cycle) => ( + handleDeleteCycle(cycle)} + handleEditCycle={() => handleEditCycle(cycle)} + /> + ))} +
) : (
diff --git a/apps/app/components/cycles/cycles-list.tsx b/apps/app/components/cycles/cycles-list.tsx index e55f0e6f1..dc4693637 100644 --- a/apps/app/components/cycles/cycles-list.tsx +++ b/apps/app/components/cycles/cycles-list.tsx @@ -1,10 +1,11 @@ -// react import { useState } from "react"; + // components import { DeleteCycleModal, SingleCycleCard } from "components/cycles"; +// icons +import { CompletedCycleIcon, CurrentCycleIcon, UpcomingCycleIcon } from "components/icons"; // types import { ICycle, SelectCycleType } from "types"; -import { CompletedCycleIcon, CurrentCycleIcon, UpcomingCycleIcon } from "components/icons"; type TCycleStatsViewProps = { cycles: ICycle[]; @@ -44,14 +45,16 @@ export const CyclesList: React.FC = ({ data={selectedCycleForDelete} /> {cycles.length > 0 ? ( - cycles.map((cycle) => ( - handleDeleteCycle(cycle)} - handleEditCycle={() => handleEditCycle(cycle)} - /> - )) +
+ {cycles.map((cycle) => ( + handleDeleteCycle(cycle)} + handleEditCycle={() => handleEditCycle(cycle)} + /> + ))} +
) : (
{type === "upcoming" ? ( diff --git a/apps/app/components/cycles/single-cycle-card.tsx b/apps/app/components/cycles/single-cycle-card.tsx index 1fa565ceb..79d6b7c77 100644 --- a/apps/app/components/cycles/single-cycle-card.tsx +++ b/apps/app/components/cycles/single-cycle-card.tsx @@ -4,22 +4,22 @@ import Link from "next/link"; import Image from "next/image"; import { useRouter } from "next/router"; -// swr import useSWR from "swr"; + // services import cyclesService from "services/cycles.service"; // hooks import useToast from "hooks/use-toast"; // ui -import { Button, CustomMenu } from "components/ui"; +import { CustomMenu, LinearProgressIndicator } from "components/ui"; +import { Disclosure, Transition } from "@headlessui/react"; // icons import { CalendarDaysIcon } from "@heroicons/react/20/solid"; -import { UserIcon } from "@heroicons/react/24/outline"; -import { CyclesIcon } from "components/icons"; +import { ChevronDownIcon, PencilIcon, StarIcon } from "@heroicons/react/24/outline"; // helpers -import { renderShortNumericDateFormat } from "helpers/date-time.helper"; +import { renderShortDateWithYearFormat } from "helpers/date-time.helper"; import { groupBy } from "helpers/array.helper"; -import { copyTextToClipboard } from "helpers/string.helper"; +import { capitalizeFirstLetter, copyTextToClipboard } from "helpers/string.helper"; // types import { CycleIssueResponse, ICycle } from "types"; // fetch-keys @@ -34,11 +34,11 @@ type TSingleStatProps = { const stateGroupColours: { [key: string]: string; } = { - backlog: "#3f76ff", - unstarted: "#ff9e9e", - started: "#d687ff", - cancelled: "#ff5353", - completed: "#096e8d", + backlog: "#DEE2E6", + unstarted: "#26B5CE", + started: "#F7AE59", + cancelled: "#D687FF", + completed: "#09A953", }; export const SingleCycleCard: React.FC = (props) => { @@ -82,100 +82,138 @@ export const SingleCycleCard: React.FC = (props) => { }); }; + const progressIndicatorData = Object.keys(groupedIssues).map((group, index) => ({ + id: index, + name: capitalizeFirstLetter(group), + value: + cycleIssues && cycleIssues.length > 0 + ? (groupedIssues[group].length / cycleIssues.length) * 100 + : 0, + color: stateGroupColours[group], + })); + return ( - <> -
-
-
-
- - -

- {cycle.name} -

-
- - - Edit cycle +
+
+ + +
+
+

{cycle.name}

+ {/* + + */} +
+ +
+
+ + Start : + {renderShortDateWithYearFormat(startDate)} +
+
+ + End : + {renderShortDateWithYearFormat(endDate)} +
+
+
+
+ + +
+
+
+ {cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? ( + {cycle.owned_by.first_name} + ) : ( + + )} + {cycle.owned_by.first_name} +
+
+ + + Delete cycle Copy cycle link
-
-
- - Cycle dates -
-
- {renderShortNumericDateFormat(startDate)} - {renderShortNumericDateFormat(endDate)} -
-
- - Created by -
-
- {cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? ( - {cycle.owned_by.first_name} - ) : ( - - {cycle.owned_by.first_name.charAt(0)} - - )} - {cycle.owned_by.first_name} -
-
-
-
+ + + {({ open }) => ( +
- - Open Cycle - -
-
-
-

PROGRESS

-
- {Object.keys(groupedIssues).map((group) => ( -
-
- -
{group}
-
-
- - {groupedIssues[group].length}{" "} - - -{" "} - {cycleIssues && cycleIssues.length > 0 - ? `${Math.round( - (groupedIssues[group].length / cycleIssues.length) * 100 - )}%` - : "0%"} - - -
+
+ Progress + + +
- ))} -
-
+ + +
+
+
+ {Object.keys(groupedIssues).map((group) => ( +
+
+ +
{group}
+
+
+ + {groupedIssues[group].length}{" "} + + -{" "} + {cycleIssues && cycleIssues.length > 0 + ? `${Math.round( + (groupedIssues[group].length / cycleIssues.length) * 100 + )}%` + : "0%"} + + +
+
+ ))} +
+
+
+
+
+
+ )} +
- +
); }; diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts index 607caecd5..7a9108850 100644 --- a/apps/app/components/ui/index.ts +++ b/apps/app/components/ui/index.ts @@ -16,3 +16,4 @@ export * from "./progress-bar"; export * from "./spinner"; export * from "./tooltip"; export * from "./labels-list"; +export * from "./linear-progress-indicator"; diff --git a/apps/app/components/ui/linear-progress-indicator.tsx b/apps/app/components/ui/linear-progress-indicator.tsx new file mode 100644 index 000000000..8145c7f4d --- /dev/null +++ b/apps/app/components/ui/linear-progress-indicator.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { Tooltip } from "./tooltip"; + +type Props = { + data: any; +}; + +export const LinearProgressIndicator: React.FC = ({ data }) => { + const total = data.reduce((acc: any, cur: any) => acc + cur.value, 0); + let progress = 0; + + const bars = data.map((item: any) => { + const width = `${(item.value / total) * 100}%`; + const style = { + width, + backgroundColor: item.color, + }; + progress += item.value; + + return ( + +
+ + ); + }); + + return ( +
+ {total === 0 ? " - 0%" :
{bars}
} +
+ ); +}; diff --git a/apps/app/helpers/date-time.helper.ts b/apps/app/helpers/date-time.helper.ts index 1fdd58f58..3ec660826 100644 --- a/apps/app/helpers/date-time.helper.ts +++ b/apps/app/helpers/date-time.helper.ts @@ -101,4 +101,12 @@ export const getDateRangeStatus = (startDate: string , endDate: string ) => { } else { return "upcoming"; } +} + +export const renderShortDateWithYearFormat = (date: Date) => { + const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const day = date.getDate(); + const month = months[date.getMonth()]; + const year = date.getFullYear(); + return isNaN(date.getTime()) ? "N/A" : ` ${month} ${day}, ${year}`; } \ No newline at end of file diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index f690e0a16..595a07bfa 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -2,10 +2,11 @@ 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"; @@ -110,68 +111,85 @@ const ProjectCycles: NextPage = () => { data={selectedCycle} />
-

Current Cycle

-
- +
+

Current Cycle

+
+ +
-
- - - - `w-1/3 rounded-lg px-6 py-2 ${selected ? "bg-gray-300" : "hover:bg-gray-200"}` - } +
+

Others

+
+ + - Upcoming - - - `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 - - - - - - - - - - - - - - + + ` rounded-3xl border px-6 py-3 ${ + selected + ? "bg-theme text-white" + : "border-gray-400 bg-white text-gray-900 hover:bg-gray-200" + }` + } + > + Upcoming + + + ` rounded-3xl border px-6 py-3 ${ + selected + ? "bg-theme text-white" + : "border-gray-400 bg-white text-gray-900 hover:bg-gray-200" + }` + } + > + Completed + + + ` rounded-3xl border px-6 py-3 ${ + selected + ? "bg-theme text-white" + : "border-gray-400 bg-white text-gray-900 hover:bg-gray-200" + }` + } + > + Drafts + + + + + + + + + + + + + + +