import { useEffect, useState } from 'react'; import Typography from 'antd/es/typography'; import Switch from 'antd/es/switch'; import Button from 'antd/es/button'; import Modal from 'antd/es/modal'; import message from 'antd/es/message'; import Space from 'antd/es/space'; import Divider from 'antd/es/divider'; import { useNavigate } from 'react-router-dom'; import { updateConsent, exportMyData, deleteMyAccount, resendVerificationEmail } from './customerApi'; import { setFavoriteAlerts } from './favoritesApi'; import { useCustomerAuth } from './CustomerAuthContext'; import AccountDetails from './AccountDetails'; const { Text } = Typography; type Props = Readonly<{ // Supplied by the route, which decides where closing lands: back to the page // the customer came from, or to the storefront when they arrived directly. onClose: () => void; }>; export default function Account({ onClose }: Props) { const { customer, loading, refresh, logout } = useCustomerAuth(); const navigate = useNavigate(); const [resending, setResending] = useState(false); useEffect(() => { if (!loading && !customer) navigate('/login'); }, [loading, customer, navigate]); if (!customer) return null; async function handleResendVerification() { setResending(true); try { await resendVerificationEmail(); message.success('Sent. Check your inbox, and your spam folder.'); } catch (err) { // Shown as it arrives: the rate limit's message says the mail probably // did send and where to look, which a generic failure would throw away. message.error((err as Error).message); } finally { setResending(false); } } async function handleFavoriteAlertsToggle(checked: boolean) { try { await setFavoriteAlerts(checked); } catch (err) { message.error((err as Error).message); return; } refresh(); message.success(checked ? 'We will email you when a favorite sells' : 'Turned off'); } async function handleConsentToggle(checked: boolean) { await updateConsent(checked); message.success(checked ? 'Subscribed to emails' : 'Unsubscribed from emails'); refresh(); } async function handleLogout() { try { await logout(); } catch (err) { message.error(`Couldn't log out — ${(err as Error).message}`); return; } // replace, so Back doesn't return to the account page — which would only // bounce to /login now that the session is gone. navigate('/', { replace: true }); } function handleDelete() { Modal.confirm({ title: 'Delete your account?', content: 'This permanently removes your account and personal data. Your past orders are kept for accounting purposes but disconnected from your identity. This cannot be undone.', okText: 'Delete my account', okButtonProps: { danger: true }, onOk: async () => { await deleteMyAccount(); // The storefront is rendered behind this modal, so without clearing the // session it goes on showing "My Account" and hiding Sign up for an // account that no longer exists — visibly stale, not merely stale in // state. replace, so Back cannot return to /account and bounce to // /login. refresh(); message.success('Account deleted'); navigate('/', { replace: true }); } }); } return (
{customer.email} {/* The button only exists while there is something to verify. Offering it on a verified account would be a control whose only outcome is a refusal. */} {!customer.email_verified && (
Email not verified — check your inbox for a verification link.
)} Receive emails about new items {/* A separate consent from marketing above, and shown separately so a customer can hold one without the other. */}
Email me when an item I favorited is sold
{/* Order history is a page of its own now. The link stays here because this is where a customer looks for it. */}
); }