From b7b8d3914ac460679fd93f0a14f385de847439bf Mon Sep 17 00:00:00 2001 From: kunalv17 <116634168+kunalv17@users.noreply.github.com> Date: Tue, 28 Mar 2023 16:48:46 +0530 Subject: [PATCH] style: views list page, chore: views favotire (#562) --- .../components/modules/single-module-card.tsx | 61 ++++---- apps/app/components/views/index.ts | 1 + .../app/components/views/single-view-item.tsx | 132 ++++++++++++++++++ .../projects/[projectId]/views/index.tsx | 38 ++--- apps/app/services/modules.service.ts | 2 +- apps/app/services/views.service.ts | 32 +++++ apps/app/types/views.d.ts | 1 + 7 files changed, 201 insertions(+), 66 deletions(-) create mode 100644 apps/app/components/views/single-view-item.tsx diff --git a/apps/app/components/modules/single-module-card.tsx b/apps/app/components/modules/single-module-card.tsx index 1e0df412a..82e59cd41 100644 --- a/apps/app/components/modules/single-module-card.tsx +++ b/apps/app/components/modules/single-module-card.tsx @@ -55,29 +55,22 @@ export const SingleModuleCard: React.FC = ({ module, handleEditModule }) }; const handleAddToFavorites = () => { - if (!workspaceSlug && !projectId && !module) return; + if (!workspaceSlug || !projectId || !module) return; + + mutate( + MODULE_LIST(projectId as string), + (prevData) => + (prevData ?? []).map((m) => ({ + ...m, + is_favorite: m.id === module.id ? true : m.is_favorite, + })), + false + ); modulesService .addModuleToFavorites(workspaceSlug as string, projectId as string, { module: module.id, }) - .then(() => { - mutate( - MODULE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((m) => ({ - ...m, - is_favorite: m.id === module.id ? true : m.is_favorite, - })), - false - ); - - setToastAlert({ - type: "success", - title: "Success!", - message: "Successfully added the module to favorites.", - }); - }) .catch(() => { setToastAlert({ type: "error", @@ -88,26 +81,20 @@ export const SingleModuleCard: React.FC = ({ module, handleEditModule }) }; const handleRemoveFromFavorites = () => { - if (!workspaceSlug || !module) return; + if (!workspaceSlug || !projectId || !module) return; + + mutate( + MODULE_LIST(projectId as string), + (prevData) => + (prevData ?? []).map((m) => ({ + ...m, + is_favorite: m.id === module.id ? false : m.is_favorite, + })), + false + ); modulesService .removeModuleFromFavorites(workspaceSlug as string, projectId as string, module.id) - .then(() => { - mutate( - MODULE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((m) => ({ - ...m, - is_favorite: m.id === module.id ? false : m.is_favorite, - })), - false - ); - setToastAlert({ - type: "success", - title: "Success!", - message: "Successfully removed the module from favorites.", - }); - }) .catch(() => { setToastAlert({ type: "error", @@ -161,11 +148,11 @@ export const SingleModuleCard: React.FC = ({ module, handleEditModule }) {module?.status?.replace("-", " ")} {module.is_favorite ? ( - ) : ( - )} diff --git a/apps/app/components/views/index.ts b/apps/app/components/views/index.ts index cad0d63d8..7a6307e56 100644 --- a/apps/app/components/views/index.ts +++ b/apps/app/components/views/index.ts @@ -2,3 +2,4 @@ export * from "./delete-view-modal"; export * from "./form"; export * from "./modal"; export * from "./select-filters"; +export * from "./single-view-item" diff --git a/apps/app/components/views/single-view-item.tsx b/apps/app/components/views/single-view-item.tsx new file mode 100644 index 000000000..8b47d65c7 --- /dev/null +++ b/apps/app/components/views/single-view-item.tsx @@ -0,0 +1,132 @@ +import React, { useState } from "react"; + +import Link from "next/link"; +import { useRouter } from "next/router"; +import { IView } from "types"; + +// icons +import { TrashIcon, StarIcon } from "@heroicons/react/24/outline"; +import { StackedLayersIcon } from "components/icons"; + +//components +import { CustomMenu } from "components/ui"; + +import viewsService from "services/views.service"; + +import { mutate } from "swr"; + +import { VIEWS_LIST } from "constants/fetch-keys"; + +import useToast from "hooks/use-toast"; + +type Props = { + view: IView, + setSelectedView: React.Dispatch>, +}; + + +export const SingleViewItem: React.FC = ({ + view, + setSelectedView, +}) => { + + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const { setToastAlert } = useToast(); + + const handleAddToFavorites = () => { + if (!workspaceSlug || !projectId || !view) return; + + mutate( + VIEWS_LIST(projectId as string), + (prevData) => + (prevData ?? []).map((v) => ({ + ...v, + is_favorite: v.id === view.id ? true : v.is_favorite, + })), + false + ); + + viewsService + .addViewToFavorites(workspaceSlug as string, projectId as string, { + view: view.id, + }) + .catch(() => { + setToastAlert({ + type: "error", + title: "Error!", + message: "Couldn't add the view to favorites. Please try again.", + }); + }); + }; + + const handleRemoveFromFavorites = () => { + if (!workspaceSlug || !view) return; + + mutate( + VIEWS_LIST(projectId as string), + (prevData) => + (prevData ?? []).map((v) => ({ + ...v, + is_favorite: v.id === view.id ? false : v.is_favorite, + })), + false + ); + + viewsService + .removeViewFromFavorites(workspaceSlug as string, projectId as string, view.id) + .catch(() => { + setToastAlert({ + type: "error", + title: "Error!", + message: "Couldn't remove the view from favorites. Please try again.", + }); + }); + }; + + return ( +
+
+
+
+ + + {view.name} + +
+
+ { + view.is_favorite ? ( + + ) : ( + + ) + } + + { + setSelectedView(view); + }} + > + + + Delete + + + +
+
+ {view?.description &&

+ {view.description} +

} +
+
+ ) +} diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx index f89dcf857..848073251 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import Link from "next/link"; import { useRouter } from "next/router"; import useSWR from "swr"; @@ -16,19 +15,18 @@ import projectService from "services/project.service"; import AppLayout from "layouts/app-layout"; // ui import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; -// icons -import { TrashIcon } from "@heroicons/react/24/outline"; + // image import emptyView from "public/empty-state/empty-view.svg"; // fetching keys import { PROJECT_DETAILS, VIEWS_LIST } from "constants/fetch-keys"; // components -import { CustomMenu, PrimaryButton, Loader, EmptyState } from "components/ui"; -import { DeleteViewModal, CreateUpdateViewModal } from "components/views"; +import { PrimaryButton, Loader, EmptyState } from "components/ui"; +import { DeleteViewModal, CreateUpdateViewModal, SingleViewItem } from "components/views"; + // types import { IView, UserAuth } from "types"; import type { NextPage, GetServerSidePropsContext } from "next"; -import { StackedLayersIcon } from "components/icons"; const ProjectViews: NextPage = (props) => { const [isCreateViewModalOpen, setIsCreateViewModalOpen] = useState(false); @@ -52,6 +50,8 @@ const ProjectViews: NextPage = (props) => { : null ); + console.log(views) + return ( = (props) => {

