mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-04-19 19:01:19 +00:00
Queries are near perfect, also quality of life improvements
This commit is contained in:
parent
e2181722e3
commit
e265d1ea88
45
package-lock.json
generated
45
package-lock.json
generated
@ -30,6 +30,7 @@
|
||||
"zapthreads": "^0.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"postcss": "^8",
|
||||
@ -1275,6 +1276,36 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography": {
|
||||
"version": "0.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz",
|
||||
"integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.castarray": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"postcss-selector-parser": "6.0.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": ">=3.0.0 || insiders"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.51.21",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.21.tgz",
|
||||
@ -7249,6 +7280,20 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.castarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -31,6 +31,7 @@
|
||||
"zapthreads": "^0.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"postcss": "^8",
|
||||
|
@ -5,70 +5,71 @@ import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
import { useCoursesZapsQuery } from "@/hooks/nostrQueries/zaps/useCoursesZapsQuery";
|
||||
import { useZapsQuery } from "@/hooks/nostrQueries/zaps/useZapsQuery";
|
||||
|
||||
const CourseTemplate = ({ course }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { zaps, zapsLoading, zapsError } = useCoursesZapsQuery({ event: course });
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: course, type: "course" });
|
||||
|
||||
useEffect(() => {
|
||||
if (!zaps || zapsLoading || zapsError) return;
|
||||
useEffect(() => {
|
||||
if (!zaps || zapsLoading || zapsError) return;
|
||||
|
||||
let total = 0;
|
||||
zaps.forEach((zap) => {
|
||||
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === course.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${course.kind}:${course.id}:${course.d}`)) {
|
||||
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);
|
||||
}, [course, zaps, zapsLoading, zapsError]);
|
||||
let total = 0;
|
||||
zaps.forEach((zap) => {
|
||||
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === course.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${course.kind}:${course.id}:${course.d}`)) {
|
||||
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);
|
||||
}, [course, zaps, zapsLoading, zapsError]);
|
||||
|
||||
if (zapsError) return <div>Error: {zapsError}</div>;
|
||||
if (zapsError) return <div>Error: {zapsError}</div>;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md"
|
||||
>
|
||||
<div
|
||||
onClick={() => router.push(`/course/${course.id}`)}
|
||||
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
||||
style={{ paddingBottom: "56.25%" }}
|
||||
>
|
||||
<Image
|
||||
alt="course thumbnail"
|
||||
src={returnImageProxy(course.image)}
|
||||
quality={100}
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col justify-start w-full mt-4">
|
||||
<h4 className="mb-1 font-bold text-lg font-blinker line-clamp-2">
|
||||
{course.name || course.title}
|
||||
</h4>
|
||||
<p className="text-sm text-gray-500 line-clamp-2">{course.description || course.summary}</p>
|
||||
<div className="flex flex-row justify-between items-center mt-2">
|
||||
<p className="text-xs text-gray-400">
|
||||
{course?.published_at && course.published_at !== "" ? (
|
||||
formatTimestampToHowLongAgo(course.published_at)
|
||||
) : (
|
||||
formatTimestampToHowLongAgo(course.created_at)
|
||||
)}
|
||||
</p>
|
||||
<ZapDisplay zapAmount={zapAmount} event={course} zapsLoading={zapsLoading} />
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md"
|
||||
>
|
||||
{/* Wrap the image in a div with a relative class with a padding-bottom of 56.25% representing the aspect ratio of 16:9 */}
|
||||
<div
|
||||
onClick={() => router.push(`/course/${course.id}`)}
|
||||
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
||||
style={{ paddingBottom: "56.25%" }}
|
||||
>
|
||||
<Image
|
||||
alt="course thumbnail"
|
||||
src={returnImageProxy(course.image)}
|
||||
quality={100}
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col justify-start w-full mt-4">
|
||||
<h4 className="mb-1 font-bold text-lg font-blinker line-clamp-2">
|
||||
{course.name || course.title}
|
||||
</h4>
|
||||
<p className="text-sm text-gray-500 line-clamp-2">{course.description || course.summary}</p>
|
||||
<div className="flex flex-row justify-between items-center mt-2">
|
||||
<p className="text-xs text-gray-400">
|
||||
{course?.published_at && course.published_at !== "" ? (
|
||||
formatTimestampToHowLongAgo(course.published_at)
|
||||
) : (
|
||||
formatTimestampToHowLongAgo(course.created_at)
|
||||
)}
|
||||
</p>
|
||||
<ZapDisplay zapAmount={zapAmount} event={course} zapsLoading={zapsLoading} />
|
||||
</div>
|
||||
);
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CourseTemplate;
|
||||
|
@ -3,13 +3,13 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useResourceZapsQuery } from "@/hooks/nostrQueries/zaps/useResourceZapsQuery";
|
||||
import { useZapsQuery } from "@/hooks/nostrQueries/zaps/useZapsQuery";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
|
||||
const ResourceTemplate = ({ resource }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const { zaps, zapsLoading, zapsError } = useResourceZapsQuery({ event: resource });
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: resource, type: "resource" });
|
||||
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
|
@ -3,18 +3,18 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useWorkshopsZapsQuery } from "@/hooks/nostrQueries/zaps/useWorkshopsZapsQuery";
|
||||
import { useZapsQuery } from "@/hooks/nostrQueries/zaps/useZapsQuery";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
|
||||
const WorkshopTemplate = ({ workshop }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { zaps, zapsLoading, zapsError } = useWorkshopsZapsQuery({ event: workshop });
|
||||
const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: workshop, type: "workshop" });
|
||||
|
||||
useEffect(() => {
|
||||
if (!zaps || zapsLoading || zapsError) return;
|
||||
if (zapsLoading || !zaps) return;
|
||||
|
||||
let total = 0;
|
||||
zaps.forEach((zap) => {
|
||||
@ -28,13 +28,15 @@ const WorkshopTemplate = ({ workshop }) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setZapAmount(total);
|
||||
}, [zaps, workshop, zapsLoading, zapsError]);
|
||||
|
||||
|
||||
if (zapsError) return <div>Error: {zapsError}</div>;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md">
|
||||
{/* Wrap the image in a div with a relative class with a padding-bottom of 56.25% representing the aspect ratio of 16:9 */}
|
||||
<div
|
||||
onClick={() => router.push(`/details/${workshop.id}`)}
|
||||
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
||||
|
@ -41,12 +41,12 @@ const WorkshopForm = ({ draft = null }) => {
|
||||
// Check if it's a YouTube video
|
||||
if (videoUrl.includes('youtube.com') || videoUrl.includes('youtu.be')) {
|
||||
const videoId = videoUrl.split('v=')[1] || videoUrl.split('/').pop();
|
||||
embedCode = `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allowfullscreen></iframe>`;
|
||||
embedCode = `<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;max-width:100%;"><iframe src="https://www.youtube.com/embed/${videoId}" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;" allowfullscreen></iframe></div>`;
|
||||
}
|
||||
// Check if it's a Vimeo video
|
||||
else if (videoUrl.includes('vimeo.com')) {
|
||||
const videoId = videoUrl.split('/').pop();
|
||||
embedCode = `<iframe width="560" height="315" src="https://player.vimeo.com/video/${videoId}" frameborder="0" allowfullscreen></iframe>`;
|
||||
embedCode = `<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;max-width:100%;"><iframe src="https://player.vimeo.com/video/${videoId}" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;" allowfullscreen></iframe></div>`;
|
||||
}
|
||||
// Add more conditions here for other video services
|
||||
|
||||
|
@ -12,7 +12,7 @@ const ZapDisplay = ({ zapAmount, event, zapsLoading }) => {
|
||||
{zapsLoading ? (
|
||||
<ProgressSpinner style={{width: '20px', height: '20px'}} strokeWidth="8" animationDuration=".5s" />
|
||||
) : (
|
||||
zapAmount
|
||||
zapAmount !== null ? zapAmount : <ProgressSpinner style={{width: '20px', height: '20px'}} strokeWidth="8" animationDuration=".5s" />
|
||||
)}
|
||||
</span>
|
||||
<OverlayPanel className='w-[40%] h-[40%]' ref={op}>
|
||||
|
@ -2,6 +2,7 @@ import React from "react";
|
||||
import { nip19 } from "nostr-tools";
|
||||
|
||||
const ZapForm = ({ event }) => {
|
||||
console.log('event', event);
|
||||
const nAddress = nip19.naddrEncode({
|
||||
kind: event?.kind,
|
||||
pubkey: event?.pubkey,
|
||||
|
@ -38,7 +38,7 @@ const { data: courses, isLoading: coursesLoading, error: coursesError, refetch:
|
||||
queryKey: ['courses', isClient],
|
||||
queryFn: fetchCoursesFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
refetchInterval: 1000 * 60 * 30, // 30 minutes
|
||||
enabled: isClient,
|
||||
})
|
||||
|
||||
|
@ -43,7 +43,7 @@ const { data: resources, isLoading: resourcesLoading, error: resourcesError, ref
|
||||
queryKey: ['resources', isClient],
|
||||
queryFn: fetchResourcesFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
refetchInterval: 1000 * 60 * 30, // 30 minutes
|
||||
enabled: isClient,
|
||||
})
|
||||
|
||||
|
@ -43,7 +43,7 @@ const { data: workshops, isLoading: workshopsLoading, error: workshopsError, ref
|
||||
queryKey: ['workshops', isClient],
|
||||
queryFn: fetchWorkshopsFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
refetchInterval: 1000 * 60 * 30, // 30 minutes
|
||||
enabled: isClient,
|
||||
})
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
export function useCoursesZapsQuery({ event }) {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const [zaps, setZaps] = useState([]);
|
||||
const [zapsLoading, setZapsLoading] = useState(true);
|
||||
const [zapsError, setZapsError] = useState(null);
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isClient || !ndk || !event) return;
|
||||
|
||||
let subscription = null;
|
||||
let isSubscribed = true;
|
||||
|
||||
const fetchZapsFromNDK = async () => {
|
||||
try {
|
||||
await ndk.connect();
|
||||
const uniqueEvents = new Set();
|
||||
|
||||
const filters = [
|
||||
{ kinds: [9735], "#e": [event.id] },
|
||||
{ kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }
|
||||
];
|
||||
|
||||
subscription = ndk.subscribe(filters);
|
||||
|
||||
subscription.on('event', (zap) => {
|
||||
if (isSubscribed) {
|
||||
uniqueEvents.add(zap);
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
}
|
||||
});
|
||||
|
||||
subscription.on('eose', () => {
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
setZapsLoading(false);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
setZapsError('Error fetching zaps from NDK: ' + error);
|
||||
setZapsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchZapsFromNDK();
|
||||
|
||||
return () => {
|
||||
isSubscribed = false;
|
||||
if (subscription) {
|
||||
subscription.stop();
|
||||
}
|
||||
};
|
||||
}, [isClient, ndk, event]);
|
||||
|
||||
return { zaps, zapsLoading, zapsError };
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
export function useResourceZapsQuery({ event }) {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const [zaps, setZaps] = useState([]);
|
||||
const [zapsLoading, setZapsLoading] = useState(true);
|
||||
const [zapsError, setZapsError] = useState(null);
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isClient || !ndk || !event) return;
|
||||
|
||||
let subscription = null;
|
||||
let isSubscribed = true;
|
||||
|
||||
const fetchZapsFromNDK = async () => {
|
||||
try {
|
||||
await ndk.connect();
|
||||
const uniqueEvents = new Set();
|
||||
|
||||
const filters = [
|
||||
{ kinds: [9735], "#e": [event.id] },
|
||||
{ kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }
|
||||
];
|
||||
|
||||
subscription = ndk.subscribe(filters);
|
||||
|
||||
subscription.on('event', (zap) => {
|
||||
if (isSubscribed) {
|
||||
uniqueEvents.add(zap);
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
}
|
||||
});
|
||||
|
||||
subscription.on('eose', () => {
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
setZapsLoading(false);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
setZapsError('Error fetching zaps from NDK: ' + error);
|
||||
setZapsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchZapsFromNDK();
|
||||
|
||||
return () => {
|
||||
isSubscribed = false;
|
||||
if (subscription) {
|
||||
subscription.stop();
|
||||
}
|
||||
};
|
||||
}, [isClient, ndk, event]);
|
||||
|
||||
return { zaps, zapsLoading, zapsError };
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
export function useWorkshopsZapsQuery({ event }) {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const [zaps, setZaps] = useState([]);
|
||||
const [zapsLoading, setZapsLoading] = useState(true);
|
||||
const [zapsError, setZapsError] = useState(null);
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isClient || !ndk || !event) return;
|
||||
|
||||
let subscription = null;
|
||||
let isSubscribed = true;
|
||||
|
||||
const fetchZapsFromNDK = async () => {
|
||||
try {
|
||||
await ndk.connect();
|
||||
const uniqueEvents = new Set();
|
||||
|
||||
const filters = [
|
||||
{ kinds: [9735], "#e": [event.id] },
|
||||
{ kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }
|
||||
];
|
||||
|
||||
subscription = ndk.subscribe(filters);
|
||||
|
||||
subscription.on('event', (zap) => {
|
||||
if (isSubscribed) {
|
||||
uniqueEvents.add(zap);
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
}
|
||||
});
|
||||
|
||||
subscription.on('eose', () => {
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
setZapsLoading(false);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
setZapsError('Error fetching zaps from NDK: ' + error);
|
||||
setZapsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchZapsFromNDK();
|
||||
|
||||
return () => {
|
||||
isSubscribed = false;
|
||||
if (subscription) {
|
||||
subscription.stop();
|
||||
}
|
||||
};
|
||||
}, [isClient, ndk, event]);
|
||||
|
||||
return { zaps, zapsLoading, zapsError };
|
||||
}
|
39
src/hooks/nostrQueries/zaps/useZapsQuery.js
Normal file
39
src/hooks/nostrQueries/zaps/useZapsQuery.js
Normal file
@ -0,0 +1,39 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
export function useZapsQuery({ event, type }) {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
const fetchZaps = async (event) => {
|
||||
try {
|
||||
await ndk.connect();
|
||||
|
||||
const filters = [
|
||||
{ kinds: [9735], "#e": [event.id] },
|
||||
{ kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }
|
||||
];
|
||||
|
||||
const events = await ndk.fetchEvents(filters, { closeOnEose: true });
|
||||
return events;
|
||||
} catch (error) {
|
||||
console.error('Error fetching zaps from NDK:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const { data: zaps, isLoading: zapsLoading, error: zapsError, refetch: refetchZaps } = useQuery({
|
||||
queryKey: ['zaps', isClient, event, type],
|
||||
queryFn: () => fetchZaps(event),
|
||||
staleTime: 10000, // 10 seconds
|
||||
refetchInterval: 10000, // 10 seconds
|
||||
enabled: isClient,
|
||||
})
|
||||
|
||||
return { zaps, zapsLoading, zapsError, refetchZaps }
|
||||
}
|
@ -34,6 +34,7 @@ export function useZapsSubscription({ event }) {
|
||||
if (isSubscribed) {
|
||||
uniqueEvents.add(zap);
|
||||
setZaps(Array.from(uniqueEvents));
|
||||
setZapsLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -38,7 +38,7 @@ export default function Details() {
|
||||
const ndk = useNDKContext();
|
||||
const [user] = useLocalStorageWithEffect('user', {});
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { zaps, zapsError } = useZapsSubscription({ event: processedEvent });
|
||||
const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@ -105,8 +105,8 @@ export default function Details() {
|
||||
|
||||
useEffect(() => {
|
||||
if (event) {
|
||||
const { id, pubkey, content, title, summary, image, published_at, d, topics } = parseEvent(event);
|
||||
setProcessedEvent({ id, pubkey, content, title, summary, image, published_at, d, topics });
|
||||
const parsedEvent = parseEvent(event);
|
||||
setProcessedEvent(parsedEvent);
|
||||
}
|
||||
}, [event]);
|
||||
|
||||
@ -184,7 +184,7 @@ export default function Details() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-full flex justify-end">
|
||||
<ZapDisplay zapAmount={zapAmount} event={processedEvent} />
|
||||
<ZapDisplay zapAmount={zapAmount} event={processedEvent} zapsLoading={zapsLoading} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -29,5 +29,8 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
plugins: [
|
||||
require('@tailwindcss/typography'),
|
||||
// ...
|
||||
],
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user