import { Form } from "@remix-run/react"; import { DownloadIcon } from "lucide-react"; import { QRCodeSVG } from "qrcode.react"; import { useState } from "react"; import { Button } from "~/components/primitives/Buttons"; import { CopyableText } from "~/components/primitives/CopyableText"; import { CopyButton } from "~/components/primitives/CopyButton"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "~/components/primitives/Dialog"; import { FormError } from "~/components/primitives/FormError"; import { InputOTP, InputOTPGroup, InputOTPSlot } from "~/components/primitives/InputOTP"; import { Paragraph } from "~/components/primitives/Paragraph"; interface MfaSetupDialogProps { isOpen: boolean; setupData?: { secret: string; otpAuthUrl: string; }; recoveryCodes?: string[]; error?: string; isSubmitting: boolean; onValidate: (code: string) => void; onCancel: () => void; onSaveRecoveryCodes: () => void; } export function MfaSetupDialog({ isOpen, setupData, recoveryCodes, error, isSubmitting, onValidate, onCancel, onSaveRecoveryCodes, }: MfaSetupDialogProps) { const [totpCode, setTotpCode] = useState(""); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); onValidate(totpCode); setTotpCode(""); }; const handleCancel = () => { setTotpCode(""); onCancel(); }; const handleRecoverySubmit = (e: React.FormEvent) => { e.preventDefault(); onSaveRecoveryCodes(); }; const downloadRecoveryCodes = () => { if (!recoveryCodes) return; const content = recoveryCodes.join("\n"); const blob = new Blob([content], { type: "text/plain" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "trigger-dev-recovery-codes.txt"; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; // Show recovery codes if they exist if (recoveryCodes && recoveryCodes.length > 0) { return ( Recovery codes Copy and store these recovery codes carefully in case you lose your device. {recoveryCodes.map((code, index) => ( {code} ))} Download Copy Continue ); } // Show QR setup if no recovery codes yet if (!setupData) return null; return ( Enable authenticator app Scan the QR code below with your preferred authenticator app then enter the 6 digit code that the app generates. Alternatively, you can copy the secret below and paste it into your app. setTotpCode(value)} variant="large" name="totpCode" onKeyDown={(e) => { if (e.key === "Enter" && totpCode.length === 6) { handleSubmit(e); } }} > {error && {error}} Cancel Confirm ); }