diff --git a/src/components/content/courses/CourseDetails.js b/src/components/content/courses/CourseDetails.js
index be4b154..26a8bf0 100644
--- a/src/components/content/courses/CourseDetails.js
+++ b/src/components/content/courses/CourseDetails.js
@@ -38,7 +38,7 @@ export default function CourseDetails({ processedEvent }) {
const { returnImageProxy } = useImageProxy();
const { data: session, status } = useSession();
const router = useRouter();
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
if (session) {
diff --git a/src/components/content/courses/DraftCourseDetails.js b/src/components/content/courses/DraftCourseDetails.js
index 12ee3b5..0b4125b 100644
--- a/src/components/content/courses/DraftCourseDetails.js
+++ b/src/components/content/courses/DraftCourseDetails.js
@@ -29,7 +29,7 @@ export default function DraftCourseDetails({ processedEvent, lessons }) {
const { returnImageProxy } = useImageProxy();
const { data: session, status } = useSession();
const router = useRouter();
- const ndk = useNDKContext();
+ const { ndk, addSigner } = useNDKContext();
const fetchAuthor = useCallback(async (pubkey) => {
if (!pubkey) return;
@@ -64,6 +64,10 @@ export default function DraftCourseDetails({ processedEvent, lessons }) {
const processedLessons = [];
try {
+ // Step 0: Add signer if not already added
+ if (!ndk.signer) {
+ await addSigner();
+ }
// Step 1: Process lessons
for (const lesson of lessons) {
processedLessons.push({
diff --git a/src/components/forms/CourseForm.js b/src/components/forms/CourseForm.js
index 0a54f8a..b1c1c64 100644
--- a/src/components/forms/CourseForm.js
+++ b/src/components/forms/CourseForm.js
@@ -34,7 +34,7 @@ const CourseForm = () => {
const { drafts, draftsLoading, draftsError } = useDraftsQuery();
const { data: session, status } = useSession();
const [user, setUser] = useState(null);
- const ndk = useNDKContext();
+ const { ndk, addSigner } = useNDKContext();
const router = useRouter();
const { showToast } = useToast();
@@ -51,6 +51,10 @@ const CourseForm = () => {
const handleDraftSubmit = async (e) => {
e.preventDefault();
+ if (!ndk.signer) {
+ await addSigner();
+ }
+
// Prepare the lessons from selected lessons
const resources = await Promise.all(selectedLessons.map(async (lesson) => {
// if .type is present than this lesson is a draft we need to publish
diff --git a/src/components/forms/ResourceForm.js b/src/components/forms/ResourceForm.js
index b7d95bd..73aa42f 100644
--- a/src/components/forms/ResourceForm.js
+++ b/src/components/forms/ResourceForm.js
@@ -31,7 +31,7 @@ const ResourceForm = ({ draft = null, isPublished = false }) => {
const { data: session, status } = useSession();
const { showToast } = useToast();
const router = useRouter();
- const ndk = useNDKContext();
+ const { ndk, addSigner } = useNDKContext();
useEffect(() => {
console.log('isPublished', isPublished);
@@ -108,6 +108,10 @@ const ResourceForm = ({ draft = null, isPublished = false }) => {
console.log('event', event);
try {
+ if (!ndk.signer) {
+ await addSigner();
+ }
+
await ndk.connect();
const published = await ndk.publish(event);
diff --git a/src/components/navbar/Navbar.js b/src/components/navbar/Navbar.js
index 5b18cf7..f4c2539 100644
--- a/src/components/navbar/Navbar.js
+++ b/src/components/navbar/Navbar.js
@@ -73,7 +73,7 @@ const Navbar = () => {
onClick={(e) => menu.current.toggle(e)}>
*/}
- router.push('/')} className="flex flex-row items-center justify-center cursor-pointer">
+
router.push('/').then(() => window.location.reload())} className="flex flex-row items-center justify-center cursor-pointer">
{
const menu = useRef(null);
- const handleLogout = () => {
- signOut();
+ const handleLogout = async () => {
+ await signOut({ redirect: false }); // Wait for the sign-out to complete
router.push('/').then(() => window.location.reload());
}
diff --git a/src/components/profile/PurchasedListItem.js b/src/components/profile/PurchasedListItem.js
new file mode 100644
index 0000000..1148e11
--- /dev/null
+++ b/src/components/profile/PurchasedListItem.js
@@ -0,0 +1,30 @@
+import React, { useEffect, useState } from "react";
+import { useNDKContext } from "@/context/NDKContext";
+import { parseEvent } from "@/utils/nostr";
+import { ProgressSpinner } from "primereact/progressspinner";
+
+const PurchasedListItem = ({ eventId, category }) => {
+ const { ndk } = useNDKContext();
+ const [event, setEvent] = useState(null);
+
+ useEffect(() => {
+ const fetchEvent = async () => {
+ if (!eventId) return;
+
+ try {
+ await ndk.connect();
+ const event = await ndk.fetchEvent(eventId);
+ if (event) {
+ setEvent(parseEvent(event));
+ }
+ } catch (error) {
+ console.error("Error fetching event:", error);
+ }
+ }
+ fetchEvent();
+ }, [eventId, ndk]);
+
+ return !event || !ndk ? : ({event.title});
+}
+
+export default PurchasedListItem;
\ No newline at end of file
diff --git a/src/components/profile/UserContent.js b/src/components/profile/UserContent.js
index 6950ed8..6f7962d 100644
--- a/src/components/profile/UserContent.js
+++ b/src/components/profile/UserContent.js
@@ -25,7 +25,7 @@ const UserContent = () => {
const [user, setUser] = useState(null);
const router = useRouter();
const { showToast } = useToast();
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
const { courses, coursesLoading, coursesError } = useCoursesQuery();
const { resources, resourcesLoading, resourcesError } = useResourcesQuery();
const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery();
diff --git a/src/components/zaps/ZapDisplay.js b/src/components/zaps/ZapDisplay.js
index f6cec51..fd53303 100644
--- a/src/components/zaps/ZapDisplay.js
+++ b/src/components/zaps/ZapDisplay.js
@@ -19,8 +19,8 @@ const ZapDisplay = ({ zapAmount, event, zapsLoading }) => {
return (
<>
op.current.toggle(e)}>
-
-
+
+
{zapsLoading || zapAmount === null || extraLoading ? (
) : (
diff --git a/src/context/NDKContext.js b/src/context/NDKContext.js
index 710a3d8..4b83678 100644
--- a/src/context/NDKContext.js
+++ b/src/context/NDKContext.js
@@ -4,31 +4,38 @@ import NDK, { NDKNip07Signer } from "@nostr-dev-kit/ndk";
const NDKContext = createContext(null);
const relayUrls = [
- "wss://nos.lol/",
- "wss://relay.damus.io/",
- "wss://relay.snort.social/",
- "wss://relay.nostr.band/",
- "wss://nostr.mutinywallet.com/",
- "wss://relay.mutinywallet.com/",
- "wss://relay.primal.net/"
+ "wss://nos.lol/",
+ "wss://relay.damus.io/",
+ "wss://relay.snort.social/",
+ "wss://relay.nostr.band/",
+ "wss://nostr.mutinywallet.com/",
+ "wss://relay.mutinywallet.com/",
+ "wss://relay.primal.net/"
];
export const NDKProvider = ({ children }) => {
- const [ndk, setNdk] = useState(null);
+ const [ndk, setNdk] = useState(null);
- useEffect(() => {
- const nip07signer = new NDKNip07Signer();
- const instance = new NDK({ explicitRelayUrls: relayUrls, signer: nip07signer });
- setNdk(instance);
- }, []);
+ useEffect(() => {
+ const instance = new NDK({ explicitRelayUrls: relayUrls });
+ setNdk(instance);
+ }, []);
- return (
-
- {children}
-
- );
+ const addSigner = async () => {
+ if (ndk) {
+ const nip07signer = new NDKNip07Signer();
+ await ndk.signer?.user();
+ ndk.signer = nip07signer;
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
};
export const useNDKContext = () => {
- return useContext(NDKContext);
-};
+ return useContext(NDKContext);
+};
\ No newline at end of file
diff --git a/src/hooks/nostrQueries/content/useAllContentQuery.js b/src/hooks/nostrQueries/content/useAllContentQuery.js
index 9ea7fcb..1526d07 100644
--- a/src/hooks/nostrQueries/content/useAllContentQuery.js
+++ b/src/hooks/nostrQueries/content/useAllContentQuery.js
@@ -4,7 +4,7 @@ import { useNDKContext } from '@/context/NDKContext';
export function useAllContentQuery({ids}) {
const [isClient, setIsClient] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
setIsClient(true);
diff --git a/src/hooks/nostrQueries/content/useCoursesQuery.js b/src/hooks/nostrQueries/content/useCoursesQuery.js
index 4bd55b1..52b2e03 100644
--- a/src/hooks/nostrQueries/content/useCoursesQuery.js
+++ b/src/hooks/nostrQueries/content/useCoursesQuery.js
@@ -7,7 +7,7 @@ const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY;
export function useCoursesQuery() {
const [isClient, setIsClient] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
setIsClient(true);
diff --git a/src/hooks/nostrQueries/content/useResourcesQuery.js b/src/hooks/nostrQueries/content/useResourcesQuery.js
index 4f3ba70..e536a1f 100644
--- a/src/hooks/nostrQueries/content/useResourcesQuery.js
+++ b/src/hooks/nostrQueries/content/useResourcesQuery.js
@@ -7,7 +7,7 @@ const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY;
export function useResourcesQuery() {
const [isClient, setIsClient] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
setIsClient(true);
diff --git a/src/hooks/nostrQueries/content/useWorkshopsQuery.js b/src/hooks/nostrQueries/content/useWorkshopsQuery.js
index af59866..91571a5 100644
--- a/src/hooks/nostrQueries/content/useWorkshopsQuery.js
+++ b/src/hooks/nostrQueries/content/useWorkshopsQuery.js
@@ -7,7 +7,7 @@ const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY;
export function useWorkshopsQuery() {
const [isClient, setIsClient] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
setIsClient(true);
diff --git a/src/hooks/nostrQueries/zaps/useZapsQuery.js b/src/hooks/nostrQueries/zaps/useZapsQuery.js
index d7aad8b..f20c153 100644
--- a/src/hooks/nostrQueries/zaps/useZapsQuery.js
+++ b/src/hooks/nostrQueries/zaps/useZapsQuery.js
@@ -4,7 +4,7 @@ import { useNDKContext } from '@/context/NDKContext';
export function useZapsQuery({ event, type }) {
const [isClient, setIsClient] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
setIsClient(true);
diff --git a/src/hooks/nostrQueries/zaps/useZapsSubscription.js b/src/hooks/nostrQueries/zaps/useZapsSubscription.js
index 93c73b3..60d4052 100644
--- a/src/hooks/nostrQueries/zaps/useZapsSubscription.js
+++ b/src/hooks/nostrQueries/zaps/useZapsSubscription.js
@@ -5,7 +5,7 @@ export function useZapsSubscription({event}) {
const [zaps, setZaps] = useState([]);
const [zapsLoading, setZapsLoading] = useState(true);
const [zapsError, setZapsError] = useState(null);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
useEffect(() => {
let subscription;
@@ -19,12 +19,9 @@ export function useZapsSubscription({event}) {
{ kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }
];
await ndk.connect();
- console.log("filters", filters);
subscription = ndk.subscribe(filters);
- subscription.on('event', (zapEvent) => {
- console.log("event", zapEvent);
-
+ subscription.on('event', (zapEvent) => {
// Check if we've already seen this zap
if (!zapIds.has(zapEvent.id)) {
zapIds.add(zapEvent.id);
diff --git a/src/pages/api/auth/[...nextauth].js b/src/pages/api/auth/[...nextauth].js
index f23a949..a853c1e 100644
--- a/src/pages/api/auth/[...nextauth].js
+++ b/src/pages/api/auth/[...nextauth].js
@@ -75,6 +75,7 @@ export default NextAuth({
],
callbacks: {
async jwt({ token, trigger, user }) {
+ console.log('TRIGGER', trigger);
if (trigger === "update") {
// if we trigger an update call the authorize function again
const newUser = await authorize(token.user.pubkey);
@@ -95,6 +96,12 @@ export default NextAuth({
async redirect({ url, baseUrl }) {
return baseUrl;
},
+ async signOut({ token, session }) {
+ console.log('signOut', token, session);
+ token = {}
+ session = {}
+ return true
+ },
},
secret: process.env.NEXTAUTH_SECRET,
session: { strategy: "jwt" },
diff --git a/src/pages/auth/signin.js b/src/pages/auth/signin.js
index 647d430..0a2e943 100644
--- a/src/pages/auth/signin.js
+++ b/src/pages/auth/signin.js
@@ -2,13 +2,14 @@ import { signIn, useSession } from "next-auth/react"
import { useState, useEffect } from "react"
import { useNDKContext } from "@/context/NDKContext";
import { Button } from 'primereact/button';
-import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";
export default function SignIn() {
const [email, setEmail] = useState("")
const [nostrPubkey, setNostrPubkey] = useState("")
const [nostrPrivkey, setNostrPrivkey] = useState("")
+ const {ndk, addSigner} = useNDKContext();
+
const { data: session, status } = useSession(); // Get the current session's data and status
useEffect(() => {
@@ -22,14 +23,14 @@ export default function SignIn() {
const handleNostrSignIn = async (e) => {
e.preventDefault()
-
- const nip07signer = new NDKNip07Signer();
- const ndk = new NDK({ signer: nip07signer });
- await ndk.connect()
+ if (!ndk.signer) {
+ await addSigner();
+ }
+
try {
- const user = await nip07signer.user()
+ const user = await ndk.signer.user()
const pubkey = user?._pubkey
signIn("nostr", { pubkey })
diff --git a/src/pages/course/[slug]/draft.js b/src/pages/course/[slug]/draft.js
index 22755d4..5188069 100644
--- a/src/pages/course/[slug]/draft.js
+++ b/src/pages/course/[slug]/draft.js
@@ -20,7 +20,7 @@ const DraftCourse = () => {
const [lessonsWithAuthors, setLessonsWithAuthors] = useState([]);
const router = useRouter();
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
const fetchAuthor = useCallback(async (pubkey) => {
if (!pubkey) return;
diff --git a/src/pages/course/[slug]/index.js b/src/pages/course/[slug]/index.js
index 19ef294..954a607 100644
--- a/src/pages/course/[slug]/index.js
+++ b/src/pages/course/[slug]/index.js
@@ -19,7 +19,7 @@ const Course = () => {
const [lessons, setLessons] = useState([]);
const router = useRouter();
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
const fetchAuthor = useCallback(async (pubkey) => {
const author = await ndk.getUser({ pubkey });
diff --git a/src/pages/details/[slug]/edit.js b/src/pages/details/[slug]/edit.js
index e265b7f..b5919ff 100644
--- a/src/pages/details/[slug]/edit.js
+++ b/src/pages/details/[slug]/edit.js
@@ -10,7 +10,7 @@ import { useToast } from "@/hooks/useToast";
export default function Edit() {
const [event, setEvent] = useState(null);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
const router = useRouter();
const { showToast } = useToast();
diff --git a/src/pages/details/[slug]/index.js b/src/pages/details/[slug]/index.js
index a9dae9e..1b8dd41 100644
--- a/src/pages/details/[slug]/index.js
+++ b/src/pages/details/[slug]/index.js
@@ -31,7 +31,7 @@ export default function Details() {
const [decryptedContent, setDecryptedContent] = useState(null);
const [authorView, setAuthorView] = useState(false);
- const ndk = useNDKContext();
+ const {ndk, addSigner} = useNDKContext();
const { data: session, update } = useSession();
const [user, setUser] = useState(null);
const { showToast } = useToast();
diff --git a/src/pages/draft/[slug]/index.js b/src/pages/draft/[slug]/index.js
index 1a8828d..2bae292 100644
--- a/src/pages/draft/[slug]/index.js
+++ b/src/pages/draft/[slug]/index.js
@@ -49,7 +49,7 @@ export default function Draft() {
const { width, height } = useResponsiveImageDimensions();
const router = useRouter();
const { showToast } = useToast();
- const ndk = useNDKContext();
+ const { ndk, addSigner } = useNDKContext();
useEffect(() => {
if (session) {
@@ -74,6 +74,10 @@ export default function Draft() {
const handleSubmit = async () => {
try {
+ if (!ndk.signer) {
+ await addSigner();
+ }
+
if (draft) {
const { unsignedEvent, type } = await buildEvent(draft);
diff --git a/src/pages/profile.js b/src/pages/profile.js
index 319f7b5..8dcacdb 100644
--- a/src/pages/profile.js
+++ b/src/pages/profile.js
@@ -5,6 +5,10 @@ import { Menu } from "primereact/menu";
import { Column } from "primereact/column";
import { useImageProxy } from "@/hooks/useImageProxy";
import { useSession } from 'next-auth/react';
+import { ProgressSpinner } from "primereact/progressspinner";
+import PurchasedListItem from "@/components/profile/PurchasedListItem";
+import { useNDKContext } from "@/context/NDKContext";
+import { formatDateTime } from "@/utils/time";
import UserContent from "@/components/profile/UserContent";
import Image from "next/image";
import BitcoinConnectButton from "@/components/bitcoinConnect/BitcoinConnect";
@@ -15,6 +19,7 @@ const Profile = () => {
const { data: session, status } = useSession();
const { returnImageProxy } = useImageProxy();
+ const { ndk } = useNDKContext();
const menu = useRef(null);
useEffect(() => {
@@ -33,8 +38,6 @@ const Profile = () => {
}
}, [session]);
- const purchases = [];
-
const menuItems = [
{
label: "Edit",
@@ -96,17 +99,28 @@ const Profile = () => {
/>
-
-
-
-
-
-
+ {!session || !session?.user || !ndk ? (
+
+ ) : (
+
+
+ {
+ console.log("rowData", rowData);
+ return
+ }}
+ header="Name"
+ >
+ item.courseId) ? "course" : "resource"} header="Category">
+ formatDateTime(rowData?.createdAt)} header="Date">
+
+
+ )}
)
diff --git a/src/utils/time.js b/src/utils/time.js
index e0cb53c..0abe0c7 100644
--- a/src/utils/time.js
+++ b/src/utils/time.js
@@ -3,6 +3,24 @@ export const formatUnixTimestamp = (time) => {
return date.toDateString();
}
+export const formatDateTime = (isoDate) => {
+ const date = new Date(isoDate);
+
+ // Example: Format to a more readable string
+ const formattedDate = date.toLocaleString("en-US", {
+ timeZone: "UTC", // Optional: You can change this to the user's time zone if needed
+ weekday: "long", // "long" for full name, "short" for abbreviated
+ year: "numeric",
+ month: "long", // "long" for full name, "short" for abbreviated
+ day: "numeric",
+ hour: "numeric",
+ minute: "numeric",
+ second: "numeric",
+ });
+
+ return formattedDate;
+}
+
export const formatTimestampToHowLongAgo = (time) => {
const date = new Date(time * 1000);
const now = new Date();