Views

{views.map((view) => ( -
-
- - - {view.name} - -
- - { - setSelectedView(view); - }} - > - - - Delete - - - -
+ view={view} + setSelectedView={setSelectedView} + /> ))}
diff --git a/apps/app/services/modules.service.ts b/apps/app/services/modules.service.ts index e1cde9cc9..29a1f02be 100644 --- a/apps/app/services/modules.service.ts +++ b/apps/app/services/modules.service.ts @@ -1,7 +1,7 @@ // services import APIService from "services/api.service"; // types -import type { IIssueViewOptions, IModule, ModuleIssueResponse, IIssue } from "types"; +import type { IIssueViewOptions, IModule, IIssue } from "types"; const { NEXT_PUBLIC_API_BASE_URL } = process.env; diff --git a/apps/app/services/views.service.ts b/apps/app/services/views.service.ts index a3bdf550c..80699d994 100644 --- a/apps/app/services/views.service.ts +++ b/apps/app/services/views.service.ts @@ -80,6 +80,38 @@ class ViewServices extends APIService { throw error?.response?.data; }); } + + async addViewToFavorites( + workspaceSlug: string, + projectId: string, + data: { + view: string; + } + ): Promise { + return this.post( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-views/`, + data + ) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + + async removeViewFromFavorites( + workspaceSlug: string, + projectId: string, + viewId: string + ): Promise { + return this.delete( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-views/${viewId}/` + ) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + } export default new ViewServices(); diff --git a/apps/app/types/views.d.ts b/apps/app/types/views.d.ts index f5cef0126..f599d2f6d 100644 --- a/apps/app/types/views.d.ts +++ b/apps/app/types/views.d.ts @@ -3,6 +3,7 @@ export interface IView { access: string; created_at: Date; updated_at: Date; + is_favorite: boolean; created_by: string; updated_by: string; name: string;