"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { CalendarClock } from "lucide-react"; import { useAuth } from "@/contexts/AuthContext"; import { Button } from "@/components/ui/button"; import { ButtonSpinner } from "@/components/ui/button-spinner"; import { StatusMessage } from "@/components/ui/status-message"; import { StandaloneCard, StandaloneCardHeader, } from "@/components/layout/standalone-card"; import { getApiErrorMessage } from "@/lib/api/error"; import { DEFAULT_POST_AUTH_REDIRECT } from "@/lib/auth-redirect"; import { formatPurgeDay, parsePurgeDate } from "@/lib/purge-date"; const RESTORE_FAILED = "Couldn't restore your account. Please try again."; /** * The offer at the end of a sign-in into an account that is waiting to be purged, * and the click that undoes the deletion. * * Nothing has happened yet by the time this renders: the identity was verified, the * API answered `deletion_pending`, and no session was issued and no row was touched. * Signing in must not quietly cancel a deletion somebody deliberately asked for, so * the restore is its own decision and this screen is where it is made. */ export function RestoreAccountCard() { const { restore, restoreAccount } = useAuth(); const router = useRouter(); const [isRestoring, setIsRestoring] = useState(false); const [error, setError] = useState(null); if (!restore) { return null; } const purgeOn = parsePurgeDate(restore.purgeAfter); const handleRestore = async () => { setIsRestoring(true); setError(null); try { await restoreAccount(restore.restoreToken); router.push(DEFAULT_POST_AUTH_REDIRECT); // Deliberately still `isRestoring`: the navigation is under way, and the // token has been spent either way, so re-arming the button would only offer // a second restore that cannot succeed. } catch (err) { // Worth showing verbatim. The API distinguishes a spent or expired token // from an account whose grace period ran out while this was on screen, and // the second is the one thing the diver most needs to be told plainly. setError(getApiErrorMessage(err, RESTORE_FAILED)); setIsRestoring(false); } }; return (

{restore.email}{" "} was deleted, and nothing has been erased yet.{" "} {purgeOn ? ( <> Your dives, dive drafts, dive sites, trips, courses, certifications, gear, contacts, people and tags are erased for good on{" "} {formatPurgeDay(purgeOn)} . ) : ( "Your dives, dive drafts, dive sites, trips, courses, certifications, gear, contacts, people and tags are erased for good once this instance's grace period runs out." )}

Restoring brings all of it back and signs you in. Leave it, and the date above decides.

{error} {/* The one-shot warning, and it is not boilerplate: the six-digit code claims its request row before the account is even resolved, so a code spent on reaching this screen is spent. Whichever way in was used, this offer lives in memory and a reload has nothing to come back to. */}

This offer belongs to the sign-in you just completed - if you leave or reload this page, sign in again to get back here.

No thanks, leave my account deleted

); }