From d2522c8d93c6b011c0cc9ba262ce9273ed261b72 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Thu, 10 Apr 2025 22:52:18 +0100 Subject: [PATCH] feat: account deletion --- src/app/api/auth/delete/route.ts | 20 ++++ .../profile-settings/delete-account.tsx | 91 +++++++++++++++++++ src/app/profile/settings/page.tsx | 11 ++- 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/app/api/auth/delete/route.ts create mode 100644 src/app/components/profile-settings/delete-account.tsx diff --git a/src/app/api/auth/delete/route.ts b/src/app/api/auth/delete/route.ts new file mode 100644 index 0000000..98608ff --- /dev/null +++ b/src/app/api/auth/delete/route.ts @@ -0,0 +1,20 @@ +import { NextResponse } from "next/server"; + +import { auth } from "@/lib/auth"; +import { prisma } from "@/lib/prisma"; + +export async function DELETE() { + const session = await auth(); + if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + + try { + await prisma.user.delete({ + where: { id: Number(session.user?.id!) }, + }); + } catch (error) { + console.error("Failed to delete user:", error); + return NextResponse.json({ error: "Failed to delete account" }, { status: 500 }); + } + + return NextResponse.json({ success: true }); +} diff --git a/src/app/components/profile-settings/delete-account.tsx b/src/app/components/profile-settings/delete-account.tsx new file mode 100644 index 0000000..54506ba --- /dev/null +++ b/src/app/components/profile-settings/delete-account.tsx @@ -0,0 +1,91 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { createPortal } from "react-dom"; +import { Icon } from "@iconify/react"; +import { redirect } from "next/navigation"; + +export default function DeleteAccount() { + const [isOpen, setIsOpen] = useState(false); + const [isVisible, setIsVisible] = useState(false); + + const [error, setError] = useState(undefined); + + const submit = async () => { + const response = await fetch("/api/auth/delete", { method: "DELETE" }); + if (!response.ok) { + const { error } = await response.json(); + setError(error); + return; + } + + redirect("/404"); + }; + + const close = () => { + setIsVisible(false); + setTimeout(() => { + setIsOpen(false); + }, 300); + }; + + useEffect(() => { + if (isOpen) { + // slight delay to trigger animation + setTimeout(() => setIsVisible(true), 10); + } + }, [isOpen]); + + return ( + <> + + + {isOpen && + createPortal( +
+
+ +
+
+

Delete Account

+ +
+ +

+ Are you sure? This is permanent and will remove all uploaded Miis. This action cannot be undone. +

+ + {error && Error: {error}} + +
+ + +
+
+
, + document.body + )} + + ); +} diff --git a/src/app/profile/settings/page.tsx b/src/app/profile/settings/page.tsx index ffc5ca3..b008fdc 100644 --- a/src/app/profile/settings/page.tsx +++ b/src/app/profile/settings/page.tsx @@ -1,10 +1,13 @@ import { redirect } from "next/navigation"; import Image from "next/image"; +import Link from "next/link"; + +import { Icon } from "@iconify/react"; import { auth } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; -import { Icon } from "@iconify/react"; -import Link from "next/link"; + +import DeleteAccount from "@/app/components/profile-settings/delete-account"; export default async function ProfileSettingsPage() { const session = await auth(); @@ -106,9 +109,7 @@ export default async function ProfileSettingsPage() {

This will permanently remove your account and all uploaded Miis. This action cannot be undone

- +