diff options
Diffstat (limited to 'web/app')
| -rw-r--r-- | web/app/api/v1/links/[linkId]/route.ts | 32 | ||||
| -rw-r--r-- | web/app/bookmarks/components/LinkCard.tsx | 36 | ||||
| -rw-r--r-- | web/app/layout.tsx | 6 |
3 files changed, 66 insertions, 8 deletions
diff --git a/web/app/api/v1/links/[linkId]/route.ts b/web/app/api/v1/links/[linkId]/route.ts new file mode 100644 index 00000000..39449d6d --- /dev/null +++ b/web/app/api/v1/links/[linkId]/route.ts @@ -0,0 +1,32 @@ +import { authOptions } from "@/lib/auth"; +import { unbookmarkLink } from "@/lib/services/links"; +import { Prisma } from "@remember/db"; + +import { getServerSession } from "next-auth"; +import { NextRequest } from "next/server"; + +export async function DELETE( + _request: NextRequest, + { params }: { params: { linkId: string } }, +) { + // TODO: We probably should be using an API key here instead of the session; + const session = await getServerSession(authOptions); + if (!session) { + return new Response(null, { status: 401 }); + } + + try { + await unbookmarkLink(params.linkId, session.user.id); + } catch (e: unknown) { + if ( + e instanceof Prisma.PrismaClientKnownRequestError && + e.code === "P2025" // RecordNotFound + ) { + return new Response(null, { status: 404 }); + } else { + throw e; + } + } + + return new Response(null, { status: 201 }); +} diff --git a/web/app/bookmarks/components/LinkCard.tsx b/web/app/bookmarks/components/LinkCard.tsx index 75973f7e..907acd19 100644 --- a/web/app/bookmarks/components/LinkCard.tsx +++ b/web/app/bookmarks/components/LinkCard.tsx @@ -13,12 +13,34 @@ import { ImageCardFooter, ImageCardTitle, } from "@/components/ui/imageCard"; +import { useToast } from "@/components/ui/use-toast"; +import APIClient from "@/lib/api"; import { ZBookmarkedLink } from "@/lib/types/api/links"; import { MoreHorizontal, Trash2 } from "lucide-react"; import Link from "next/link"; +import { useRouter } from "next/navigation"; -export function LinkOptions() { - // TODO: Implement deletion +export function LinkOptions({ linkId }: { linkId: string }) { + const { toast } = useToast(); + const router = useRouter(); + + const unbookmarkLink = async () => { + let [_, error] = await APIClient.unbookmarkLink(linkId); + + if (error) { + toast({ + variant: "destructive", + title: "Something went wrong", + description: "There was a problem with your request.", + }); + } else { + toast({ + description: "The link has been deleted!", + }); + } + + router.refresh(); + }; return ( <DropdownMenu> <DropdownMenuTrigger asChild> @@ -27,10 +49,10 @@ export function LinkOptions() { </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-fit"> - <DropdownMenuItem className="text-destructive"> - <Trash2 className="mr-2 h-4 w-4" /> - <span>Delete</span> - </DropdownMenuItem> + <DropdownMenuItem className="text-destructive" onClick={unbookmarkLink}> + <Trash2 className="mr-2 h-4 w-4" /> + <span>Delete</span> + </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> ); @@ -59,7 +81,7 @@ export default function LinkCard({ link }: { link: ZBookmarkedLink }) { {parsedUrl.host} </Link> </div> - <LinkOptions /> + <LinkOptions linkId={link.id} /> </div> </ImageCardFooter> </ImageCard> diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 30d918df..a6543b1c 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; import React from "react"; +import { Toaster } from "@/components/ui/toaster"; const inter = Inter({ subsets: ["latin"] }); @@ -17,7 +18,10 @@ export default function RootLayout({ }>) { return ( <html lang="en"> - <body className={inter.className}>{children}</body> + <body className={inter.className}> + {children} + <Toaster /> + </body> </html> ); } |
