Add settings page with sign-out and delete account sections.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Developing-Gamer 2026-05-27 12:47:54 -07:00
parent 6df13f5356
commit f245ea55da
3 changed files with 142 additions and 0 deletions

View File

@ -0,0 +1,93 @@
'use client';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import { useState } from "react";
import { useStackApp, useUser } from "@stackframe/stack";
import { Section } from "../section";
export function DeleteAccountSection(props?: { mockMode?: boolean }) {
const user = useUser({ or: props?.mockMode ? 'return-null' : 'redirect' });
const app = useStackApp();
const project = app.useProject();
const [deleting, setDeleting] = useState(false);
const showDeleteSection = props?.mockMode || project.config.clientUserDeletionEnabled;
if (!showDeleteSection) {
return null;
}
const handleDeleteAccount = async () => {
if (props?.mockMode) {
alert("Mock mode: Account deletion clicked");
setDeleting(false);
return;
}
if (user) {
await user.delete();
await app.redirectToHome();
}
};
return (
<Section
title="Delete Account"
description="Permanently remove your account and all associated data"
>
<div className="w-full md:w-[350px]">
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="danger-zone" className="border-b-0">
<AccordionTrigger className="text-red-500 hover:text-red-600 font-semibold py-2">
Danger zone
</AccordionTrigger>
<AccordionContent className="pt-2">
{!deleting ? (
<div className="flex flex-col gap-2">
<p className="text-xs text-muted-foreground leading-normal mb-2">
Once you delete your account, there is no going back. Please be certain.
</p>
<Button
variant="destructive"
onClick={() => setDeleting(true)}
className="rounded-xl w-full"
>
Delete account
</Button>
</div>
) : (
<div className="flex flex-col gap-3">
<p className="text-xs font-semibold text-red-500 leading-relaxed">
Are you sure you want to delete your account? This action is IRREVERSIBLE and will delete ALL associated data.
</p>
<div className="flex gap-2">
<Button
variant="destructive"
onClick={handleDeleteAccount}
className="rounded-xl flex-1 text-xs"
>
Yes, delete account
</Button>
<Button
variant="outline"
onClick={() => setDeleting(false)}
className="border-black/[0.08] dark:border-white/[0.08] hover:bg-zinc-50 dark:hover:bg-zinc-900 rounded-xl flex-1 text-xs"
>
Cancel
</Button>
</div>
</div>
)}
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</Section>
);
}

View File

@ -0,0 +1,15 @@
import { PageLayout } from "../page-layout";
import { DeleteAccountSection } from "./delete-account-section";
import { SignOutSection } from "./sign-out-section";
export function SettingsPage(props?: {
mockMode?: boolean,
}) {
return (
<PageLayout>
<DeleteAccountSection mockMode={props?.mockMode} />
<SignOutSection mockMode={props?.mockMode} />
</PageLayout>
);
}

View File

@ -0,0 +1,34 @@
'use client';
import { Button } from "@/components/ui/button";
import { useUser } from "@stackframe/stack";
import { Section } from "../section";
export function SignOutSection(props?: { mockMode?: boolean }) {
const user = useUser({ or: props?.mockMode ? "return-null" : "throw" });
const handleSignOut = async () => {
if (props?.mockMode) {
alert("Mock mode: Sign out clicked");
return;
}
if (user) {
await user.signOut();
}
};
return (
<Section
title="Sign out"
description="End your current session"
>
<Button
variant='outline'
onClick={handleSignOut}
className="border-black/[0.08] dark:border-white/[0.08] hover:bg-zinc-50 dark:hover:bg-zinc-900 rounded-xl px-4 py-2 w-full md:w-auto transition-colors duration-150"
>
Sign out
</Button>
</Section>
);
}