From 48b3d8476c00df16f60be7d2d8f7a2c5b78c8a7b Mon Sep 17 00:00:00 2001 From: Tomas Salgado <91388965+tomas-salgado@users.noreply.github.com> Date: Sat, 30 Nov 2024 16:30:51 -0600 Subject: [PATCH] move where we have the delete button, and update the modal for confirming deletion of resource to match the UI pattern we use for deleting offers --- .../routes/_profile.resources.$id_.delete.tsx | 94 ++++++++++---- .../routes/_profile.resources.$id_.edit.tsx | 15 ++- .../app/shared/components/resource.tsx | 118 ++++-------------- 3 files changed, 107 insertions(+), 120 deletions(-) diff --git a/apps/member-profile/app/routes/_profile.resources.$id_.delete.tsx b/apps/member-profile/app/routes/_profile.resources.$id_.delete.tsx index 0855e9fa3..4c9418879 100644 --- a/apps/member-profile/app/routes/_profile.resources.$id_.delete.tsx +++ b/apps/member-profile/app/routes/_profile.resources.$id_.delete.tsx @@ -1,13 +1,51 @@ -import { type ActionFunctionArgs, redirect } from '@remix-run/node'; -import { Form, useNavigate, useSearchParams } from '@remix-run/react'; -import { useState } from 'react'; +import { + type ActionFunctionArgs, + json, + type LoaderFunctionArgs, + redirect, +} from '@remix-run/node'; +import { + Form as RemixForm, + useActionData, + useLoaderData, + useSearchParams, +} from '@remix-run/react'; -import { Button, Modal } from '@oyster/ui'; +import { db } from '@oyster/db'; +import { Button, Form, getErrors, Modal } from '@oyster/ui'; import { deleteResource } from '@/modules/resource/use-cases/delete-resource'; import { Route } from '@/shared/constants'; +import { + commitSession, + ensureUserAuthenticated, + toast, + user, +} from '@/shared/session.server'; + +export async function loader({ params, request }: LoaderFunctionArgs) { + const session = await ensureUserAuthenticated(request); + + const resource = await db + .selectFrom('resources') + .select(['title']) + .where('id', '=', params.id as string) + .where('postedBy', '=', user(session)) + .executeTakeFirst(); + + if (!resource) { + throw new Response(null, { + status: 404, + statusText: 'The resource you are looking for does not exist.', + }); + } + + return json(resource); +} export async function action({ params, request }: ActionFunctionArgs) { + const session = await ensureUserAuthenticated(request); + const { id } = params; if (!id) throw new Error('Resource ID is required'); @@ -17,15 +55,24 @@ export async function action({ params, request }: ActionFunctionArgs) { const url = new URL(request.url); const searchParams = url.searchParams.toString(); + toast(session, { + message: 'Resource deleted successfully.', + }); + return redirect( - `${Route['/resources']}${searchParams ? `?${searchParams}` : ''}` + `${Route['/resources']}${searchParams ? `?${searchParams}` : ''}`, + { + headers: { + 'Set-Cookie': await commitSession(session), + }, + } ); } -export default function DeleteResource() { - const navigate = useNavigate(); +export default function DeleteResourceModal() { + const { title } = useLoaderData(); const [searchParams] = useSearchParams(); - const [isDeleting, setIsDeleting] = useState(false); + const { error } = getErrors(useActionData()); const getReturnPath = () => { const currentParams = searchParams.toString(); @@ -36,26 +83,21 @@ export default function DeleteResource() { return ( - - Are you sure you want to delete this resource? - + Delete Resource + - This action cannot be undone. -
setIsDeleting(true)}> - - - + + + Are you sure you want to delete "{title}"? This action cannot be undone. + + + + {error} + + + Delete - +
); } diff --git a/apps/member-profile/app/routes/_profile.resources.$id_.edit.tsx b/apps/member-profile/app/routes/_profile.resources.$id_.edit.tsx index 695edc49e..4dec50511 100644 --- a/apps/member-profile/app/routes/_profile.resources.$id_.edit.tsx +++ b/apps/member-profile/app/routes/_profile.resources.$id_.edit.tsx @@ -9,6 +9,8 @@ import { redirect, } from '@remix-run/node'; import { + generatePath, + Link, Form as RemixForm, useActionData, useLoaderData, @@ -21,6 +23,7 @@ import { Button, Divider, Form, + getButtonCn, getErrors, Modal, validateForm, @@ -50,6 +53,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) { 'resources.link', 'resources.title', 'resources.type', + 'resources.id', ], where: { id: params.id as string }, }); @@ -170,8 +174,17 @@ export default function EditResourceModal() { {error} - + Save + + + Delete + diff --git a/apps/member-profile/app/shared/components/resource.tsx b/apps/member-profile/app/shared/components/resource.tsx index 15ccbf590..72af6ce62 100644 --- a/apps/member-profile/app/shared/components/resource.tsx +++ b/apps/member-profile/app/shared/components/resource.tsx @@ -4,24 +4,15 @@ import { useFetcher, useSearchParams, } from '@remix-run/react'; -import { type PropsWithChildren, useState } from 'react'; -import { - ArrowUp, - BarChart2, - Edit, - MoreHorizontal, - Share, - Trash2, -} from 'react-feather'; +import { type PropsWithChildren } from 'react'; +import { ArrowUp, BarChart2, Edit, Share } from 'react-feather'; import { match } from 'ts-pattern'; import { ResourceType } from '@oyster/core/resources'; import { cx, - Dropdown, getIconButtonCn, getTextCn, - IconButton, Pill, ProfilePicture, Text, @@ -293,7 +284,6 @@ function ResourceActionGroup({ shareableUri, }: Pick) { const [searchParams] = useSearchParams(); - const [open, setOpen] = useState(false); const toast = useToast(); const { trackFromClient } = useMixpanelTracker(); @@ -302,10 +292,6 @@ function ResourceActionGroup({ backgroundColorOnHover: 'gray-200', }); - function onClick() { - setOpen(true); - } - return (
    {!!editable && ( @@ -328,84 +314,30 @@ function ResourceActionGroup({ )} - {editable ? ( -
  • - setOpen(false)}> - - - - - - More Options - - - {open && ( - - - - - - - - Delete - - - - - )} - -
  • - ) : ( -
  • - - - - - - Copy Resource Link - - -
  • - )} +
  • + + + + + + Copy Resource Link + + +
); }