"use client";
import { useCallback, useState } from "react";
import { TwoFactorSetup } from "@/components/ui/two-factor-setup";
const settings = {
account: "olivia@example.com",
issuer: "Acme Console",
/** Any six digits pass, except this one, which the demo refuses. */
wrongCode: "000000",
};
/** The well-known example key of the TOTP documentation ("Hello!" in base32), not a real one. */
const EXAMPLE_KEY = ["JBSW", "Y3DP", "EHPK", "3PXP"].join("").repeat(2);
const BACKUP_CODES = [
"7Q2KD-4MZPA",
"R8VNE-2WQXT",
"J5HCF-9LBUY",
"P3TXG-6KDRM",
"W9AHL-5ZQNE",
"C4MRT-8YJVK",
];
const CHECK_MS = 700;
const wait = (ms: number) =>
new Promise<void>((resolve) => {
setTimeout(resolve, ms);
});
/** Scan, enter any six digits (but `wrongCode`), save the backup codes, and start over. */
export default function Demo(props: Partial<typeof settings>) {
const { account, issuer, wrongCode } = { ...settings, ...props };
const [round, setRound] = useState(0);
const [isDone, setDone] = useState(false);
const verify = useCallback(
async (code: string) => {
await wait(CHECK_MS);
if (code === wrongCode) {
throw new Error(
"That code did not match. Wait for the next one and try again."
);
}
return BACKUP_CODES;
},
[wrongCode]
);
const done = useCallback(() => setDone(true), []);
const again = useCallback(() => {
setDone(false);
setRound((count) => count + 1);
}, []);
return (
<div className="flex min-h-[600px] w-full items-center justify-center bg-background p-6">
<div className="w-full max-w-xl">
{isDone ? (
<div className="flex flex-col items-start gap-3 rounded-2xl border border-border bg-card p-5 text-sm">
<p role="status">Two-factor sign-in is on for {account}.</p>
<button
className="h-11 rounded-lg border border-border px-4 font-medium hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
onClick={again}
type="button"
>
Start over
</button>
</div>
) : (
<TwoFactorSetup
account={account}
issuer={issuer}
key={round}
onDone={done}
onVerify={verify}
secret={EXAMPLE_KEY}
/>
)}
</div>
</div>
);
}