From 05ced21d7d673e71cf384e1976ee6d2c78ea9be9 Mon Sep 17 00:00:00 2001 From: Will Date: Sun, 8 Dec 2024 20:15:51 -0500 Subject: [PATCH] add delete from watching section button (#26) --- src/actions/index.ts | 15 +++ src/components/Media/DeleteWatchingButton.tsx | 34 +++++++ src/components/Media/MediaCard.astro | 95 +++++++++++-------- src/utils/watching.ts | 24 ++++- 4 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 src/components/Media/DeleteWatchingButton.tsx diff --git a/src/actions/index.ts b/src/actions/index.ts index 0c4417f..8e40f68 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -1,4 +1,5 @@ import { getTrending, multiSearch } from '@/utils/tmdb' +import { deleteItemFromWatching } from '@/utils/watching' import { defineAction } from 'astro:actions' import { z } from 'astro:schema' @@ -27,4 +28,18 @@ export const server = { } }, }), + deleteItemFromWatching: defineAction({ + input: z.object({ id: z.number().or(z.string()) }), + handler: async ({ id }, context) => { + try { + await deleteItemFromWatching({ + headers: context.request.headers, + id, + }) + return true + } catch (e) { + return false + } + }, + }), } diff --git a/src/components/Media/DeleteWatchingButton.tsx b/src/components/Media/DeleteWatchingButton.tsx new file mode 100644 index 0000000..2dac7b5 --- /dev/null +++ b/src/components/Media/DeleteWatchingButton.tsx @@ -0,0 +1,34 @@ +import { useCallback } from 'react' +import { actions } from 'astro:actions' +import { Button } from '../ui/button' +import { XIcon } from 'lucide-react' + +export function DeleteWatchingButton({ + id, + mediaTitle, +}: { + id: string | number + mediaTitle: string +}) { + const handleClick = useCallback(async () => { + const element = document.querySelector( + `[data-watching-id="${id}"]` + ) + if (element) { + element.remove() + } + + await actions.deleteItemFromWatching({ id }) + }, [id]) + + return ( + + ) +} diff --git a/src/components/Media/MediaCard.astro b/src/components/Media/MediaCard.astro index d5211a9..6864483 100644 --- a/src/components/Media/MediaCard.astro +++ b/src/components/Media/MediaCard.astro @@ -3,6 +3,7 @@ import { Image } from 'astro:assets' import { formatDate, getImagePath } from '@/utils' import { getTvOrMovieUrl } from '@/utils/url' import { Progress } from '@/components/ui/progress' +import { DeleteWatchingButton } from './DeleteWatchingButton' export interface Props { media: 'tv' | 'movie' @@ -38,54 +39,66 @@ const percentageWatched = isWatching : 0 --- - -
- { - image && ( - {title} - ) - } -
-
-

- {mediaTitle} -

+
+ { + image && ( + {title} + ) + } +
-

Rating: {rating.toFixed(1)}

- -

{formatDate(releaseDate)}

- -

{language}

+

+ {mediaTitle} +

+
+

Rating: {rating.toFixed(1)}

+ +

{formatDate(releaseDate)}

+ +

{language}

+
-
+ { + percentageWatched > 0 && ( +
+ +
+ ) + } +
{ - percentageWatched > 0 && ( -
- + isWatching && ( +
+
) } - +
diff --git a/src/utils/watching.ts b/src/utils/watching.ts index 3061148..33c2b24 100644 --- a/src/utils/watching.ts +++ b/src/utils/watching.ts @@ -1,4 +1,4 @@ -import { db, desc, eq, Watching } from 'astro:db' +import { db, desc, and, eq, Watching } from 'astro:db' import { auth } from './auth/server' import type { MovieWithMediaType, TVWithMediaType } from 'tmdb-ts' import type { Session, User } from 'better-auth' @@ -92,3 +92,25 @@ export async function linkWatching({ await Promise.allSettled([...insertPromises, ...deletePromises]) } + +export async function deleteItemFromWatching({ + headers, + id, +}: { + headers: Headers + id: string | number +}) { + const session = await auth.api.getSession({ + headers, + }) + + if (!session) { + throw new Error('Not authenticated') + } + + await db + .delete(Watching) + .where(and(eq(Watching.userId, session.user.id), eq(Watching.mediaId, +id))) + + console.log('Deleted watching') +}