diff --git a/src/components/bitcoinConnect/CoursePaymentButton.js b/src/components/bitcoinConnect/CoursePaymentButton.js index 463c3e4..d614881 100644 --- a/src/components/bitcoinConnect/CoursePaymentButton.js +++ b/src/components/bitcoinConnect/CoursePaymentButton.js @@ -6,6 +6,7 @@ import { initializeBitcoinConnect } from './BitcoinConnect'; import { LightningAddress } from '@getalby/lightning-tools'; import { useToast } from '@/hooks/useToast'; import { useSession } from 'next-auth/react'; +import { useRouter } from 'next/router'; import GenericButton from '@/components/buttons/GenericButton'; import axios from 'axios'; // Import axios for API calls @@ -20,19 +21,20 @@ const CoursePaymentButton = ({ lnAddress, amount, onSuccess, onError, courseId } const [invoice, setInvoice] = useState(null); const [userId, setUserId] = useState(null); const { showToast } = useToast(); - const { data: session } = useSession(); + const { data: session, status } = useSession(); const [dialogVisible, setDialogVisible] = useState(false); // New state for dialog visibility - - useEffect(() => { - if (session?.user) { - setUserId(session.user.id); - } - }, [session]); + const router = useRouter(); useEffect(() => { initializeBitcoinConnect(); }, []); + useEffect(() => { + if (session && session.user) { + setUserId(session.user.id); + } + }, [status, session]); + useEffect(() => { const fetchInvoice = async () => { try { @@ -78,17 +80,24 @@ const CoursePaymentButton = ({ lnAddress, amount, onSuccess, onError, courseId } return ( <> - setDialogVisible(true)} + { + if (status === 'unauthenticated') { + console.log('unauthenticated'); + router.push('/auth/signin'); + } else { + setDialogVisible(true); + } + }} disabled={!invoice} severity='primary' rounded icon='pi pi-wallet' className='text-[#f8f8ff] text-sm' /> - setDialogVisible(false)} header="Make Payment" style={{ width: '50vw' }} diff --git a/src/components/bitcoinConnect/ResourcePaymentButton.js b/src/components/bitcoinConnect/ResourcePaymentButton.js index 48de9d6..6ba70d7 100644 --- a/src/components/bitcoinConnect/ResourcePaymentButton.js +++ b/src/components/bitcoinConnect/ResourcePaymentButton.js @@ -8,6 +8,7 @@ import { useSession } from 'next-auth/react'; import { ProgressSpinner } from 'primereact/progressspinner'; import axios from 'axios'; import GenericButton from '@/components/buttons/GenericButton'; +import { useRouter } from 'next/router'; const Payment = dynamic( () => import('@getalby/bitcoin-connect-react').then((mod) => mod.Payment), @@ -18,19 +19,20 @@ const ResourcePaymentButton = ({ lnAddress, amount, onSuccess, onError, resource const [invoice, setInvoice] = useState(null); const [userId, setUserId] = useState(null); const { showToast } = useToast(); - const { data: session } = useSession(); + const { data: session, status } = useSession(); const [dialogVisible, setDialogVisible] = useState(false); - - useEffect(() => { - if (session?.user) { - setUserId(session.user.id); - } - }, [session]); + const router = useRouter(); useEffect(() => { initializeBitcoinConnect(); }, []); + useEffect(() => { + if (session && session.user) { + setUserId(session.user.id); + } + }, [status, session]); + useEffect(() => { const fetchInvoice = async () => { try { @@ -79,7 +81,14 @@ const ResourcePaymentButton = ({ lnAddress, amount, onSuccess, onError, resource setDialogVisible(true)} + onClick={() => { + if (status === 'unauthenticated') { + console.log('unauthenticated'); + router.push('/auth/signin'); + } else { + setDialogVisible(true); + } + }} disabled={!invoice} severity='primary' rounded diff --git a/src/components/bitcoinConnect/SubscriptionPaymentButton.js b/src/components/bitcoinConnect/SubscriptionPaymentButton.js index 27be3c9..1a3d941 100644 --- a/src/components/bitcoinConnect/SubscriptionPaymentButton.js +++ b/src/components/bitcoinConnect/SubscriptionPaymentButton.js @@ -24,7 +24,8 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio const [showRecurringOptions, setShowRecurringOptions] = useState(false); const [nwcInput, setNwcInput] = useState(''); const { showToast } = useToast(); - const { data: session } = useSession(); + const { data: session, status } = useSession(); + const router = useRouter(); const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS; const amount = 25; @@ -211,8 +212,13 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio label="Pay as you go" icon="pi pi-bolt" onClick={async () => { - const invoice = await fetchInvoice(); - setInvoice(invoice); + if (status === 'unauthenticated') { + console.log('unauthenticated'); + router.push('/auth/signin'); + } else { + const invoice = await fetchInvoice(); + setInvoice(invoice); + } }} severity='primary' className="w-fit mt-4 text-[#f8f8ff]" @@ -232,7 +238,14 @@ const SubscriptionPaymentButtons = ({ onSuccess, onError, onRecurringSubscriptio } severity='help' className="w-fit mt-4 text-[#f8f8ff] bg-purple-600" - onClick={() => setShowRecurringOptions(!showRecurringOptions)} + onClick={() => { + if (status === 'unauthenticated') { + console.log('unauthenticated'); + router.push('/auth/signin'); + } else { + setShowRecurringOptions(!showRecurringOptions); + } + }} /> )} diff --git a/src/components/content/courses/CourseDetails.js b/src/components/content/courses/CourseDetails.js index 3cd96a5..6a66376 100644 --- a/src/components/content/courses/CourseDetails.js +++ b/src/components/content/courses/CourseDetails.js @@ -17,6 +17,7 @@ import 'primeicons/primeicons.css'; import CoursePaymentButton from "@/components/bitcoinConnect/CoursePaymentButton"; import { ProgressSpinner } from 'primereact/progressspinner'; import { defaultRelayUrls } from "@/context/NDKContext"; +import useWindowWidth from '@/hooks/useWindowWidth'; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -35,6 +36,8 @@ export default function CourseDetails({ processedEvent, paidCourse, lessons, dec const { data: session, status } = useSession(); const router = useRouter(); const {ndk, addSigner} = useNDKContext(); + const windowWidth = useWindowWidth(); + const isMobileView = windowWidth <= 768; const lnAddress = process.env.NEXT_PUBLIC_LIGHTNING_ADDRESS; diff --git a/src/components/content/courses/CourseDetailsNew.js b/src/components/content/courses/CourseDetailsNew.js index b98246c..52385ca 100644 --- a/src/components/content/courses/CourseDetailsNew.js +++ b/src/components/content/courses/CourseDetailsNew.js @@ -29,6 +29,7 @@ export default function CourseDetailsNew({ processedEvent, paidCourse, lessons, const { data: session, status } = useSession(); const { showToast } = useToast(); const windowWidth = useWindowWidth(); + const isMobileView = windowWidth <= 768; const { ndk } = useNDKContext(); const fetchAuthor = useCallback(async (pubkey) => { @@ -134,7 +135,14 @@ export default function CourseDetailsNew({ processedEvent, paidCourse, lessons, )} -

