diff --git a/app/api/artist/remove/route.ts b/app/api/artist/remove/route.ts deleted file mode 100644 index 9edeaa21c..000000000 --- a/app/api/artist/remove/route.ts +++ /dev/null @@ -1,19 +0,0 @@ -import supabase from "@/lib/supabase/serverClient"; -import { NextRequest } from "next/server"; - -export async function GET(req: NextRequest) { - const artistId = req.nextUrl.searchParams.get("artistId"); - - try { - await supabase.from("accounts").delete().eq("id", artistId); - return Response.json({ success: true }, { status: 200 }); - } catch (error) { - console.error(error); - const message = error instanceof Error ? error.message : "failed"; - return Response.json({ message }, { status: 400 }); - } -} - -export const dynamic = "force-dynamic"; -export const fetchCache = "force-no-store"; -export const revalidate = 0; diff --git a/components/ArtistSetting/DeleteModal.tsx b/components/ArtistSetting/DeleteModal.tsx index 9b20d6c03..838c22e65 100644 --- a/components/ArtistSetting/DeleteModal.tsx +++ b/components/ArtistSetting/DeleteModal.tsx @@ -1,23 +1,22 @@ import { useArtistProvider } from "@/providers/ArtistProvider"; -import { ArtistRecord } from "@/types/Artist"; +import useDeleteArtist from "@/hooks/useDeleteArtist"; interface DeleteModalProps { toggleModal: () => void; } const DeleteModal = ({ toggleModal }: DeleteModalProps) => { - const { editableArtist, artists, setArtists, toggleSettingModal } = - useArtistProvider(); + const { editableArtist, toggleSettingModal } = useArtistProvider(); + const { deleteArtist } = useDeleteArtist(); const handleDelete = async () => { - const temp = artists.filter( - (artistEle: ArtistRecord) => - artistEle.account_id !== editableArtist?.account_id, - ); - setArtists([...temp]); + const artistId = editableArtist?.account_id; + if (!artistId) { + return; + } toggleModal(); toggleSettingModal(); - await fetch(`/api/artist/remove?artistId=${editableArtist?.account_id}`); + await deleteArtist(artistId); }; return ( diff --git a/components/Artists/DropDown.tsx b/components/Artists/DropDown.tsx index 547d74a07..57ba1df76 100644 --- a/components/Artists/DropDown.tsx +++ b/components/Artists/DropDown.tsx @@ -3,19 +3,16 @@ import { ArtistRecord } from "@/types/Artist"; import { Trash2 } from "lucide-react"; import { containerPatterns, textPatterns } from "@/lib/styles/patterns"; import { cn } from "@/lib/utils"; +import useDeleteArtist from "@/hooks/useDeleteArtist"; const DropDown = ({ artist }: { artist: ArtistRecord }) => { - const { setArtists, artists, setMenuVisibleArtistId, getArtists } = - useArtistProvider(); + const { setMenuVisibleArtistId } = useArtistProvider(); + const { deleteArtist } = useDeleteArtist(); const handleDelete = async () => { - const temp = artists.filter( - (artistEle: ArtistRecord) => artistEle.account_id !== artist.account_id, - ); - setArtists([...temp]); - setMenuVisibleArtistId(null); - await fetch(`/api/artist/remove?artistId=${artist.account_id}`); - getArtists(); + await deleteArtist(artist.account_id, { + onSuccess: () => setMenuVisibleArtistId(null), + }); }; return ( diff --git a/hooks/useDeleteArtist.ts b/hooks/useDeleteArtist.ts new file mode 100644 index 000000000..0aef78113 --- /dev/null +++ b/hooks/useDeleteArtist.ts @@ -0,0 +1,50 @@ +import { usePrivy } from "@privy-io/react-auth"; +import { toast } from "sonner"; +import { deleteArtist } from "@/lib/artists/deleteArtist"; +import { useArtistProvider } from "@/providers/ArtistProvider"; + +interface DeleteArtistOptions { + onSuccess?: () => void; +} + +interface UseDeleteArtistReturn { + deleteArtist: (artistId: string, options?: DeleteArtistOptions) => Promise; +} + +export default function useDeleteArtist(): UseDeleteArtistReturn { + const { getAccessToken } = usePrivy(); + const { artists, setArtists, getArtists } = useArtistProvider(); + + const deleteArtistHandler = async ( + artistId: string, + options?: DeleteArtistOptions, + ): Promise => { + const previousArtists = artists; + const nextArtists = artists.filter(artist => artist.account_id !== artistId); + setArtists(nextArtists); + + try { + const accessToken = await getAccessToken(); + if (!accessToken) { + throw new Error("Please sign in to delete an artist"); + } + + await deleteArtist(accessToken, artistId); + options?.onSuccess?.(); + } catch (error) { + setArtists(previousArtists); + toast.error(error instanceof Error ? error.message : "Failed to delete artist"); + return; + } + + try { + await getArtists(); + } catch { + toast.error("Artist deleted, but failed to refresh the artist list"); + } + }; + + return { + deleteArtist: deleteArtistHandler, + }; +} diff --git a/lib/artists/deleteArtist.ts b/lib/artists/deleteArtist.ts new file mode 100644 index 000000000..b1c920126 --- /dev/null +++ b/lib/artists/deleteArtist.ts @@ -0,0 +1,27 @@ +import { getClientApiBaseUrl } from "@/lib/api/getClientApiBaseUrl"; + +interface DeleteArtistResponse { + success?: boolean; + error?: string; +} + +/** + * Deletes an artist through the dedicated API. + * + * @param accessToken - Privy access token for Bearer auth + * @param artistId - Artist account ID to delete + */ +export async function deleteArtist(accessToken: string, artistId: string): Promise { + const response = await fetch(`${getClientApiBaseUrl()}/api/artists/${artistId}`, { + method: "DELETE", + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }); + + const data: DeleteArtistResponse = await response.json(); + + if (!response.ok || !data.success) { + throw new Error(data.error || "Failed to delete artist"); + } +}