mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-06 01:02:04 +00:00
Standardized and improved payment messages on paid courses and resources
This commit is contained in:
parent
edcbb5fa52
commit
aaedada2ca
@ -58,6 +58,8 @@ const CoursePaymentButton = ({ lnAddress, amount, onSuccess, onError, courseId }
|
||||
amountPaid: parseInt(amount, 10)
|
||||
};
|
||||
|
||||
console.log('purchaseData', purchaseData);
|
||||
|
||||
const result = await axios.post('/api/purchase/course', purchaseData);
|
||||
|
||||
if (result.status === 200) {
|
||||
|
@ -4,8 +4,9 @@ import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import ZapDisplay from '@/components/zaps/ZapDisplay';
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { nip19, nip04 } from 'nostr-tools';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import GenericButton from '@/components/buttons/GenericButton';
|
||||
import Image from 'next/image';
|
||||
import dynamic from 'next/dynamic';
|
||||
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
||||
@ -36,26 +37,6 @@ export default function CourseDetails({ processedEvent, paidCourse, lessons, dec
|
||||
|
||||
const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS;
|
||||
|
||||
useEffect(() => {
|
||||
console.log("processedEvent", processedEvent);
|
||||
}, [processedEvent]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("lessons", lessons);
|
||||
}, [lessons]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("zaps", zaps);
|
||||
}, [zaps]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("paidCourse", paidCourse);
|
||||
}, [paidCourse]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("decryptionPerformed", decryptionPerformed);
|
||||
}, [decryptionPerformed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (session) {
|
||||
setUser(session.user);
|
||||
@ -96,6 +77,38 @@ export default function CourseDetails({ processedEvent, paidCourse, lessons, dec
|
||||
}
|
||||
}, [zaps, processedEvent]);
|
||||
|
||||
const renderPaymentMessage = () => {
|
||||
if (paidCourse && !decryptionPerformed) {
|
||||
return (
|
||||
<CoursePaymentButton
|
||||
lnAddress={lnAddress}
|
||||
amount={processedEvent.price}
|
||||
onSuccess={handlePaymentSuccess}
|
||||
onError={handlePaymentError}
|
||||
courseId={processedEvent.d}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const coursePurchased = session?.user?.purchased?.some(purchase =>
|
||||
purchase?.courseId === processedEvent.d
|
||||
);
|
||||
|
||||
if (paidCourse && decryptionPerformed && author && session?.user?.role?.subscribed && processedEvent?.pubkey !== session?.user?.pubkey) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`You are subscribed so you can access all paid content`} icon="pi pi-check" label="Subscribed" severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
if (paidCourse && author && processedEvent?.pubkey === session?.user?.pubkey) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`You created this paid course, users must pay ${processedEvent.price} sats to access it`} icon="pi pi-check" label={`Price ${processedEvent.price} sats`} severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
if (paidCourse && decryptionPerformed && author && coursePurchased) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`You have purchased this course`} icon="pi pi-check" label="Purchased" severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
if (!processedEvent || !author) {
|
||||
return (
|
||||
<div className="flex justify-center items-center h-screen">
|
||||
@ -146,21 +159,7 @@ export default function CourseDetails({ processedEvent, paidCourse, lessons, dec
|
||||
className="w-[344px] h-[194px] object-cover object-top rounded-lg"
|
||||
/>
|
||||
<div className='w-full flex justify-between items-center'>
|
||||
{paidCourse && !decryptionPerformed && (
|
||||
<CoursePaymentButton
|
||||
lnAddress={lnAddress}
|
||||
amount={processedEvent.price}
|
||||
onSuccess={handlePaymentSuccess}
|
||||
onError={handlePaymentError}
|
||||
resourceId={processedEvent.d}
|
||||
/>
|
||||
)}
|
||||
{paidCourse && decryptionPerformed && author && processedEvent?.pubkey !== session?.user?.pubkey && (
|
||||
<p className='text-green-500'>Paid {processedEvent.price} sats</p>
|
||||
)}
|
||||
{paidCourse && author && processedEvent?.pubkey === session?.user?.pubkey && (
|
||||
<p className='text-green-500'>Price {processedEvent.price} sats</p>
|
||||
)}
|
||||
{renderPaymentMessage()}
|
||||
<ZapDisplay
|
||||
zapAmount={zapAmount}
|
||||
event={processedEvent}
|
||||
|
@ -14,19 +14,11 @@ const MDDisplay = dynamic(
|
||||
}
|
||||
);
|
||||
|
||||
const CourseLesson = ({ lesson, course }) => {
|
||||
const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const [paidResource, setPaidResource] = useState(false);
|
||||
const [decryptedContent, setDecryptedContent] = useState(false);
|
||||
const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: lesson, type: "lesson" });
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
|
||||
useEffect(() => {
|
||||
if (course.price) {
|
||||
setPaidResource(true);
|
||||
}
|
||||
}, [course]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!zaps || zapsLoading || zapsError) return;
|
||||
|
||||
@ -36,10 +28,10 @@ const CourseLesson = ({ lesson, course }) => {
|
||||
}, [zaps, zapsLoading, zapsError, lesson]);
|
||||
|
||||
const renderContent = () => {
|
||||
if (decryptedContent) {
|
||||
return <MDDisplay className='p-4 rounded-lg w-full' source={decryptedContent} />;
|
||||
if (isPaid && decryptionPerformed) {
|
||||
return <MDDisplay className='p-4 rounded-lg w-full' source={lesson.content} />;
|
||||
}
|
||||
if (paidResource && !decryptedContent) {
|
||||
if (isPaid && !decryptionPerformed) {
|
||||
return <p className="text-center text-xl text-red-500">This content is paid and needs to be purchased before viewing.</p>;
|
||||
}
|
||||
if (lesson?.content) {
|
||||
|
@ -4,6 +4,7 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import ResourcePaymentButton from "@/components/bitcoinConnect/ResourcePaymentButton";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
import GenericButton from "@/components/buttons/GenericButton";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useZapsSubscription } from "@/hooks/nostrQueries/zaps/useZapsSubscription";
|
||||
import { getTotalFromZaps } from "@/utils/lightning";
|
||||
@ -26,6 +27,22 @@ const ResourceDetails = ({processedEvent, topics, title, summary, image, price,
|
||||
}
|
||||
}, [zaps, processedEvent]);
|
||||
|
||||
const renderPaymentMessage = () => {
|
||||
if (session?.user && session.user?.role?.subscribed && decryptedContent) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`You are subscribed so you can access all paid content`} icon="pi pi-check" label="Subscribed" severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
if (paidResource && decryptedContent && author && processedEvent?.pubkey !== session?.user?.pubkey && !session?.user?.role?.subscribed) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`Pay ${processedEvent.price} sats to access this content or subscribe to get access to all content`} icon="pi pi-check" label={`Paid ${processedEvent.price} sats`} severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
if (paidResource && author && processedEvent?.pubkey === session?.user?.pubkey) {
|
||||
return <GenericButton tooltipOptions={{position: 'top'}} tooltip={`You created this paid content, users must pay ${processedEvent.price} sats to access it`} icon="pi pi-check" label={`Price ${processedEvent.price} sats`} severity="success" outlined size="small" className="cursor-default hover:opacity-100 hover:bg-transparent focus:ring-0" />
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='w-full flex flex-row justify-between max-tab:flex-col max-mob:flex-col'>
|
||||
<i className='pi pi-arrow-left pr-8 cursor-pointer hover:opacity-75 max-tab:pl-2 max-tab:my-4' onClick={() => router.push('/')} />
|
||||
@ -76,11 +93,7 @@ const ResourceDetails = ({processedEvent, topics, title, summary, image, price,
|
||||
resourceId={processedEvent.d}
|
||||
/>}
|
||||
|
||||
{/* if the resource has been paid for show a green paid x sats text */}
|
||||
{paidResource && decryptedContent && author && !processedEvent?.pubkey === session?.user?.pubkey && <p className='text-green-500'>Paid {processedEvent.price} sats</p>}
|
||||
|
||||
{/* if this is the author of the resource show a zap button */}
|
||||
{paidResource && author && processedEvent?.pubkey === session?.user?.pubkey && <p className='text-green-500'>Price {processedEvent.price} sats</p>}
|
||||
{renderPaymentMessage()}
|
||||
|
||||
<ZapDisplay
|
||||
zapAmount={zapAmount}
|
||||
|
@ -129,6 +129,8 @@ const Course = () => {
|
||||
session.user?.role?.subscribed ||
|
||||
session.user?.pubkey === course?.pubkey;
|
||||
|
||||
console.log('canAccess', canAccess);
|
||||
|
||||
if (canAccess && lessons.length > 0) {
|
||||
try {
|
||||
const decryptedLessons = await Promise.all(lessons.map(async (lesson) => {
|
||||
@ -154,11 +156,12 @@ const Course = () => {
|
||||
}
|
||||
}, [course, lessons, paidCourse, decryptionPerformed]);
|
||||
|
||||
const handlePaymentSuccess = async (response, newCourse) => {
|
||||
const handlePaymentSuccess = async (response) => {
|
||||
if (response && response?.preimage) {
|
||||
console.log("newCourse", newCourse);
|
||||
const updated = await update();
|
||||
console.log("session after update", updated);
|
||||
showToast('success', 'Payment Success', 'You have successfully purchased this course');
|
||||
router.reload();
|
||||
} else {
|
||||
showToast('error', 'Error', 'Failed to purchase course. Please try again.');
|
||||
}
|
||||
@ -187,7 +190,7 @@ const Course = () => {
|
||||
handlePaymentError={handlePaymentError}
|
||||
/>
|
||||
{lessons.length > 0 && lessons.map((lesson, index) => (
|
||||
<CourseLesson key={index} lesson={lesson} course={course} />
|
||||
<CourseLesson key={index} lesson={lesson} course={course} decryptionPerformed={decryptionPerformed} isPaid={paidCourse} />
|
||||
))}
|
||||
<div className="mx-auto my-6">
|
||||
{course?.content && <MDDisplay className='p-4 rounded-lg' source={course.content} />}
|
||||
|
Loading…
x
Reference in New Issue
Block a user