From ec8b740c40b72ae03fe946a71ed44b8d4d04e1d9 Mon Sep 17 00:00:00 2001 From: austinkelsay Date: Mon, 26 Aug 2024 17:33:26 -0500 Subject: [PATCH] Made nostr queries for content without using useQuery and it is faster so I'm using that for right now --- .../content/carousels/CoursesCarousel.js | 4 +- .../content/carousels/ResourcesCarousel.js | 4 +- .../content/carousels/WorkshopsCarousel.js | 4 +- src/components/forms/course/CourseForm.js | 8 +-- src/components/forms/course/LessonSelector.js | 2 +- src/components/profile/UserContent.js | 12 ++-- src/hooks/nostr/useCourses.js | 68 ++++++++++++++++++ src/hooks/nostr/useResources.js | 69 +++++++++++++++++++ src/hooks/nostr/useWorkshops.js | 69 +++++++++++++++++++ 9 files changed, 223 insertions(+), 17 deletions(-) create mode 100644 src/hooks/nostr/useCourses.js create mode 100644 src/hooks/nostr/useResources.js create mode 100644 src/hooks/nostr/useWorkshops.js diff --git a/src/components/content/carousels/CoursesCarousel.js b/src/components/content/carousels/CoursesCarousel.js index d4289c8..4eda6bd 100644 --- a/src/components/content/carousels/CoursesCarousel.js +++ b/src/components/content/carousels/CoursesCarousel.js @@ -3,7 +3,7 @@ import { Carousel } from 'primereact/carousel'; import { parseCourseEvent } from '@/utils/nostr'; import CourseTemplate from '@/components/content/carousels/templates/CourseTemplate'; import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; -import { useCoursesQuery } from '@/hooks/nostrQueries/content/useCoursesQuery'; +import { useCourses } from '@/hooks/nostr/useCourses'; const responsiveOptions = [ { @@ -25,7 +25,7 @@ const responsiveOptions = [ export default function CoursesCarousel() { const [processedCourses, setProcessedCourses] = useState([]); - const { courses, coursesLoading, coursesError, refetchCourses } = useCoursesQuery() + const { courses, coursesLoading, coursesError } = useCourses() useEffect(() => { const fetch = async () => { diff --git a/src/components/content/carousels/ResourcesCarousel.js b/src/components/content/carousels/ResourcesCarousel.js index 6977fdd..fe755de 100644 --- a/src/components/content/carousels/ResourcesCarousel.js +++ b/src/components/content/carousels/ResourcesCarousel.js @@ -3,7 +3,7 @@ import { Carousel } from 'primereact/carousel'; import { parseEvent } from '@/utils/nostr'; import ResourceTemplate from '@/components/content/carousels/templates/ResourceTemplate'; import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; -import { useResourcesQuery } from '@/hooks/nostrQueries/content/useResourcesQuery'; +import { useResources } from '@/hooks/nostr/useResources'; const responsiveOptions = [ { @@ -25,7 +25,7 @@ const responsiveOptions = [ export default function ResourcesCarousel() { const [processedResources, setProcessedResources] = useState([]); - const { resources, resourcesLoading, resourcesError, refetchResources } = useResourcesQuery() + const { resources, resourcesLoading, resourcesError } = useResources() useEffect(() => { const fetch = async () => { diff --git a/src/components/content/carousels/WorkshopsCarousel.js b/src/components/content/carousels/WorkshopsCarousel.js index f907475..640e741 100644 --- a/src/components/content/carousels/WorkshopsCarousel.js +++ b/src/components/content/carousels/WorkshopsCarousel.js @@ -3,7 +3,7 @@ import { Carousel } from 'primereact/carousel'; import { parseEvent } from '@/utils/nostr'; import WorkshopTemplate from '@/components/content/carousels/templates/WorkshopTemplate'; import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; -import { useWorkshopsQuery } from '@/hooks/nostrQueries/content/useWorkshopsQuery'; +import { useWorkshops } from '@/hooks/nostr/useWorkshops'; const responsiveOptions = [ { @@ -25,7 +25,7 @@ const responsiveOptions = [ export default function WorkshopsCarousel() { const [processedWorkshops, setProcessedWorkshops] = useState([]); - const { workshops, workshopsLoading, workshopsError, refetchWorkshops } = useWorkshopsQuery(); + const { workshops, workshopsLoading, workshopsError } = useWorkshops(); useEffect(() => { const fetch = async () => { diff --git a/src/components/forms/course/CourseForm.js b/src/components/forms/course/CourseForm.js index 129d281..25ee373 100644 --- a/src/components/forms/course/CourseForm.js +++ b/src/components/forms/course/CourseForm.js @@ -8,9 +8,9 @@ import { useSession } from 'next-auth/react'; import { useRouter } from 'next/router'; import { useToast } from '@/hooks/useToast'; import { parseEvent } from '@/utils/nostr'; -import { useResourcesQuery } from '@/hooks/nostrQueries/content/useResourcesQuery'; -import { useWorkshopsQuery } from '@/hooks/nostrQueries/content/useWorkshopsQuery'; import { useDraftsQuery } from '@/hooks/apiQueries/useDraftsQuery'; +import { useResources } from '@/hooks/nostr/useResources'; +import { useWorkshops } from '@/hooks/nostr/useWorkshops'; import axios from 'axios'; import LessonSelector from './LessonSelector'; @@ -27,8 +27,8 @@ const CourseForm = ({ draft = null }) => { const { data: session } = useSession(); const router = useRouter(); const { showToast } = useToast(); - const { resources, resourcesLoading, resourcesError } = useResourcesQuery(); - const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery(); + const { resources, resourcesLoading, resourcesError } = useResources(); + const { workshops, workshopsLoading, workshopsError } = useWorkshops(); const { drafts, draftsLoading, draftsError } = useDraftsQuery(); useEffect(() => { diff --git a/src/components/forms/course/LessonSelector.js b/src/components/forms/course/LessonSelector.js index 4f915e2..6d5fe7b 100644 --- a/src/components/forms/course/LessonSelector.js +++ b/src/components/forms/course/LessonSelector.js @@ -4,7 +4,7 @@ import { Button } from 'primereact/button'; import { Dialog } from 'primereact/dialog'; import { Accordion, AccordionTab } from 'primereact/accordion'; import EmbeddedResourceForm from '@/components/forms/course/embedded/EmbeddedResourceForm'; -import EmbeddedWorkshopForm from '@/components/forms/course/embedded/EmbeddedWorkshopform'; +import EmbeddedWorkshopForm from '@/components/forms/course/embedded/EmbeddedWorkshopForm'; import ContentDropdownItem from '@/components/content/dropdowns/ContentDropdownItem'; import SelectedContentItem from '@/components/content/SelectedContentItem'; import { parseEvent } from '@/utils/nostr'; diff --git a/src/components/profile/UserContent.js b/src/components/profile/UserContent.js index bbf0bdb..fdf8b7d 100644 --- a/src/components/profile/UserContent.js +++ b/src/components/profile/UserContent.js @@ -2,9 +2,9 @@ import React, { useState, useEffect } from "react"; import { useRouter } from "next/router"; import { Button } from "primereact/button"; import MenuTab from "@/components/menutab/MenuTab"; -import { useCoursesQuery } from "@/hooks/nostrQueries/content/useCoursesQuery"; -import { useResourcesQuery } from "@/hooks/nostrQueries/content/useResourcesQuery"; -import { useWorkshopsQuery } from "@/hooks/nostrQueries/content/useWorkshopsQuery"; +import { useCourses } from "@/hooks/nostr/useCourses"; +import { useResources } from "@/hooks/nostr/useResources"; +import { useWorkshops } from "@/hooks/nostr/useWorkshops"; import { useDraftsQuery } from "@/hooks/apiQueries/useDraftsQuery"; import { useCourseDraftsQuery } from "@/hooks/apiQueries/useCourseDraftsQuery"; import { useContentIdsQuery } from "@/hooks/apiQueries/useContentIdsQuery"; @@ -27,9 +27,9 @@ const UserContent = () => { const router = useRouter(); const { showToast } = useToast(); const {ndk, addSigner} = useNDKContext(); - const { courses, coursesLoading, coursesError } = useCoursesQuery(); - const { resources, resourcesLoading, resourcesError } = useResourcesQuery(); - const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery(); + const { courses, coursesLoading, coursesError } = useCourses(); + const { resources, resourcesLoading, resourcesError } = useResources(); + const { workshops, workshopsLoading, workshopsError } = useWorkshops(); const { courseDrafts, courseDraftsLoading, courseDraftsError } = useCourseDraftsQuery(); const { drafts, draftsLoading, draftsError } = useDraftsQuery(); const { contentIds, contentIdsLoading, contentIdsError, refetchContentIds } = useContentIdsQuery(); diff --git a/src/hooks/nostr/useCourses.js b/src/hooks/nostr/useCourses.js new file mode 100644 index 0000000..d0adc5f --- /dev/null +++ b/src/hooks/nostr/useCourses.js @@ -0,0 +1,68 @@ +import { useState, useEffect } from 'react'; +import { useNDKContext } from '@/context/NDKContext'; +import { useContentIdsQuery } from '@/hooks/apiQueries/useContentIdsQuery'; + +const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY; + +export function useCourses() { + const [isClient, setIsClient] = useState(false); + const [courses, setCourses] = useState(); + + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const { contentIds } = useContentIdsQuery() + const {ndk, addSigner} = useNDKContext(); + + useEffect(() => { + setIsClient(true); + }, []); + + const hasRequiredProperties = (event, contentIds) => { + const hasId = event.tags.some(([tag, value]) => tag === "d" && contentIds.includes(value)); + return hasId; + }; + + const fetchCoursesFromNDK = async () => { + setIsLoading(true); + setError(null); + try { + if (!contentIds || contentIds.length === 0) { + console.log('No content IDs found'); + setIsLoading(false); + return []; // Return early if no content IDs are found + } + + await ndk.connect(); + + const filter = { kinds: [30004], authors: [AUTHOR_PUBKEY] }; + const events = await ndk.fetchEvents(filter); + + if (events && events.size > 0) { + const eventsArray = Array.from(events); + const courses = eventsArray.filter(event => hasRequiredProperties(event, contentIds)); + setIsLoading(false); + return courses; + } + setIsLoading(false); + return []; + } catch (error) { + console.error('Error fetching courses from NDK:', error); + setError(error); + setIsLoading(false); + return []; + } + }; + + useEffect(() => { + if (isClient && contentIds) { + fetchCoursesFromNDK().then(fetchedCourses => { + if (fetchedCourses && fetchedCourses.length > 0) { + setCourses(fetchedCourses); + } + }); + } + }, [isClient, contentIds]); + + return { courses, isLoading, error }; +} \ No newline at end of file diff --git a/src/hooks/nostr/useResources.js b/src/hooks/nostr/useResources.js new file mode 100644 index 0000000..bf28925 --- /dev/null +++ b/src/hooks/nostr/useResources.js @@ -0,0 +1,69 @@ +import { useState, useEffect } from 'react'; +import { useNDKContext } from '@/context/NDKContext'; +import { useContentIdsQuery } from '@/hooks/apiQueries/useContentIdsQuery'; + +const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY; + +export function useResources() { + const [isClient, setIsClient] = useState(false); + const [resources, setResources] = useState(); + // Add new state variables for loading and error + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const { contentIds } = useContentIdsQuery() + const {ndk, addSigner} = useNDKContext(); + + useEffect(() => { + setIsClient(true); + }, []); + + const hasRequiredProperties = (event, contentIds) => { + const hasResource = event.tags.some(([tag, value]) => tag === "t" && value === "resource"); + const hasId = event.tags.some(([tag, value]) => tag === "d" && contentIds.includes(value)); + return hasResource && hasId; + }; + + const fetchResourcesFromNDK = async () => { + setIsLoading(true); + setError(null); + try { + if (!contentIds || contentIds.length === 0) { + console.log('No content IDs found'); + setIsLoading(false); + return []; // Return early if no content IDs are found + } + + await ndk.connect(); + + const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }; + const events = await ndk.fetchEvents(filter); + + if (events && events.size > 0) { + const eventsArray = Array.from(events); + const resources = eventsArray.filter(event => hasRequiredProperties(event, contentIds)); + setIsLoading(false); + return resources; + } + setIsLoading(false); + return []; + } catch (error) { + console.error('Error fetching resources from NDK:', error); + setError(error); + setIsLoading(false); + return []; + } + }; + + useEffect(() => { + if (isClient && contentIds) { + fetchResourcesFromNDK().then(fetchedResources => { + if (fetchedResources && fetchedResources.length > 0) { + setResources(fetchedResources); + } + }); + } + }, [isClient, contentIds]); + + return { resources, isLoading, error }; +} \ No newline at end of file diff --git a/src/hooks/nostr/useWorkshops.js b/src/hooks/nostr/useWorkshops.js new file mode 100644 index 0000000..63065bf --- /dev/null +++ b/src/hooks/nostr/useWorkshops.js @@ -0,0 +1,69 @@ +import { useState, useEffect } from 'react'; +import { useNDKContext } from '@/context/NDKContext'; +import { useContentIdsQuery } from '@/hooks/apiQueries/useContentIdsQuery'; + +const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY; + +export function useWorkshops() { + const [isClient, setIsClient] = useState(false); + const [workshops, setWorkshops] = useState(); + // Add new state variables for loading and error + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const { contentIds } = useContentIdsQuery() + const {ndk, addSigner} = useNDKContext(); + + useEffect(() => { + setIsClient(true); + }, []); + + const hasRequiredProperties = (event, contentIds) => { + const hasWorkshop = event.tags.some(([tag, value]) => tag === "t" && value === "workshop"); + const hasId = event.tags.some(([tag, value]) => tag === "d" && contentIds.includes(value)); + return hasWorkshop && hasId; + }; + + const fetchWorkshopsFromNDK = async () => { + setIsLoading(true); + setError(null); + try { + if (!contentIds || contentIds.length === 0) { + console.log('No content IDs found'); + setIsLoading(false); + return []; // Return early if no content IDs are found + } + + await ndk.connect(); + + const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }; + const events = await ndk.fetchEvents(filter); + + if (events && events.size > 0) { + const eventsArray = Array.from(events); + const workshops = eventsArray.filter(event => hasRequiredProperties(event, contentIds)); + setIsLoading(false); + return workshops; + } + setIsLoading(false); + return []; + } catch (error) { + console.error('Error fetching workshops from NDK:', error); + setError(error); + setIsLoading(false); + return []; + } + }; + + useEffect(() => { + if (isClient && contentIds) { + fetchWorkshopsFromNDK().then(fetchedWorkshops => { + if (fetchedWorkshops && fetchedWorkshops.length > 0) { + setWorkshops(fetchedWorkshops); + } + }); + } + }, [isClient, contentIds]); + + return { workshops, isLoading, error }; +} \ No newline at end of file