diff --git a/app/(app)/list/[naddr]/_components/Header.tsx b/app/(app)/list/[naddr]/_components/Header.tsx new file mode 100644 index 0000000..345f76d --- /dev/null +++ b/app/(app)/list/[naddr]/_components/Header.tsx @@ -0,0 +1,185 @@ +"use client"; +import { useEffect, useState } from "react"; +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 Spinner from "@/components/spinner"; +import { getTagValues, getTagsValues } from "@/lib/nostr/utils"; +import ProfileInfo from "./ProfileInfo"; +import useCurrentUser from "@/lib/hooks/useCurrentUser"; +import { useNDK } from "@/app/_providers/ndk"; +import { toast } from "sonner"; +import { + sendZap, + checkPayment, + updateListUsersFromZaps, +} from "@/lib/actions/zap"; +import { useModal } from "@/app/_providers/modal/provider"; + +const EditListModal = dynamic(() => import("@/components/Modals/EditList"), { + ssr: false, +}); +const CreateEventModal = dynamic(() => import("@/components/Modals/NewEvent"), { + ssr: false, +}); + +export default function Header({ naddr }: { naddr: string }) { + 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); + const { type, data } = nip19.decode(naddr); + console.log("PASSED", naddr, data); + if (type !== "naddr") { + throw new Error("Invalid list"); + } + const { identifier, kind, pubkey } = data; + const { profile } = useProfile(pubkey); + const { events } = useEvents({ + filter: { + authors: [pubkey], + kinds: [kind], + ["#d"]: [identifier], + limit: 1, + }, + }); + const event = events[0]; + + if (!event) { + return ( +
+ +
+ ); + } + const noteIds = getTagsValues("e", event.tags).filter(Boolean); + console.log("notes", event.tags); + const title = + getTagValues("title", event.tags) ?? + getTagValues("name", event.tags) ?? + "Untitled"; + const image = + getTagValues("image", event.tags) ?? + getTagValues("picture", event.tags) ?? + getTagValues("banner", event.tags) ?? + profile?.banner; + + const description = getTagValues("description", event.tags); + const rawEvent = event.rawEvent(); + const subscriptionsEnabled = !!getTagValues("subscriptions", rawEvent.tags); + const priceInBTC = getTagValues("price", rawEvent.tags); + const isMember = + currentUser && + getTagsValues("p", rawEvent.tags).includes(currentUser.pubkey); + + useEffect(() => { + if (!currentUser || !subscriptionsEnabled) return; + if (!isMember && !checkingPayment && !hasValidPayment) { + void handleCheckPayment(); + } + }, [isMember, currentUser]); + + async function handleCheckPayment() { + if (!event) return; + setCheckingPayment(true); + console.log("Checking payment"); + try { + const result = await checkPayment( + ndk!, + event.tagId(), + currentUser!.hexpubkey, + rawEvent, + ); + console.log("Payment result", result); + if (result) { + setHasValidPayment(true); + } + } catch (err) { + console.log("error sending zap", err); + } finally { + setCheckingPayment(false); + } + } + async function handleSyncUsers() { + if (!event) return; + setSyncingUsers(true); + try { + console.log("handleSyncUsers"); + await updateListUsersFromZaps(ndk!, event.tagId(), rawEvent); + toast.success("Users Synced!"); + } catch (err) { + console.log("error syncing users", err); + } finally { + setSyncingUsers(false); + } + } + return ( +
+
+
+ {!!image && ( + banner + )} +
+
+
+
+
+

+ {title} +

+
+ +
+
+
+ {!!currentUser && currentUser.pubkey === pubkey && ( + <> + + + + + )} + {subscriptionsEnabled && !isMember && } +
+
+ +
+ {!!description && ( +

+ {description} +

+ )} +
+
+
+ ); +} diff --git a/app/(app)/list/[naddr]/page.tsx b/app/(app)/list/[naddr]/page.tsx index 63aaa35..29c2945 100644 --- a/app/(app)/list/[naddr]/page.tsx +++ b/app/(app)/list/[naddr]/page.tsx @@ -13,18 +13,8 @@ import Spinner from "@/components/spinner"; import { getTagValues, getTagsValues } from "@/lib/nostr/utils"; import ProfileInfo from "./_components/ProfileInfo"; import Feed from "@/containers/Feed"; - -const demo = [ - { - id: "1", - title: "BTC Radio", - description: - "BTC Radio is the best fuking show ever. you should sub to it. now", - picture: - "https://assets.whop.com/cdn-cgi/image/width=1080/https://assets.whop.com/images/images/51602.original.png?1693358530", - tags: ["music", "crypto", "art"], - }, -]; +import useCurrentUser from "@/lib/hooks/useCurrentUser"; +import Header from "./_components/Header"; export default function ListPage({ params: { naddr }, @@ -33,14 +23,11 @@ export default function ListPage({ naddr: string; }; }) { - const [activeTab, setActiveTab] = useState("feed"); const { type, data } = nip19.decode(naddr); - console.log("PASSED", naddr, data); if (type !== "naddr") { throw new Error("Invalid list"); } const { identifier, kind, pubkey } = data; - const { profile } = useProfile(pubkey); const { events } = useEvents({ filter: { authors: [pubkey], @@ -60,56 +47,10 @@ export default function ListPage({ } const noteIds = getTagsValues("e", event.tags).filter(Boolean); console.log("notes", event.tags); - const title = - getTagValues("title", event.tags) ?? - getTagValues("name", event.tags) ?? - "Untitled"; - const image = - getTagValues("image", event.tags) ?? - getTagValues("picture", event.tags) ?? - getTagValues("banner", event.tags) ?? - profile?.banner; - const description = getTagValues("description", event.tags); return (
-
-
-
- {!!image && ( - banner - )} -
-
-
-
-
-

- {title} -

-
- -
-
- -
- -
- {!!description && ( -

- {description} -

- )} -
-
-
+
; export default function CreateList() { const [isLoading, setIsLoading] = useState(false); const modal = useModal(); + const router = useRouter(); const { currentUser, updateUser } = useCurrentUser(); const { ndk } = useNDK(); @@ -80,8 +81,13 @@ export default function CreateList() { } // getLists(currentUser!.hexpubkey); setIsLoading(false); - toast.success("List Created!"); - modal?.hide(); + if (event) { + toast.success("List Created!"); + modal?.hide(); + router.push(`/list/${event.encode()}`); + } else { + toast.error("An error occured"); + } } return ( ; + +type EditListModalProps = { + listEvent: NostrEvent; +}; +export default function EditListModal({ listEvent }: EditListModalProps) { + const modal = useModal(); + const [isLoading, setIsLoading] = useState(false); + const [sent, setSent] = useState(false); + const { ndk } = useNDK(); + const { events } = useEvents({ + filter: { + kinds: [listEvent.kind as number], + authors: [listEvent.pubkey], + since: unixTimeNowInSeconds() - 10, + limit: 1, + }, + enabled: sent, + }); + useEffect(() => { + if (events.length) { + console.log("Done!"); + setIsLoading(false); + toast.success("List Updated!"); + modal?.hide(); + } + }, [events]); + + async function handleSubmit(listData: EditListType) { + setIsLoading(true); + const newTags = Object.entries(listData); + setSent(true); + const result = await updateList(ndk!, listEvent, newTags); + } + const defaultValues: Partial = { + title: + getTagValues("title", listEvent.tags) ?? + getTagValues("name", listEvent.tags), + image: + getTagValues("image", listEvent.tags) ?? + getTagValues("picture", listEvent.tags), + description: + getTagValues("description", listEvent.tags) ?? + getTagValues("summary", listEvent.tags), + }; + + return ( + + ); +}