diff --git a/apps/web/app/(app)/settings/DeleteSection.tsx b/apps/web/app/(app)/settings/DeleteSection.tsx index 3ba7bff20..0698647dc 100644 --- a/apps/web/app/(app)/settings/DeleteSection.tsx +++ b/apps/web/app/(app)/settings/DeleteSection.tsx @@ -7,10 +7,13 @@ import { deleteAccountAction, resetAnalyticsAction, } from "@/utils/actions/user"; -import { handleActionResult } from "@/utils/server-action"; import { logOut } from "@/utils/user"; +import { isActionError } from "@/utils/error"; +import { useStatLoader } from "@/providers/StatLoaderProvider"; export function DeleteSection() { + const { onCancelLoadBatch } = useStatLoader(); + return ( { + onCancelLoadBatch(); + const result = await deleteAccountAction(); + await logOut("/"); + if (isActionError(result)) throw new Error(result.error); + }, + { + loading: "Deleting account...", + success: "Account deleted!", + error: (err) => `Error deleting account: ${err.message}`, + }, + ); }} > Yes, delete my account diff --git a/apps/web/app/(app)/settings/WebhookSection.tsx b/apps/web/app/(app)/settings/WebhookSection.tsx index 9b443b3c3..0fea22d40 100644 --- a/apps/web/app/(app)/settings/WebhookSection.tsx +++ b/apps/web/app/(app)/settings/WebhookSection.tsx @@ -8,7 +8,7 @@ import { RegenerateSecretButton } from "@/app/(app)/settings/WebhookGenerate"; export async function WebhookSection() { const session = await auth(); const userId = session?.user.id; - if (!userId) throw new Error("Not authenticated"); + if (!userId) return null; const user = await prisma.user.findUnique({ where: { id: userId }, diff --git a/apps/web/app/(landing)/login/page.tsx b/apps/web/app/(landing)/login/page.tsx index af865fa91..b63ccb495 100644 --- a/apps/web/app/(landing)/login/page.tsx +++ b/apps/web/app/(landing)/login/page.tsx @@ -20,7 +20,6 @@ export default async function AuthenticationPage({ searchParams?: Record; }) { const session = await auth(); - console.log("🚀 ~ session:", session?.user); if (session?.user.email && !searchParams?.error) { if (searchParams?.next) { redirect(searchParams?.next); diff --git a/apps/web/app/(landing)/welcome-upgrade/page.tsx b/apps/web/app/(landing)/welcome-upgrade/page.tsx index c9c7bc1a2..4ba9cedd4 100644 --- a/apps/web/app/(landing)/welcome-upgrade/page.tsx +++ b/apps/web/app/(landing)/welcome-upgrade/page.tsx @@ -4,6 +4,7 @@ import { Pricing } from "@/app/(app)/premium/Pricing"; import { Footer } from "@/app/(landing)/home/Footer"; import { Loading } from "@/components/Loading"; import { WelcomeUpgradeNav } from "@/app/(landing)/welcome-upgrade/WelcomeUpgradeNav"; +import { userCount } from "@/utils/config"; export default function WelcomeUpgradePage() { return ( @@ -18,7 +19,7 @@ export default function WelcomeUpgradePage() { Spend 50% less time on email

- Join 9,000+ users that use Inbox Zero + Join {userCount} users that use Inbox Zero
to be more productive!

diff --git a/apps/web/app/api/auth/[...nextauth]/auth.ts b/apps/web/app/api/auth/[...nextauth]/auth.ts index fc9655592..cc4aaf69a 100644 --- a/apps/web/app/api/auth/[...nextauth]/auth.ts +++ b/apps/web/app/api/auth/[...nextauth]/auth.ts @@ -9,6 +9,7 @@ const defaultAuthOptions = getAuthOptions(); export const { handlers: { GET, POST }, auth, + signOut, } = NextAuth((req) => { if (req?.url) { const url = new URL(req?.url); diff --git a/apps/web/providers/StatLoaderProvider.tsx b/apps/web/providers/StatLoaderProvider.tsx index 8751913fe..09c2d1d09 100644 --- a/apps/web/providers/StatLoaderProvider.tsx +++ b/apps/web/providers/StatLoaderProvider.tsx @@ -23,12 +23,14 @@ type Context = { loadBefore: boolean; showToast: boolean; }) => Promise; + onCancelLoadBatch: () => void; }; const StatLoaderContext = createContext({ isLoading: false, onLoad: async () => {}, onLoadBatch: async () => {}, + onCancelLoadBatch: () => {}, }); export const useStatLoader = () => useContext(StatLoaderContext); @@ -64,6 +66,7 @@ const statLoader = new StatLoader(); export function StatLoaderProvider(props: { children: React.ReactNode }) { const [isLoading, setIsLoading] = useState(false); + const [stopLoading, setStopLoading] = useState(false); const onLoad = useCallback( async (options: { loadBefore: boolean; showToast: boolean }) => { @@ -78,18 +81,26 @@ export function StatLoaderProvider(props: { children: React.ReactNode }) { async (options: { loadBefore: boolean; showToast: boolean }) => { const batchSize = 50; for (let i = 0; i < batchSize; i++) { + if (stopLoading) break; console.log("Loading batch", i); await onLoad({ ...options, showToast: options.showToast && i === batchSize - 1, }); } + setStopLoading(false); }, - [onLoad], + [onLoad, stopLoading], ); + const onCancelLoadBatch = useCallback(() => { + setStopLoading(true); + }, []); + return ( - + {props.children} ); diff --git a/apps/web/utils/actions/user.ts b/apps/web/utils/actions/user.ts index 73e1f26ae..5f2af278a 100644 --- a/apps/web/utils/actions/user.ts +++ b/apps/web/utils/actions/user.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { deleteContact as deleteLoopsContact } from "@inboxzero/loops"; import { deleteContact as deleteResendContact } from "@inboxzero/resend"; -import { auth } from "@/app/api/auth/[...nextauth]/auth"; +import { auth, signOut } from "@/app/api/auth/[...nextauth]/auth"; import prisma from "@/utils/prisma"; import { deleteInboxZeroLabels, deleteUserLabels } from "@/utils/redis/label"; import { deleteUserStats } from "@/utils/redis/stats"; @@ -66,10 +66,14 @@ export const deleteAccountAction = withActionInstrumentation( }), ]); } catch (error) { - console.error("Error while deleting account: ", error); + console.error("Error while deleting account:", error); captureException(error, undefined, session.user.email); } + try { + await signOut(); + } catch (error) {} + await prisma.user.delete({ where: { email: session.user.email } }); }, );