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