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 (