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