Skip to content

Commit

Permalink
feat - added the delete account UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Chigala committed Mar 19, 2024
1 parent 4ea2cd6 commit 9d64b7a
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 0 deletions.
48 changes: 48 additions & 0 deletions app/(dashboard)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import DeleteAccountCard from "@/components/delete-account-card";
import { DashboardHeader } from "@/components/header";
import { DashboardShell } from "@/components/shell";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";

export const metadata = {
title: "Settings",
description: "Your account settings",
};

const emailSettingItems = [
{
id: 1,
label: "Get Email for moments of celebration",
description: "We'll send you an email when you level up or earn a badge.",
},
{
id: 2,
label: "Get Email for new projects",
description: "We'll send you an email when a new project is added that matches your interests.",
},
];

export default async function SettingsPage() {
const handleDeleteAccount = () => {
console.log("Deleting account");
};
return (
<DashboardShell>
<DashboardHeader heading="Settings" text="Your account settings" />
<div className="h-fit w-full space-y-3 rounded-lg bg-zinc-50 p-5 ">
<p className="text-md font-bold">Email Settings </p>
{emailSettingItems.map((item) => (
<div key={item.id} className="flex items-center space-x-2">
<Checkbox id={item.label} />
<label
htmlFor={item.label}
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
{item.label}
</label>
</div>
))}
</div>
<DeleteAccountCard />
</DashboardShell>
);
}
24 changes: 24 additions & 0 deletions components/delete-account-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";

import { useDeleteAccountModal } from "@/components/delete-modal";
import { Button } from "@/components/ui/button";
import { Delete } from "lucide-react";

export default function DeleteAccountCard() {
const { setShowDeleteAccountModal, DeleteAccountModal } = useDeleteAccountModal();
return (
<div>
<DeleteAccountModal />
<div className="h-fit w-full space-y-3 rounded-lg bg-zinc-50 p-5 ">
<p className="text-md font-bold">Account </p>
<Button
onClick={() => {
setShowDeleteAccountModal(true);
}}
variant="destructive">
Delete Account
</Button>
</div>
</div>
);
}
93 changes: 93 additions & 0 deletions components/delete-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Button } from "@/components/ui/button";
import { Modal } from "@/components/ui/modal";
import { useToast } from "@/components/ui/use-toast";
import { useRouter } from "next/navigation";
import { Dispatch, SetStateAction, useCallback, useMemo, useState } from "react";

function DeleteAccountModal({
showDeleteAccountModal,
setShowDeleteAccountModal,
}: {
showDeleteAccountModal: boolean;
setShowDeleteAccountModal: Dispatch<SetStateAction<boolean>>;
}) {
const router = useRouter();
const [deleting, setDeleting] = useState(false);
const { toast } = useToast();

async function deleteAccount() {
setDeleting(true);
console.log("deleting account");
//TODO: add function that would be responsible for deleting the account
// await fetch(`/api/user`, {
// method: "DELETE",
// headers: {
// "Content-Type": "application/json",
// },
// }).then(async (res) => {
// if (res.status === 200) {
// update();
// // delay to allow for the route change to complete
// await new Promise((resolve) =>
// setTimeout(() => {
// router.push("/register");
// resolve(null);
// }, 200)
// );
// } else {
// setDeleting(false);
// const error = await res.text();
// throw error;
// }
// });
}

return (
<Modal showModal={showDeleteAccountModal} setShowModal={setShowDeleteAccountModal}>
<div className="flex flex-col items-center justify-center space-y-3 border-gray-200 px-4 py-4 pt-8 sm:px-16">
<h3 className="text-lg font-medium">Are you absolutely sure?</h3>
<p className="text-center text-sm text-gray-500">
This action cannot be undone. This will permanently delete your account and remove your data from
our servers.
</p>
</div>

<form
onSubmit={async (e) => {
e.preventDefault();
toast({
title: `deleting`,
description: "Next steps to be built",
});
await deleteAccount();
}}
className="flex flex-col space-y-6 bg-gray-50 px-4 py-8 text-left sm:px-16">
<Button variant="destructive" loading={deleting}>
{" "}
Delete
</Button>
</form>
</Modal>
);
}

export function useDeleteAccountModal() {
const [showDeleteAccountModal, setShowDeleteAccountModal] = useState(false);

const DeleteAccountModalCallback = useCallback(() => {
return (
<DeleteAccountModal
showDeleteAccountModal={showDeleteAccountModal}
setShowDeleteAccountModal={setShowDeleteAccountModal}
/>
);
}, [showDeleteAccountModal, setShowDeleteAccountModal]);

return useMemo(
() => ({
setShowDeleteAccountModal,
DeleteAccountModal: DeleteAccountModalCallback,
}),
[setShowDeleteAccountModal, DeleteAccountModalCallback]
);
}
73 changes: 73 additions & 0 deletions components/ui/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use client";

import { cn } from "@/lib/utils";
import * as Dialog from "@radix-ui/react-dialog";
import { useRouter } from "next/navigation";
import { Dispatch, SetStateAction } from "react";


//inspired by dub.co

export function Modal({
children,
className,
showModal,
setShowModal,
onClose,
desktopOnly,
preventDefaultClose,
}: {
children: React.ReactNode;
className?: string;
showModal?: boolean;
setShowModal?: Dispatch<SetStateAction<boolean>>;
onClose?: () => void;
desktopOnly?: boolean;
preventDefaultClose?: boolean;
}) {
const router = useRouter();

const closeModal = ({ dragged }: { dragged?: boolean } = {}) => {
if (preventDefaultClose && !dragged) {
return;
}
// fire onClose event if provided
onClose && onClose();

// if setShowModal is defined, use it to close modal
if (setShowModal) {
setShowModal(false);
// else, this is intercepting route @modal
} else {
router.back();
}
};


return (
<Dialog.Root
open={setShowModal ? showModal : true}
onOpenChange={(open) => {
if (!open) {
closeModal();
}
}}>
<Dialog.Portal>
<Dialog.Overlay
// for detecting when there's an active opened modal
id="modal-backdrop"
className="animate-fade-in fixed inset-0 z-40 bg-gray-100 bg-opacity-50 backdrop-blur-md"
/>
<Dialog.Content
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
className={cn(
"animate-scale-in fixed inset-0 z-40 m-auto max-h-fit w-full max-w-md overflow-hidden border border-gray-200 bg-white p-0 shadow-xl sm:rounded-2xl",
className
)}>
{children}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}

0 comments on commit 9d64b7a

Please sign in to comment.