diff --git a/src/components/content/courses/CombinedLesson.js b/src/components/content/courses/CombinedLesson.js index 202e993..f026390 100644 --- a/src/components/content/courses/CombinedLesson.js +++ b/src/components/content/courses/CombinedLesson.js @@ -14,6 +14,7 @@ import useTrackVideoLesson from '@/hooks/tracking/useTrackVideoLesson'; import { Menu } from "primereact/menu"; import { Toast } from "primereact/toast"; import MoreOptionsMenu from "@/components/ui/MoreOptionsMenu"; +import { useSession } from "next-auth/react"; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -35,6 +36,7 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple const windowWidth = useWindowWidth(); const isMobileView = windowWidth <= 768; const isVideo = lesson?.type === 'video'; + const { data: session } = useSession(); const { isCompleted: videoCompleted, isTracking: videoTracking, markLessonAsCompleted } = useTrackVideoLesson({ lessonId: lesson?.d, @@ -45,46 +47,60 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple decryptionPerformed }); - const menuItems = [ - { - label: 'Mark as completed', - icon: 'pi pi-check-circle', - command: async () => { - try { - await markLessonAsCompleted(); - setCompleted(lesson.id); - toastRef.current.show({ - severity: 'success', - summary: 'Success', - detail: 'Lesson marked as completed', - life: 3000 - }); - } catch (error) { - console.error('Failed to mark lesson as completed:', error); - toastRef.current.show({ - severity: 'error', - summary: 'Error', - detail: 'Failed to mark lesson as completed', - life: 3000 - }); + const buildMenuItems = () => { + const items = []; + + const hasAccess = session?.user && ( + !isPaid || + decryptionPerformed || + session.user.role?.subscribed + ); + + if (hasAccess) { + items.push({ + label: 'Mark as completed', + icon: 'pi pi-check-circle', + command: async () => { + try { + await markLessonAsCompleted(); + setCompleted(lesson.id); + toastRef.current.show({ + severity: 'success', + summary: 'Success', + detail: 'Lesson marked as completed', + life: 3000 + }); + } catch (error) { + console.error('Failed to mark lesson as completed:', error); + toastRef.current.show({ + severity: 'error', + summary: 'Error', + detail: 'Failed to mark lesson as completed', + life: 3000 + }); + } } - } - }, - { + }); + } + + items.push({ label: 'Open lesson', icon: 'pi pi-arrow-up-right', command: () => { window.open(`/details/${lesson.id}`, '_blank'); } - }, - { + }); + + items.push({ label: 'View Nostr note', icon: 'pi pi-globe', command: () => { window.open(`https://habla.news/a/${nAddress}`, '_blank'); } - } - ]; + }); + + return items; + }; useEffect(() => { const handleYouTubeMessage = (event) => { @@ -270,7 +286,7 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
diff --git a/src/components/content/courses/CourseLesson.js b/src/components/content/courses/CourseLesson.js index ad8830b..34ba3a9 100644 --- a/src/components/content/courses/CourseLesson.js +++ b/src/components/content/courses/CourseLesson.js @@ -12,6 +12,7 @@ import useWindowWidth from "@/hooks/useWindowWidth"; import { nip19 } from "nostr-tools"; import appConfig from "@/config/appConfig"; import MoreOptionsMenu from "@/components/ui/MoreOptionsMenu"; +import { useSession } from "next-auth/react"; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -28,6 +29,7 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete const toastRef = useRef(null); const windowWidth = useWindowWidth(); const isMobileView = windowWidth <= 768; + const { data: session } = useSession(); const readTime = lesson?.content ? Math.max(30, Math.ceil(lesson.content.length / 20)) : 60; @@ -39,39 +41,51 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete decryptionPerformed }); - const menuItems = [ - { - label: 'Mark as completed', - icon: 'pi pi-check-circle', - command: async () => { - try { - await markLessonAsCompleted(); - setCompleted && setCompleted(lesson.id); - toastRef.current.show({ - severity: 'success', - summary: 'Success', - detail: 'Lesson marked as completed', - life: 3000 - }); - } catch (error) { - console.error('Failed to mark lesson as completed:', error); - toastRef.current.show({ - severity: 'error', - summary: 'Error', - detail: 'Failed to mark lesson as completed', - life: 3000 - }); + const buildMenuItems = () => { + const items = []; + + const hasAccess = session?.user && ( + !isPaid || + decryptionPerformed || + session.user.role?.subscribed + ); + + if (hasAccess) { + items.push({ + label: 'Mark as completed', + icon: 'pi pi-check-circle', + command: async () => { + try { + await markLessonAsCompleted(); + setCompleted && setCompleted(lesson.id); + toastRef.current.show({ + severity: 'success', + summary: 'Success', + detail: 'Lesson marked as completed', + life: 3000 + }); + } catch (error) { + console.error('Failed to mark lesson as completed:', error); + toastRef.current.show({ + severity: 'error', + summary: 'Error', + detail: 'Failed to mark lesson as completed', + life: 3000 + }); + } } - } - }, - { + }); + } + + items.push({ label: 'Open lesson', icon: 'pi pi-arrow-up-right', command: () => { window.open(`/details/${lesson.id}`, '_blank'); } - }, - { + }); + + items.push({ label: 'View Nostr note', icon: 'pi pi-globe', command: () => { @@ -85,10 +99,10 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete window.open(`https://habla.news/a/${addr}`, '_blank'); } } - } - ]; - - // Add additional links to menu items if they exist + }); + + return items; + }; useEffect(() => { if (!zaps || zapsLoading || zapsError) return; @@ -164,7 +178,7 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete
diff --git a/src/components/content/courses/DocumentLesson.js b/src/components/content/courses/DocumentLesson.js index 6919fa0..0e25f4e 100644 --- a/src/components/content/courses/DocumentLesson.js +++ b/src/components/content/courses/DocumentLesson.js @@ -13,6 +13,7 @@ import appConfig from "@/config/appConfig"; import useTrackDocumentLesson from "@/hooks/tracking/useTrackDocumentLesson"; import { Toast } from "primereact/toast"; import MoreOptionsMenu from "@/components/ui/MoreOptionsMenu"; +import { useSession } from "next-auth/react"; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -32,6 +33,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple const toastRef = useRef(null); // todo implement real read time needs to be on form const readTime = 120; + const { data: session } = useSession(); const { isCompleted, isTracking, markLessonAsCompleted } = useTrackDocumentLesson({ lessonId: lesson?.d, @@ -41,46 +43,60 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple decryptionPerformed: decryptionPerformed, }); - const menuItems = [ - { - label: 'Mark as completed', - icon: 'pi pi-check-circle', - command: async () => { - try { - await markLessonAsCompleted(); - setCompleted && setCompleted(lesson.id); - toastRef.current.show({ - severity: 'success', - summary: 'Success', - detail: 'Lesson marked as completed', - life: 3000 - }); - } catch (error) { - console.error('Failed to mark lesson as completed:', error); - toastRef.current.show({ - severity: 'error', - summary: 'Error', - detail: 'Failed to mark lesson as completed', - life: 3000 - }); + const buildMenuItems = () => { + const items = []; + + const hasAccess = session?.user && ( + !isPaid || + decryptionPerformed || + session.user.role?.subscribed + ); + + if (hasAccess) { + items.push({ + label: 'Mark as completed', + icon: 'pi pi-check-circle', + command: async () => { + try { + await markLessonAsCompleted(); + setCompleted && setCompleted(lesson.id); + toastRef.current.show({ + severity: 'success', + summary: 'Success', + detail: 'Lesson marked as completed', + life: 3000 + }); + } catch (error) { + console.error('Failed to mark lesson as completed:', error); + toastRef.current.show({ + severity: 'error', + summary: 'Error', + detail: 'Failed to mark lesson as completed', + life: 3000 + }); + } } - } - }, - { + }); + } + + items.push({ label: 'Open lesson', icon: 'pi pi-arrow-up-right', command: () => { window.open(`/details/${lesson.id}`, '_blank'); } - }, - { + }); + + items.push({ label: 'View Nostr note', icon: 'pi pi-globe', command: () => { window.open(`https://habla.news/a/${nAddress}`, '_blank'); } - } - ]; + }); + + return items; + }; useEffect(() => { if (!zaps || zapsLoading || zapsError) return; @@ -183,7 +199,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
diff --git a/src/components/content/courses/VideoLesson.js b/src/components/content/courses/VideoLesson.js index 9086996..feb803b 100644 --- a/src/components/content/courses/VideoLesson.js +++ b/src/components/content/courses/VideoLesson.js @@ -13,6 +13,7 @@ import useWindowWidth from "@/hooks/useWindowWidth"; import useTrackVideoLesson from '@/hooks/tracking/useTrackVideoLesson'; import { Toast } from "primereact/toast"; import MoreOptionsMenu from "@/components/ui/MoreOptionsMenu"; +import { useSession } from "next-auth/react"; const MDDisplay = dynamic( () => import("@uiw/react-markdown-preview"), @@ -33,6 +34,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted const mdDisplayRef = useRef(null); const menuRef = useRef(null); const toastRef = useRef(null); + const { data: session } = useSession(); const { isCompleted, isTracking, markLessonAsCompleted } = useTrackVideoLesson({ lessonId: lesson?.d, @@ -43,46 +45,60 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted decryptionPerformed }); - const menuItems = [ - { - label: 'Mark as completed', - icon: 'pi pi-check-circle', - command: async () => { - try { - await markLessonAsCompleted(); - setCompleted(lesson.id); - toastRef.current.show({ - severity: 'success', - summary: 'Success', - detail: 'Lesson marked as completed', - life: 3000 - }); - } catch (error) { - console.error('Failed to mark lesson as completed:', error); - toastRef.current.show({ - severity: 'error', - summary: 'Error', - detail: 'Failed to mark lesson as completed', - life: 3000 - }); + const buildMenuItems = () => { + const items = []; + + const hasAccess = session?.user && ( + !isPaid || + decryptionPerformed || + session.user.role?.subscribed + ); + + if (hasAccess) { + items.push({ + label: 'Mark as completed', + icon: 'pi pi-check-circle', + command: async () => { + try { + await markLessonAsCompleted(); + setCompleted(lesson.id); + toastRef.current.show({ + severity: 'success', + summary: 'Success', + detail: 'Lesson marked as completed', + life: 3000 + }); + } catch (error) { + console.error('Failed to mark lesson as completed:', error); + toastRef.current.show({ + severity: 'error', + summary: 'Error', + detail: 'Failed to mark lesson as completed', + life: 3000 + }); + } } - } - }, - { + }); + } + + items.push({ label: 'Open lesson', icon: 'pi pi-arrow-up-right', command: () => { window.open(`/details/${lesson.id}`, '_blank'); } - }, - { + }); + + items.push({ label: 'View Nostr note', icon: 'pi pi-globe', command: () => { window.open(`https://habla.news/a/${nAddress}`, '_blank'); } - } - ]; + }); + + return items; + }; useEffect(() => { const handleYouTubeMessage = (event) => { @@ -239,7 +255,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted
diff --git a/src/components/content/documents/DocumentDetails.js b/src/components/content/documents/DocumentDetails.js index 491bb30..9d28be7 100644 --- a/src/components/content/documents/DocumentDetails.js +++ b/src/components/content/documents/DocumentDetails.js @@ -141,7 +141,7 @@ const DocumentDetails = ({ processedEvent, topics, title, summary, image, price, return (
-
+