From 2ce7914b7ab3058ac580b363a2f7014e2e5eb18a Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 24 Jul 2023 11:32:59 +0530 Subject: [PATCH] style: new cycles list page design with empty states (#1633) --- .../cycles/active-cycle-details.tsx | 39 +++- apps/app/components/cycles/cycles-view.tsx | 64 +++++-- .../projects/[projectId]/cycles/index.tsx | 172 +++++++++--------- 3 files changed, 174 insertions(+), 101 deletions(-) diff --git a/apps/app/components/cycles/active-cycle-details.tsx b/apps/app/components/cycles/active-cycle-details.tsx index a876b9b11..eb0cdc7d8 100644 --- a/apps/app/components/cycles/active-cycle-details.tsx +++ b/apps/app/components/cycles/active-cycle-details.tsx @@ -110,8 +110,43 @@ export const ActiveCycleDetails: React.FC = () => { if (!cycle) return ( -
-

No active cycle is present.

+
+
+
+ + + + +
+

No active cycle

+ +
); diff --git a/apps/app/components/cycles/cycles-view.tsx b/apps/app/components/cycles/cycles-view.tsx index ad0a8e7d5..6f3fa336a 100644 --- a/apps/app/components/cycles/cycles-view.tsx +++ b/apps/app/components/cycles/cycles-view.tsx @@ -9,6 +9,7 @@ import cyclesService from "services/cycles.service"; // hooks import useToast from "hooks/use-toast"; import useUserAuth from "hooks/use-user-auth"; +import useLocalStorage from "hooks/use-local-storage"; // components import { CreateUpdateCycleModal, @@ -18,11 +19,7 @@ import { SingleCycleList, } from "components/cycles"; // ui -import { EmptyState, Loader } from "components/ui"; -// icons -import { PlusIcon } from "@heroicons/react/24/outline"; -// images -import emptyCycle from "public/empty-state/cycle.svg"; +import { Loader } from "components/ui"; // helpers import { getDateRangeStatus } from "helpers/date-time.helper"; // types @@ -48,6 +45,8 @@ export const CyclesView: React.FC = ({ cycles, viewType }) => { const [deleteCycleModal, setDeleteCycleModal] = useState(false); const [selectedCycleToDelete, setSelectedCycleToDelete] = useState(null); + const { storedValue: cycleTab } = useLocalStorage("cycleTab", "All"); + const router = useRouter(); const { workspaceSlug, projectId } = router.query; @@ -206,19 +205,48 @@ export const CyclesView: React.FC = ({ cycles, viewType }) => { ) ) : ( - } - onClick={() => { - const e = new KeyboardEvent("keydown", { - key: "q", - }); - document.dispatchEvent(e); - }} - /> +
+
+
+ + + + +
+

+ {cycleTab === "All" + ? "No cycles" + : `No ${cycleTab === "Drafts" ? "draft" : cycleTab?.toLowerCase()} cycles`} +

+ +
+
) ) : viewType === "list" ? ( diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index 6c33d97ce..3ef5c9eb4 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -2,15 +2,12 @@ import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; -import useSWR from "swr"; - // headless ui import { Tab } from "@headlessui/react"; // hooks import useLocalStorage from "hooks/use-local-storage"; import useUserAuth from "hooks/use-user-auth"; -// services -import projectService from "services/project.service"; +import useProjectDetails from "hooks/use-project-details"; // layouts import { ProjectAuthorizationWrapper } from "layouts/auth-layout"; // components @@ -23,18 +20,33 @@ import { UpcomingCyclesList, } from "components/cycles"; // ui -import { PrimaryButton } from "components/ui"; +import { EmptyState, Icon, PrimaryButton } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; // icons -import { ListBulletIcon, PlusIcon, Squares2X2Icon } from "@heroicons/react/24/outline"; +import { PlusIcon } from "@heroicons/react/24/outline"; +// images +import emptyCycle from "public/empty-state/cycle.svg"; // types import { SelectCycleType } from "types"; import type { NextPage } from "next"; -// fetch-keys -import { PROJECT_DETAILS } from "constants/fetch-keys"; const tabsList = ["All", "Active", "Upcoming", "Completed", "Drafts"]; +const cycleViews = [ + { + key: "list", + icon: "list", + }, + { + key: "board", + icon: "dataset", + }, + { + key: "gantt", + icon: "view_timeline", + }, +]; + const ProjectCycles: NextPage = () => { const [selectedCycle, setSelectedCycle] = useState(); const [createUpdateCycleModal, setCreateUpdateCycleModal] = useState(false); @@ -60,19 +72,14 @@ const ProjectCycles: NextPage = () => { }; const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug } = router.query; const { user } = useUserAuth(); - - const { data: activeProject } = useSWR( - workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null, - workspaceSlug && projectId - ? () => projectService.getProject(workspaceSlug as string, projectId as string) - : null - ); + const { projectDetails } = useProjectDetails(); useEffect(() => { if (createUpdateCycleModal) return; + const timer = setTimeout(() => { setSelectedCycle(undefined); clearTimeout(timer); @@ -84,7 +91,7 @@ const ProjectCycles: NextPage = () => { breadcrumbs={ - + } right={ @@ -106,46 +113,26 @@ const ProjectCycles: NextPage = () => { data={selectedCycle} user={user} /> -
-
-

Cycles

-
- - - -
+ {projectDetails?.total_cycles === 0 ? ( +
+ } + onClick={() => { + const e = new KeyboardEvent("keydown", { + key: "q", + }); + document.dispatchEvent(e); + }} + />
+ ) : ( { @@ -165,50 +152,73 @@ const ProjectCycles: NextPage = () => { } }} > - - {tabsList.map((tab, index) => { - if (cyclesView === "gantt_chart" && (tab === "Active" || tab === "Drafts")) - return null; +
+ + {tabsList.map((tab, index) => { + if (cyclesView === "gantt_chart" && (tab === "Active" || tab === "Drafts")) + return null; - return ( - - `rounded-3xl border px-6 py-1 outline-none ${ - selected - ? "border-custom-primary bg-custom-primary text-white font-medium" - : "border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-80" - }` - } - > - {tab} - - ); - })} - + return ( + + `border-b-2 p-4 text-sm font-medium outline-none ${ + selected + ? "border-custom-primary-100 text-custom-primary-100" + : "border-transparent" + }` + } + > + {tab} + + ); + })} + +
+ {cycleViews.map((view) => { + if (view.key === "gantt" && (cycleTab === "Active" || cycleTab === "Drafts")) + return null; + + return ( + + ); + })} +
+
- + {cyclesView !== "gantt_chart" && ( - + )} - + - + {cyclesView !== "gantt_chart" && ( - + )}
-
+ )} ); };