import React, { useEffect, useState } from 'react'; import axios from 'axios'; import { useRouter } from 'next/router'; import { parseEvent, findKind0Fields } from '@/utils/nostr'; import { useImageProxy } from '@/hooks/useImageProxy'; import { getSatAmountFromInvoice } from '@/utils/lightning'; import ZapDisplay from '@/components/zaps/ZapDisplay'; import { Tag } from 'primereact/tag'; import { Button } from 'primereact/button'; import { nip19, nip04 } from 'nostr-tools'; import { useSession } from 'next-auth/react'; import Image from 'next/image'; import dynamic from 'next/dynamic'; import ZapThreadsWrapper from '@/components/ZapThreadsWrapper'; import { useToast } from '@/hooks/useToast'; import { useNDKContext } from '@/context/NDKContext'; import { useZapsSubscription } from '@/hooks/nostrQueries/zaps/useZapsSubscription'; import { LightningAddress } from "@getalby/lightning-tools"; import PaymentButton from '@/components/bitcoinConnect/PaymentButton'; import 'primeicons/primeicons.css'; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), { ssr: false, } ); const BitcoinConnectPayButton = dynamic( () => import('@getalby/bitcoin-connect-react').then((mod) => mod.PayButton), { ssr: false, } ); const privkey = process.env.NEXT_PUBLIC_APP_PRIV_KEY; const pubkey = process.env.NEXT_PUBLIC_APP_PUBLIC_KEY; export default function Details() { const [event, setEvent] = useState(null); const [processedEvent, setProcessedEvent] = useState({}); const [author, setAuthor] = useState(null); const [bitcoinConnect, setBitcoinConnect] = useState(false); const [nAddress, setNAddress] = useState(null); const [zapAmount, setZapAmount] = useState(null); const [paidResource, setPaidResource] = useState(false); const [decryptedContent, setDecryptedContent] = useState(null); const [authorView, setAuthorView] = useState(false); const ndk = useNDKContext(); const { data: session, status } = useSession(); const [user, setUser] = useState(null); const { returnImageProxy } = useImageProxy(); const { showToast } = useToast(); const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent }); const router = useRouter(); useEffect(() => { if (session) { setUser(session.user); } }, [session]); useEffect(() => { if (processedEvent.price) { setPaidResource(true); } }, [processedEvent]); useEffect(() => { if (typeof window === 'undefined') return; const bitcoinConnectConfig = window.localStorage.getItem('bc:config'); if (bitcoinConnectConfig) { setBitcoinConnect(true); } }, []); useEffect(() => { const decryptContent = async () => { if (user && paidResource) { if (user?.purchased?.includes(processedEvent.id) || (user?.role && user?.role.subscribed)) { // decrypt the content const decryptedContent = await nip04.decrypt(privkey, pubkey, processedEvent.content); setDecryptedContent(decryptedContent); } } } decryptContent(); }, [user, paidResource, processedEvent]); useEffect(() => { if (router.isReady) { const { slug } = router.query; const fetchEvent = async (slug) => { try { await ndk.connect(); const filter = { ids: [slug] } const event = await ndk.fetchEvent(filter); if (event) { setEvent(event); if (user && user.pubkey === event.pubkey) { setAuthorView(true); } } } catch (error) { console.error('Error fetching event:', error); } }; if (ndk) { fetchEvent(slug); } } }, [router.isReady, router.query, ndk, user]); useEffect(() => { const fetchAuthor = async (pubkey) => { try { await ndk.connect(); const filter = { kinds: [0], authors: [pubkey] } const author = await ndk.fetchEvent(filter); if (author) { const fields = await findKind0Fields(JSON.parse(author.content)); setAuthor(fields); } } catch (error) { console.error('Error fetching author:', error); } } if (event && ndk) { fetchAuthor(event.pubkey); } }, [ndk, event]); useEffect(() => { if (event) { const parsedEvent = parseEvent(event); setProcessedEvent(parsedEvent); } }, [event]); useEffect(() => { if (processedEvent?.d) { const naddr = nip19.naddrEncode({ pubkey: processedEvent.pubkey, kind: processedEvent.kind, identifier: processedEvent.d, }); setNAddress(naddr); } }, [processedEvent]); useEffect(() => { if (!zaps) return; let total = 0; zaps.forEach((zap) => { const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11"); const invoice = bolt11Tag ? bolt11Tag[1] : null; if (invoice) { const amount = getSatAmountFromInvoice(invoice); total += amount; } }); setZapAmount(total); }, [zaps]); const handleDelete = async () => { try { const response = await axios.delete(`/api/resources/${processedEvent.d}`); if (response.status === 204) { showToast('success', 'Success', 'Resource deleted successfully.'); router.push('/'); } } catch (error) { if (error.response && error.response.data && error.response.data.error.includes("Invalid `prisma.resource.delete()`")) { showToast('error', 'Error', 'Resource cannot be deleted because it is part of a course, delete the course first.'); } else if (error.response && error.response.data && error.response.data.error) { showToast('error', 'Error', error.response.data.error); } else { showToast('error', 'Error', 'Failed to delete resource. Please try again.'); } } } const renderContent = () => { if (decryptedContent) { return ; } if (paidResource && !decryptedContent) { return

This content is paid and needs to be purchased before viewing.

; } if (processedEvent?.content) { return ; } return null; }; const handlePaymentSuccess = (response) => { console.log("response in higher level", response) } const handlePaymentError = (error) => { console.log("error in higher level", error) } return (
router.push('/')} />
{processedEvent && processedEvent.topics && processedEvent.topics.length > 0 && ( processedEvent.topics.map((topic, index) => ( )) ) }

{processedEvent?.title}

{processedEvent?.summary}

avatar image

Created by{' '} {author?.username}

{processedEvent && (
resource thumbnail
{paidResource && !decryptedContent && }
)}
{authorView && (
)} {typeof window !== 'undefined' && nAddress !== null && (
)}
{renderContent()}
); }