From 9c559ccf9a4843a879edf90dfea56ffeb3e87479 Mon Sep 17 00:00:00 2001 From: Aslam Date: Wed, 4 Sep 2024 06:05:32 +0700 Subject: [PATCH] feat: delete page (#130) --- .../routes/page/detail/PageDetailRoute.tsx | 72 +++++++++++++++++-- web/components/routes/page/detail/header.tsx | 11 ++- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/web/components/routes/page/detail/PageDetailRoute.tsx b/web/components/routes/page/detail/PageDetailRoute.tsx index d3db2476..77883508 100644 --- a/web/components/routes/page/detail/PageDetailRoute.tsx +++ b/web/components/routes/page/detail/PageDetailRoute.tsx @@ -15,13 +15,66 @@ import { generateUniqueSlug } from "@/lib/utils" import { FocusClasses } from "@tiptap/extension-focus" import { DetailPageHeader } from "./header" import { useMedia } from "react-use" -import TopicSelector from "@/components/custom/topic-selector" +import { TopicSelector } from "@/components/custom/topic-selector" +import { Button } from "@/components/ui/button" +import { LaIcon } from "@/components/custom/la-icon" +import { useConfirm } from "@omit/react-confirm-dialog" +import { toast } from "sonner" +import { useRouter } from "next/navigation" const TITLE_PLACEHOLDER = "Untitled" export function PageDetailRoute({ pageId }: { pageId: string }) { + const { me } = useAccount({ root: { personalLinks: [] } }) const isMobile = useMedia("(max-width: 770px)") const page = useCoState(PersonalPage, pageId as ID) + const router = useRouter() + + const confirm = useConfirm() + + const handleDelete = async () => { + const result = await confirm({ + title: "Delete page", + description: "Are you sure you want to delete this page?", + confirmText: "Delete", + cancelText: "Cancel", + cancelButton: { + variant: "outline" + }, + confirmButton: { + variant: "destructive" + } + }) + + if (result) { + if (!me?.root.personalPages) return + + try { + const index = me.root.personalPages.findIndex(item => item?.id === pageId) + if (index === -1) { + toast.error("Page not found.") + return + } + + toast.success("Page deleted.", { + position: "bottom-right", + description: ( + + {page?.title} has been deleted. + + ) + }) + + me.root.personalPages.splice(index, 1) + + // push without history + router.replace("/") + } catch (error) { + console.error("Delete operation fail", { error }) + return + } + } + } if (!page) return null @@ -29,25 +82,31 @@ export function PageDetailRoute({ pageId }: { pageId: string }) {
- +
{!isMobile && (
-
+
Page actions
-
+
{ page.topic = topic page.updatedAt = new Date() }} + variant="ghost" + className="-ml-1.5" /> +
@@ -84,12 +143,11 @@ export const DetailPageForm = ({ page }: { page: PersonalPage }) => { const personalPages = me?.root?.personalPages?.toJSON() || [] const slug = generateUniqueSlug(personalPages, page.slug || "") - const trimmedTitle = editor.getText().trim() - page.title = trimmedTitle + page.title = editor.getText() page.slug = slug page.updatedAt = new Date() - editor.commands.setContent(trimmedTitle) + editor.commands.setContent(editor.getText()) } const handleTitleKeyDown = useCallback((view: EditorView, event: KeyboardEvent) => { diff --git a/web/components/routes/page/detail/header.tsx b/web/components/routes/page/detail/header.tsx index 215e5a7e..c2e11b2f 100644 --- a/web/components/routes/page/detail/header.tsx +++ b/web/components/routes/page/detail/header.tsx @@ -5,8 +5,10 @@ import { ContentHeader, SidebarToggleButton } from "@/components/custom/content- import { PersonalPage } from "@/lib/schema/personal-page" import { useMedia } from "react-use" import { TopicSelector } from "@/components/custom/topic-selector" +import { Button } from "@/components/ui/button" +import { LaIcon } from "@/components/custom/la-icon" -export const DetailPageHeader = ({ page }: { page: PersonalPage }) => { +export const DetailPageHeader = ({ page, handleDelete }: { page: PersonalPage; handleDelete: () => void }) => { const isMobile = useMedia("(max-width: 770px)") return ( @@ -18,7 +20,7 @@ export const DetailPageHeader = ({ page }: { page: PersonalPage }) => {
-
+
{ @@ -26,7 +28,12 @@ export const DetailPageHeader = ({ page }: { page: PersonalPage }) => { page.updatedAt = new Date() }} align="start" + variant="outline" /> +
)