MnemonicDialog.tsx raw
1 import { useState } from "react";
2 import { useNavigate } from "react-router";
3 import { toast } from "sonner";
4 import MnemonicInputs from "src/components/mnemonic/MnemonicInputs";
5 import { Button } from "src/components/ui/button";
6 import { Checkbox } from "src/components/ui/checkbox";
7 import {
8 Dialog,
9 DialogContent,
10 DialogDescription,
11 DialogHeader,
12 DialogTitle,
13 } from "src/components/ui/dialog";
14 import { Label } from "src/components/ui/label";
15 import { useInfo } from "src/hooks/useInfo";
16 import { handleRequestError } from "src/utils/handleRequestError";
17 import { request } from "src/utils/request";
18
19 type Props = {
20 open?: boolean;
21 defaultOpen?: boolean;
22 onOpenChange?(open: boolean): void;
23 mnemonic: string;
24 };
25
26 export default function MnemonicDialog({
27 open,
28 defaultOpen,
29 onOpenChange,
30 mnemonic,
31 }: Props) {
32 const { data: info } = useInfo();
33 const { mutate: refetchInfo } = useInfo();
34 const [backedUp, setIsBackedUp] = useState<boolean>(false);
35 const [backedUp2, setIsBackedUp2] = useState<boolean>(false);
36 const navigate = useNavigate();
37
38 async function onSubmit(e: React.FormEvent) {
39 e.preventDefault();
40
41 const sixMonthsLater = new Date();
42 sixMonthsLater.setMonth(sixMonthsLater.getMonth() + 6);
43
44 try {
45 await request("/api/backup-reminder", {
46 method: "PATCH",
47 headers: {
48 "Content-Type": "application/json",
49 },
50 body: JSON.stringify({
51 nextBackupReminder: sixMonthsLater.toISOString(),
52 }),
53 });
54 await refetchInfo();
55 navigate("/");
56 toast("Recovery phrase backed up!");
57 } catch (error) {
58 handleRequestError("Failed to store back up info", error);
59 }
60 }
61
62 return (
63 <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={defaultOpen}>
64 <DialogContent>
65 <DialogHeader>
66 <DialogTitle>Recovery Phrase</DialogTitle>
67 <DialogDescription>
68 Write these words down, store them somewhere safe, and keep them
69 secret.
70 </DialogDescription>
71 </DialogHeader>
72 <form
73 onSubmit={onSubmit}
74 className="flex flex-col gap-2 max-w-md text-sm"
75 >
76 <MnemonicInputs mnemonic={mnemonic} readOnly={true} asCard={false} />
77 <div className="flex flex-col gap-2 mt-4">
78 <div className="flex">
79 <Checkbox
80 id="backup"
81 required
82 checked={backedUp}
83 onCheckedChange={() => setIsBackedUp(!backedUp)}
84 className="mt-0.5"
85 />
86 <Label htmlFor="backup" className="ml-2 cursor-pointer">
87 I've backed up my recovery phrase to my wallet in a private and
88 secure place
89 </Label>
90 </div>
91
92 {backedUp && !info?.albyAccountConnected && (
93 <div className="flex">
94 <Checkbox
95 id="backup2"
96 required
97 checked={backedUp2}
98 onCheckedChange={() => setIsBackedUp2(!backedUp2)}
99 className="mt-0.5"
100 />
101 <Label htmlFor="backup2" className="ml-2 cursor-pointer">
102 I understand the recovery phrase AND a backup of my hub data
103 directory after each channel opening is required to recover
104 funds from my lightning channels.
105 </Label>
106 </div>
107 )}
108 </div>
109 <div className="flex justify-end items-center mt-2">
110 <Button type="submit" size="lg" className="grow sm:grow-0">
111 Finish
112 </Button>
113 </div>
114 </form>
115 </DialogContent>
116 </Dialog>
117 );
118 }
119