Tictactoe.tsx raw

   1  import { AlertTriangleIcon, CopyIcon, ExternalLinkIcon } from "lucide-react";
   2  import React, { useEffect } from "react";
   3  import { toast } from "sonner";
   4  import AppHeader from "src/components/AppHeader";
   5  import AppCard from "src/components/connections/AppCard";
   6  import { appStoreApps } from "src/components/connections/SuggestedAppData";
   7  import QRCode from "src/components/QRCode";
   8  import { Alert, AlertDescription, AlertTitle } from "src/components/ui/alert";
   9  import { Button } from "src/components/ui/button";
  10  import {
  11    Card,
  12    CardContent,
  13    CardHeader,
  14    CardTitle,
  15  } from "src/components/ui/card";
  16  import { LoadingButton } from "src/components/ui/custom/loading-button";
  17  import { Input } from "src/components/ui/input";
  18  import {
  19    DEFAULT_APP_BUDGET_RENEWAL,
  20    DEFAULT_APP_BUDGET_SATS,
  21  } from "src/constants";
  22  import { useApps } from "src/hooks/useApps";
  23  import { copyToClipboard } from "src/lib/clipboard";
  24  import { createApp } from "src/requests/createApp";
  25  import { handleRequestError } from "src/utils/handleRequestError";
  26  import { openLink } from "src/utils/openLink";
  27  
  28  export function Tictactoe() {
  29    const appId = "tictactoe";
  30    const [isLoading, setLoading] = React.useState(false);
  31    const [appLink, setAppLink] = React.useState("");
  32    const { data: appsData, mutate: reloadApps } = useApps(undefined, undefined, {
  33      appStoreAppId: appId,
  34    });
  35    const tictactoeApps = appsData?.apps;
  36    const appStoreApp = appStoreApps.find((app) => app.id === appId)!;
  37  
  38    useEffect(() => {
  39      if (appLink) {
  40        window.open(appLink, "_blank");
  41      }
  42    }, [appLink]);
  43  
  44    const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
  45      event.preventDefault();
  46      setLoading(true);
  47      (async () => {
  48        try {
  49          const createAppResponse = await createApp({
  50            name: appStoreApp.title,
  51            scopes: ["get_info", "lookup_invoice", "make_invoice", "pay_invoice"],
  52            maxAmountSat: DEFAULT_APP_BUDGET_SATS,
  53            budgetRenewal: DEFAULT_APP_BUDGET_RENEWAL,
  54            metadata: {
  55              app_store_app_id: appId,
  56            },
  57          });
  58  
  59          setAppLink(
  60            `https://lntictactoe.com/#nwc=${encodeURIComponent(createAppResponse.pairingUri)}`
  61          );
  62          toast("Tic Tac Toe connection created");
  63        } catch (error) {
  64          handleRequestError("Failed to create connection", error);
  65        }
  66        setLoading(false);
  67        reloadApps();
  68      })();
  69    };
  70  
  71    return (
  72      <div className="grid gap-5">
  73        <AppHeader
  74          pageTitle={appStoreApp.title}
  75          title={
  76            <div className="flex flex-row items-center">
  77              <img src={appStoreApp.logo} className="w-14 h-14 rounded-lg mr-4" />
  78              <div className="flex flex-col">
  79                <div>{appStoreApp.title}</div>
  80                <div className="text-sm font-normal text-muted-foreground">
  81                  {appStoreApp.description}
  82                </div>
  83              </div>
  84            </div>
  85          }
  86        />
  87        {appLink ? (
  88          <div className="max-w-lg flex flex-col gap-5">
  89            <p>Open the link below to start playing.</p>
  90            <Alert>
  91              <AlertTriangleIcon />
  92              <AlertTitle>
  93                Save this link and add it to your home screen
  94              </AlertTitle>
  95              <AlertDescription>
  96                This link will only be shown once and can't be retrieved
  97                afterwards. Please make sure to keep it somewhere safe.
  98              </AlertDescription>
  99            </Alert>
 100            <div
 101              className="flex flex-col items-center relative cursor-pointer"
 102              onClick={() => openLink(appLink)}
 103            >
 104              <QRCode value={appLink} />
 105              <img
 106                src={appStoreApp.logo}
 107                className="absolute w-12 h-12 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-muted p-1 rounded-xl"
 108              />
 109            </div>
 110            <div className="flex gap-2">
 111              <Input disabled readOnly type="text" value={appLink} />
 112              <Button onClick={() => copyToClipboard(appLink)} variant="outline">
 113                <CopyIcon />
 114                Copy
 115              </Button>
 116              <Button onClick={() => openLink(appLink)} variant="outline">
 117                <ExternalLinkIcon />
 118                Open
 119              </Button>
 120            </div>
 121          </div>
 122        ) : (
 123          <Card className="max-w-lg">
 124            <CardHeader>
 125              <CardTitle className="text-2xl">About the App</CardTitle>
 126            </CardHeader>
 127            <CardContent className="flex flex-col gap-3">
 128              <p className="text-muted-foreground">
 129                By connecting Tic Tac Toe to your Alby Hub, you can play
 130                <br />
 131                tic tac toe with your friends and earn satoshis.
 132              </p>
 133              <div className="flex flex-col gap-5">
 134                <form
 135                  onSubmit={handleSubmit}
 136                  className="flex flex-col items-start gap-5 max-w-lg"
 137                >
 138                  <LoadingButton loading={isLoading} type="submit">
 139                    Start playing
 140                  </LoadingButton>
 141                </form>
 142              </div>
 143            </CardContent>
 144          </Card>
 145        )}
 146        {!!tictactoeApps?.length && (
 147          <>
 148            <h2 className="font-semibold text-xl">Tic Tac Toe connections</h2>
 149            <div className="grid grid-cols-1 lg:grid-cols-2 gap-3 items-stretch">
 150              {tictactoeApps.map((app, index) => (
 151                <AppCard key={index} app={app} />
 152              ))}
 153            </div>
 154          </>
 155        )}
 156      </div>
 157    );
 158  }
 159