{processedEvent.description}

+

{processedEvent.description && ( +

+ {processedEvent.description.split('\n').map((line, index) => ( +

{line}

+ ))} +
+ )} +

router.push(`/details/${processedEvent.id}/edit`)} label="Edit" severity='warning' outlined /> - window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip="View Nostr Event" tooltipOptions={{ position: 'right' }} /> + window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip={ isMobileView ? null : "View Nostr Event" } tooltipOptions={{ position: paidCourse ? 'left' : 'right' }} />
) : (
- window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip="View Nostr Event" tooltipOptions={{ position: paidCourse ? 'left' : 'right' }} /> + window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip={ isMobileView ? null : "View Nostr Event" } tooltipOptions={{ position: paidCourse ? 'left' : 'right' }} />
)}
diff --git a/src/components/content/courses/DocumentLesson.js b/src/components/content/courses/DocumentLesson.js index c001a9e..4c5b3bd 100644 --- a/src/components/content/courses/DocumentLesson.js +++ b/src/components/content/courses/DocumentLesson.js @@ -9,6 +9,7 @@ import { nip19 } from "nostr-tools"; import { Divider } from "primereact/divider"; import { getTotalFromZaps } from "@/utils/lightning"; import dynamic from "next/dynamic"; +import useWindowWidth from "@/hooks/useWindowWidth"; import { defaultRelayUrls } from "@/context/NDKContext"; const MDDisplay = dynamic( @@ -23,6 +24,8 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid }) => { const [nAddress, setNAddress] = useState(null); const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: lesson, type: "lesson" }); const { returnImageProxy } = useImageProxy(); + const windowWidth = useWindowWidth(); + const isMobileView = windowWidth <= 768; useEffect(() => { if (!zaps || zapsLoading || zapsError) return; @@ -119,7 +122,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid }) => {
['t', topic]), ['published_at', Math.floor(Date.now() / 1000).toString()], ...(draft?.price ? [['price', draft.price.toString()], ['location', `https://plebdevs.com/details/${draft.id}`]] : []), - ...(draft?.additionalLinks ? draft.additionalLinks.map(link => ['r', link]) : []), + ...(draft?.additionalLinks ? draft.additionalLinks.filter(link => link !== 'https://plebdevs.com').map(link => ['r', link]) : []), ]; type = 'document'; @@ -293,7 +293,7 @@ export default function DraftCourseDetails({ processedEvent, draftId, lessons }) ...draft.topics.map(topic => ['t', topic]), ['published_at', Math.floor(Date.now() / 1000).toString()], ...(draft?.price ? [['price', draft.price.toString()], ['location', `https://plebdevs.com/details/${draft.id}`]] : []), - ...(draft?.additionalLinks ? draft.additionalLinks.map(link => ['r', link]) : []), + ...(draft?.additionalLinks ? draft.additionalLinks.filter(link => link !== 'https://plebdevs.com').map(link => ['r', link]) : []), ]; type = 'video'; diff --git a/src/components/content/courses/VideoLesson.js b/src/components/content/courses/VideoLesson.js index 947e3ca..b0cc42c 100644 --- a/src/components/content/courses/VideoLesson.js +++ b/src/components/content/courses/VideoLesson.js @@ -10,6 +10,7 @@ import { getTotalFromZaps } from "@/utils/lightning"; import dynamic from "next/dynamic"; import { Divider } from "primereact/divider"; import { defaultRelayUrls } from "@/context/NDKContext"; +import useWindowWidth from "@/hooks/useWindowWidth"; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -23,6 +24,8 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid }) => { const [nAddress, setNAddress] = useState(null); const { zaps, zapsLoading, zapsError } = useZapsQuery({ event: lesson, type: "lesson" }); const { returnImageProxy } = useImageProxy(); + const windowWidth = useWindowWidth(); + const isMobileView = windowWidth <= 768; useEffect(() => { if (!zaps || zapsLoading || zapsError) return; @@ -130,7 +133,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid }) => {

{ if (zaps.length > 0) { @@ -172,7 +173,7 @@ const DocumentDetails = ({ processedEvent, topics, title, summary, image, price, router.push(`/details/${nAddress}/edit`)} label="Edit" severity='warning' outlined /> { if (zaps.length > 0) { @@ -165,11 +166,11 @@ const VideoDetails = ({ processedEvent, topics, title, summary, image, price, au
router.push(`/details/${nAddress}/edit`)} label="Edit" severity='warning' outlined /> - window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip="View Nostr Event" tooltipOptions={{ position: 'right' }} /> + window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip={ isMobileView ? null : "View Nostr Event" } tooltipOptions={{ position: 'right' }} />
) : (
- window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip="View Nostr Event" tooltipOptions={{ position: paidResource ? 'left' : 'right' }} /> + window.open(`https://nostr.band/${nAddress}`, '_blank')} tooltip={ isMobileView ? null : "View Nostr Event" } tooltipOptions={{ position: paidResource ? 'left' : 'right' }} />
)} diff --git a/src/components/feeds/messages/CommunityMessage.js b/src/components/feeds/messages/CommunityMessage.js index 169c669..284b7dc 100644 --- a/src/components/feeds/messages/CommunityMessage.js +++ b/src/components/feeds/messages/CommunityMessage.js @@ -10,6 +10,7 @@ import NostrIcon from '../../../../public/images/nostr.png'; import Image from 'next/image'; import { nip19 } from 'nostr-tools'; import ZapThreadsWrapper from '@/components/ZapThreadsWrapper'; +import useWindowWidth from '@/hooks/useWindowWidth'; const StackerNewsIconComponent = () => ( @@ -21,7 +22,7 @@ const StackerNewsIconComponent = () => ( const headerTemplate = (options, windowWidth, platform, id) => { return (
- + 768 ? `View in ${platform}` : null} icon="pi pi-external-link" @@ -39,6 +40,7 @@ const CommunityMessage = ({ message, searchQuery, windowWidth, platform }) => { const [npub, setNpub] = useState(null); const [collapsed, setCollapsed] = useState(true); const { data: session } = useSession(); + const isMobileView = windowWidth <= 768; useEffect(() => { if (session?.user?.pubkey) { diff --git a/src/components/forms/course/CourseForm.js b/src/components/forms/course/CourseForm.js index e1f1411..71c4ad0 100644 --- a/src/components/forms/course/CourseForm.js +++ b/src/components/forms/course/CourseForm.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { InputText } from 'primereact/inputtext'; +import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; import GenericButton from '@/components/buttons/GenericButton'; @@ -173,7 +174,7 @@ const CourseForm = ({ draft = null }) => { setTitle(e.target.value)} placeholder="Title" />
- setSummary(e.target.value)} placeholder="Summary" /> + setSummary(e.target.value)} placeholder="Summary" rows={5} cols={30} />
setCoverImage(e.target.value)} placeholder="Cover Image URL" /> diff --git a/src/pages/about.js b/src/pages/about.js index 91f554e..55150d5 100644 --- a/src/pages/about.js +++ b/src/pages/about.js @@ -3,9 +3,12 @@ import Image from 'next/image'; import NostrIcon from '../../public/images/nostr.png'; import { Tooltip } from 'primereact/tooltip'; import { useToast } from "@/hooks/useToast" +import useWindowWidth from "@/hooks/useWindowWidth"; const AboutPage = () => { const {showToast} = useToast() + const windowWidth = useWindowWidth(); + const isMobileView = windowWidth <= 768; const copyToClipboard = async (text) => { try { @@ -77,19 +80,19 @@ const AboutPage = () => {
- + - + - + Nostr - +

copyToClipboard("austin@bitcoinpleb.dev")} className='cursor-pointer'>

diff --git a/src/pages/draft/[slug]/index.js b/src/pages/draft/[slug]/index.js index 14ab0a9..c09b458 100644 --- a/src/pages/draft/[slug]/index.js +++ b/src/pages/draft/[slug]/index.js @@ -206,7 +206,7 @@ export default function Draft() { ...draft.topics.map(topic => ['t', topic]), ['published_at', Math.floor(Date.now() / 1000).toString()], ...(draft?.price ? [['price', draft.price.toString()], ['location', `https://plebdevs.com/details/${draft.id}`]] : []), - ...(draft?.additionalLinks ? draft.additionalLinks.map(link => ['r', link]) : []), + ...(draft?.additionalLinks ? draft.additionalLinks.filter(link => link !== 'https://plebdevs.com').map(link => ['r', link]) : []), ]; type = 'document'; @@ -243,7 +243,7 @@ export default function Draft() { ...draft.topics.map(topic => ['t', topic]), ['published_at', Math.floor(Date.now() / 1000).toString()], ...(draft?.price ? [['price', draft.price.toString()], ['location', `https://plebdevs.com/details/${draft.id}`]] : []), - ...(draft?.additionalLinks ? draft.additionalLinks.map(link => ['r', link]) : []), + ...(draft?.additionalLinks ? draft.additionalLinks.filter(link => link !== 'https://plebdevs.com').map(link => ['r', link]) : []), ]; type = 'video';