added confirm modal and fixed some subscribing bugs

This commit is contained in:
zmeyer44 2023-10-17 18:18:17 -04:00
parent 675e0c4507
commit 7a478f9efe
4 changed files with 118 additions and 11 deletions

View File

@ -4,8 +4,7 @@ import Image from "next/image";
import dynamic from "next/dynamic";
import { Button } from "@/components/ui/button";
import useProfile from "@/lib/hooks/useProfile";
import { nip19 } from "nostr-tools";
import useEvents from "@/lib/hooks/useEvents";
import { HiOutlineLightningBolt } from "react-icons/hi";
import Spinner from "@/components/spinner";
import { getTagValues, getTagsValues } from "@/lib/nostr/utils";
import ProfileInfo from "./ProfileInfo";
@ -19,19 +18,22 @@ import {
} from "@/lib/actions/zap";
import { useModal } from "@/app/_providers/modal/provider";
import { type NDKEvent } from "@nostr-dev-kit/ndk";
import { btcToSats, formatNumber } from "@/lib/utils";
import { formatDate } from "@/lib/utils/dates";
const EditListModal = dynamic(() => import("@/components/Modals/EditList"), {
ssr: false,
});
const CreateEventModal = dynamic(() => import("@/components/Modals/NewEvent"), {
ssr: false,
});
const ConfirmModal = dynamic(() => import("@/components/Modals/Confirm"), {
ssr: false,
});
export default function Header({ event }: { event: NDKEvent }) {
const { currentUser } = useCurrentUser();
const modal = useModal();
const { ndk } = useNDK();
const [sendingZap, setSendingZap] = useState(false);
const [checkingPayment, setCheckingPayment] = useState(false);
const [hasValidPayment, setHasValidPayment] = useState(false);
const [syncingUsers, setSyncingUsers] = useState(false);
@ -39,7 +41,6 @@ export default function Header({ event }: { event: NDKEvent }) {
const { profile } = useProfile(pubkey);
const noteIds = getTagsValues("e", event.tags).filter(Boolean);
console.log("notes", event.tags);
const title =
getTagValues("title", event.tags) ??
getTagValues("name", event.tags) ??
@ -53,7 +54,7 @@ export default function Header({ event }: { event: NDKEvent }) {
const description = getTagValues("description", event.tags);
const rawEvent = event.rawEvent();
const subscriptionsEnabled = !!getTagValues("subscriptions", rawEvent.tags);
const priceInBTC = getTagValues("price", rawEvent.tags);
const priceInBTC = parseFloat(getTagValues("price", rawEvent.tags) ?? "0");
const isMember =
currentUser &&
getTagsValues("p", rawEvent.tags).includes(currentUser.pubkey);
@ -99,6 +100,21 @@ export default function Header({ event }: { event: NDKEvent }) {
setSyncingUsers(false);
}
}
async function handleSendZap() {
try {
const result = await sendZap(
ndk!,
btcToSats(priceInBTC),
rawEvent,
`Access payment: ${title}`,
);
toast.success("Payment Sent!");
void handleCheckPayment();
} catch (err) {
console.log("error sending zap", err);
} finally {
}
}
if (!event) {
return (
<div className="center pt-20 text-primary">
@ -155,7 +171,39 @@ export default function Header({ event }: { event: NDKEvent }) {
</Button>
</>
)}
{subscriptionsEnabled && !isMember && <Button>Subscribe</Button>}
{subscriptionsEnabled && !isMember && (
<Button
onClick={() =>
modal?.show(
<ConfirmModal
title={`Subscribe to ${title}`}
onConfirm={handleSendZap}
ctaBody={
<>
<span>Zap to Subscribe</span>
<HiOutlineLightningBolt className="h-4 w-4" />
</>
}
>
<p className="text-muted-forground">
{`Pay ${priceInBTC} BTC (${formatNumber(
btcToSats(priceInBTC),
)} sats) for year long access until ${formatDate(
new Date(
new Date().setFullYear(
new Date().getFullYear() + 1,
),
),
"MMM Do, YYYY",
)}`}
</p>
</ConfirmModal>,
)
}
>
Subscribe
</Button>
)}
</div>
</div>

View File

@ -0,0 +1,56 @@
"use client";
import { useState, type ReactNode } from "react";
import Template from "./Template";
import { Button } from "@/components/ui/button";
import { useModal } from "@/app/_providers/modal/provider";
import { nip19 } from "nostr-tools";
// import { useKeys } from "@/app/_providers/keysProvider";
import { useNDK } from "@/app/_providers/ndk";
import useCurrentUser from "@/lib/hooks/useCurrentUser";
import { HiOutlineLightningBolt } from "react-icons/hi";
import { RiSubtractFill, RiAddFill } from "react-icons/ri";
import { formatCount } from "@/lib/utils";
type ConfirmModalProps = {
title?: string;
children: ReactNode;
ctaBody?: ReactNode;
onConfirm: () => Promise<void>;
};
export default function ConfirmModal({
title = "Confirm",
children,
ctaBody = "Confirm",
onConfirm,
}: ConfirmModalProps) {
const [isLoading, setIsLoading] = useState(false);
const modal = useModal();
async function handleSubmit() {
setIsLoading(true);
try {
await onConfirm();
} catch (err) {
console.log("Error", err);
} finally {
setIsLoading(false);
modal?.hide();
}
}
return (
<Template title={title} className="md:max-w-[400px]">
<div className="flex flex-col gap-y-5">
<div className="pb-2">{children}</div>
<Button
onClick={() => void handleSubmit()}
loading={isLoading}
className="w-full gap-x-1"
>
{ctaBody}
</Button>
</div>
</Template>
);
}

View File

@ -114,6 +114,7 @@ export default function FormModal<TSchema extends FieldValues>({
if (!condition) {
return (
<FormField
key={slug}
control={form.control}
name={slug as Path<TSchema>}
render={({ field }) => (
@ -187,6 +188,7 @@ export default function FormModal<TSchema extends FieldValues>({
if (!state) return;
return (
<FormField
key={slug}
control={form.control}
name={slug as Path<TSchema>}
render={({ field }) => (

View File

@ -103,10 +103,11 @@ export async function updateListUsersFromZaps(
event: NostrEvent,
) {
const SECONDS_IN_MONTH = 2_628_000;
const SECONDS_IN_YEAR = SECONDS_IN_MONTH * 365;
const paymentEvents = await ndk.fetchEvents({
kinds: [9735],
["#a"]: [tagId],
since: unixTimeNowInSeconds() - SECONDS_IN_MONTH,
since: unixTimeNowInSeconds() - SECONDS_IN_YEAR,
});
const paymentInvoices = Array.from(paymentEvents).map((paymentEvent) =>
zapInvoiceFromEvent(paymentEvent),
@ -137,7 +138,7 @@ export async function updateListUsersFromZaps(
paymentInvoice.zappee,
"",
"",
(unixTimeNowInSeconds() + SECONDS_IN_MONTH).toString(),
(unixTimeNowInSeconds() + SECONDS_IN_YEAR).toString(),
]);
}
}
@ -152,14 +153,14 @@ export async function updateListUsersFromZaps(
event.pubkey,
"",
"self",
(unixTimeNowInSeconds() + SECONDS_IN_MONTH).toString(),
(unixTimeNowInSeconds() + SECONDS_IN_YEAR).toString(),
];
} else {
validUsers.push([
event.pubkey,
"",
"self",
(unixTimeNowInSeconds() + SECONDS_IN_MONTH).toString(),
(unixTimeNowInSeconds() + SECONDS_IN_YEAR).toString(),
]);
}
console.log("Valid users", validUsers);