41 lines · 1.5 KB
import { useCopy } from "~/hooks/use-copy";
import { useViewer } from "~/hooks/use-viewer";
import { buttonClass } from "~/ui/Button";
import { Callout } from "~/ui/Callout";

function downloadText(filename: string, text: string): void {
  const url = URL.createObjectURL(new Blob([text], { type: "text/plain;charset=utf-8" }));
  const link = document.createElement("a");
  link.href = url;
  link.download = filename;
  link.click();
  URL.revokeObjectURL(url);
}

export function RecoveryCodes({ codes }: { codes: string[] }) {
  const viewer = useViewer();
  const { copied, copy } = useCopy();
  const text = `${codes.join("\n")}\n`;
  const filename = `gitfor-${viewer?.name ?? "account"}-backup-codes.txt`;
  return (
    <Callout as="output" tone="success" className="space-y-2 p-3">
      <p className="text-xs">
        Save these recovery codes somewhere safe. Each works once, and they won't be shown again.
      </p>
      <ul className="grid grid-cols-2 gap-1 font-mono text-sm text-white">
        {codes.map((code) => (
          <li key={code}>{code}</li>
        ))}
      </ul>
      <div className="flex gap-2">
        <button type="button" className={buttonClass("secondary", "sm")} onClick={() => void copy(text)}>
          {copied ? "Copied" : "Copy"}
        </button>
        <button type="button" className={buttonClass("secondary", "sm")} onClick={() => downloadText(filename, text)}>
          Download
        </button>
      </div>
    </Callout>
  );
}