IsolatedAppDrawDownDialog.tsx raw

   1  import React from "react";
   2  import { toast } from "sonner";
   3  import { LoadingButton } from "src/components/ui/custom/loading-button";
   4  import {
   5    Dialog,
   6    DialogContent,
   7    DialogDescription,
   8    DialogFooter,
   9    DialogHeader,
  10    DialogTitle,
  11    DialogTrigger,
  12  } from "src/components/ui/dialog";
  13  import { Input } from "src/components/ui/input";
  14  import { Label } from "src/components/ui/label";
  15  import { useApp } from "src/hooks/useApp";
  16  import { handleRequestError } from "src/utils/handleRequestError";
  17  import { request } from "src/utils/request";
  18  
  19  type IsolatedAppTopupProps = {
  20    appId: number;
  21  };
  22  
  23  export function IsolatedAppDrawDownDialog({
  24    appId,
  25    children,
  26  }: React.PropsWithChildren<IsolatedAppTopupProps>) {
  27    const { mutate: reloadApp } = useApp(appId);
  28    const [amountSat, setAmountSat] = React.useState("");
  29    const [description, setDescription] = React.useState("");
  30    const [loading, setLoading] = React.useState(false);
  31    const [open, setOpen] = React.useState(false);
  32    async function onSubmit(e: React.FormEvent) {
  33      e.preventDefault();
  34      setLoading(true);
  35      try {
  36        await request(`/api/transfers`, {
  37          method: "POST",
  38          headers: {
  39            "Content-Type": "application/json",
  40          },
  41          body: JSON.stringify({
  42            fromAppId: appId,
  43            amountSat: +amountSat,
  44            description,
  45          }),
  46        });
  47        await reloadApp();
  48        toast(`Successfully reduced balance by ${+amountSat} sats`);
  49        reset();
  50      } catch (error) {
  51        handleRequestError("Failed to decrease sub-wallet balance", error);
  52      }
  53      setLoading(false);
  54    }
  55  
  56    function reset() {
  57      setOpen(false);
  58      setAmountSat("");
  59      setDescription("");
  60    }
  61  
  62    return (
  63      <Dialog open={open} onOpenChange={setOpen}>
  64        <DialogTrigger asChild>{children}</DialogTrigger>
  65        <DialogContent>
  66          <form onSubmit={onSubmit}>
  67            <DialogHeader>
  68              <DialogTitle>Decrease Balance</DialogTitle>
  69              <DialogDescription>
  70                Decrease the balance of this sub-wallet.
  71              </DialogDescription>
  72            </DialogHeader>
  73            <div className="grid gap-2 mt-5">
  74              <Label htmlFor="amount">Amount (sats)</Label>
  75              <Input
  76                autoFocus
  77                id="amount"
  78                type="number"
  79                required
  80                value={amountSat}
  81                onChange={(e) => {
  82                  setAmountSat(e.target.value.trim());
  83                }}
  84              />
  85            </div>
  86            <div className="grid gap-2 mt-3">
  87              <Label htmlFor="description">Description (optional)</Label>
  88              <Input
  89                id="description"
  90                type="text"
  91                placeholder="transfer"
  92                value={description}
  93                onChange={(e) => {
  94                  setDescription(e.target.value);
  95                }}
  96              />
  97            </div>
  98            <DialogFooter className="mt-5">
  99              <LoadingButton loading={loading}>Decrease</LoadingButton>
 100            </DialogFooter>
 101          </form>
 102        </DialogContent>
 103      </Dialog>
 104    );
 105  }
 106