feat: polish
This commit is contained in:
@@ -5,15 +5,14 @@ import { useStorage } from "@lume/storage";
|
||||
import { cn, compactNumber, displayNpub } from "@lume/utils";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import { useState } from "react";
|
||||
import CurrencyInput from "react-currency-input-field";
|
||||
import { toast } from "sonner";
|
||||
import { useArk } from "../../../hooks/useArk";
|
||||
import { useProfile } from "../../../hooks/useProfile";
|
||||
import { useNoteContext } from "../provider";
|
||||
|
||||
export function NoteZap() {
|
||||
const ark = useArk();
|
||||
const storage = useStorage();
|
||||
const event = useNoteContext();
|
||||
|
||||
@@ -22,11 +21,12 @@ export function NoteZap() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isCompleted, setIsCompleted] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [invoice, setInvoice] = useState<string>(null);
|
||||
|
||||
const { user } = useProfile(event.pubkey);
|
||||
|
||||
const createZapRequest = async (instant?: boolean) => {
|
||||
if (!storage.nwc) return;
|
||||
if (instant && !storage.nwc) return;
|
||||
|
||||
let nwc: webln.NostrWebLNProvider = undefined;
|
||||
|
||||
@@ -37,6 +37,8 @@ export function NoteZap() {
|
||||
const zapAmount = parseInt(amount) * 1000;
|
||||
const res = await event.zap(zapAmount, zapMessage);
|
||||
|
||||
if (!storage.nwc) return setInvoice(res);
|
||||
|
||||
// user connect nwc
|
||||
nwc = new webln.NostrWebLNProvider({
|
||||
nostrWalletConnectUrl: storage.nwc,
|
||||
@@ -144,101 +146,105 @@ export function NoteZap() {
|
||||
<CancelIcon className="w-4 h-4" />
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
<div className="px-5 pb-5 overflow-x-hidden overflow-y-auto">
|
||||
<div className="relative flex flex-col h-40">
|
||||
<div className="inline-flex items-center justify-center flex-1 h-full gap-1">
|
||||
<CurrencyInput
|
||||
placeholder="0"
|
||||
defaultValue={"21"}
|
||||
value={amount}
|
||||
decimalsLimit={2}
|
||||
min={0} // 0 sats
|
||||
max={10000} // 1M sats
|
||||
maxLength={10000} // 1M sats
|
||||
onValueChange={(value) => setAmount(value)}
|
||||
className="flex-1 w-full text-4xl font-semibold text-right bg-transparent border-none placeholder:text-neutral-600 focus:outline-none focus:ring-0 dark:text-neutral-400"
|
||||
{!invoice ? (
|
||||
<div className="px-5 pb-5 overflow-x-hidden overflow-y-auto">
|
||||
<div className="relative flex flex-col h-40">
|
||||
<div className="inline-flex items-center justify-center flex-1 h-full gap-1">
|
||||
<CurrencyInput
|
||||
placeholder="0"
|
||||
defaultValue={"21"}
|
||||
value={amount}
|
||||
decimalsLimit={2}
|
||||
min={0} // 0 sats
|
||||
max={10000} // 1M sats
|
||||
maxLength={10000} // 1M sats
|
||||
onValueChange={(value) => setAmount(value)}
|
||||
className="flex-1 w-full text-4xl font-semibold text-right bg-transparent border-none placeholder:text-neutral-600 focus:outline-none focus:ring-0 dark:text-neutral-400"
|
||||
/>
|
||||
<span className="flex-1 w-full text-4xl font-semibold text-left text-neutral-500 dark:text-neutral-400">
|
||||
sats
|
||||
</span>
|
||||
</div>
|
||||
<div className="inline-flex items-center justify-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("69")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
69 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("100")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
100 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("200")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
200 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("500")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
500 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("1000")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
1K sats
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-full gap-2 mt-4">
|
||||
<input
|
||||
name="zapMessage"
|
||||
value={zapMessage}
|
||||
onChange={(e) => setZapMessage(e.target.value)}
|
||||
spellCheck={false}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder="Enter message (optional)"
|
||||
className="w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-3 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-400"
|
||||
/>
|
||||
<span className="flex-1 w-full text-4xl font-semibold text-left text-neutral-500 dark:text-neutral-400">
|
||||
sats
|
||||
<div className="flex flex-col gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => createZapRequest()}
|
||||
className="inline-flex items-center justify-center w-full px-4 font-medium text-white bg-blue-500 rounded-lg h-11 hover:bg-blue-600"
|
||||
>
|
||||
{isCompleted
|
||||
? "Zapped"
|
||||
: isLoading
|
||||
? "Processing..."
|
||||
: "Zap"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-5 pb-5 flex flex-col items-center justify-center gap-4">
|
||||
<div className="rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||
<QRCodeSVG value={invoice} size={256} />
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<h3 className="text-lg font-medium">Scan to zap</h3>
|
||||
<span className="text-center text-sm text-neutral-600 dark:text-neutral-400">
|
||||
You must use Bitcoin wallet which support Lightning
|
||||
<br />
|
||||
such as: Blue Wallet, Bitkit, Phoenix,...
|
||||
</span>
|
||||
</div>
|
||||
<div className="inline-flex items-center justify-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("69")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
69 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("100")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
100 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("200")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
200 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("500")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
500 sats
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAmount("1000")}
|
||||
className="w-max rounded-full bg-neutral-100 px-2.5 py-1 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
1K sats
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-full gap-2 mt-4">
|
||||
<input
|
||||
name="zapMessage"
|
||||
value={zapMessage}
|
||||
onChange={(e) => setZapMessage(e.target.value)}
|
||||
spellCheck={false}
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder="Enter message (optional)"
|
||||
className="w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-3 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-400"
|
||||
/>
|
||||
<div className="flex flex-col gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => createZapRequest()}
|
||||
className="inline-flex items-center justify-center w-full px-4 font-medium text-white bg-blue-500 rounded-lg h-11 hover:bg-blue-600"
|
||||
>
|
||||
{isCompleted ? (
|
||||
<p className="leading-tight">Successfully zapped</p>
|
||||
) : isLoading ? (
|
||||
<span className="flex flex-col">
|
||||
<p className="leading-tight">Waiting for approval</p>
|
||||
<p className="text-xs leading-tight text-neutral-100">
|
||||
Go to your wallet and approve payment request
|
||||
</p>
|
||||
</span>
|
||||
) : (
|
||||
<span className="flex flex-col">
|
||||
<p className="leading-tight">Send zap</p>
|
||||
<p className="text-xs leading-tight text-neutral-100">
|
||||
You're using nostr wallet connect
|
||||
</p>
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
|
||||
Reference in New Issue
Block a user