diff --git a/src/components/content/carousels/CoursesCarousel.js b/src/components/content/carousels/CoursesCarousel.js index 1dc409e..d46abb1 100644 --- a/src/components/content/carousels/CoursesCarousel.js +++ b/src/components/content/carousels/CoursesCarousel.js @@ -3,6 +3,7 @@ import { Carousel } from 'primereact/carousel'; import { parseEvent } from '@/utils/nostr'; import { useNostr } from '@/hooks/useNostr'; import CourseTemplate from '@/components/content/carousels/templates/CourseTemplate'; +import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; const responsiveOptions = [ { @@ -22,38 +23,38 @@ const responsiveOptions = [ } ]; - export default function CoursesCarousel() { const [processedCourses, setProcessedCourses] = useState([]); - const [courses, setCourses] = useState([]); + const [loading, setLoading] = useState(true); const { fetchCourses } = useNostr(); useEffect(() => { const fetch = async () => { + setLoading(true); try { - const courses = await fetchCourses(); - console.log('courses:', courses); - setCourses(courses); + const fetchedCourses = await fetchCourses(); + if (fetchedCourses && fetchedCourses.length > 0) { + const processed = fetchedCourses.map(course => parseEvent(course)); + setProcessedCourses(processed); + } else { + console.log('No courses fetched or empty array returned'); + } + setLoading(false); } catch (error) { console.error('Error fetching courses:', error); + setLoading(false); } - }; + }; fetch(); - }, [fetchCourses]); - - useEffect(() => { - const processCourses = courses.map(course => { - const { id, content, title, summary, image, published_at } = parseEvent(course); - return { id, content, title, summary, image, published_at }; - } - ); - setProcessedCourses(processCourses); - }, [courses]); + }, [fetchCourses]); return ( <> - <h2 className="ml-[6%] mt-4">courses</h2> - <Carousel value={[...processedCourses, ...processedCourses]} numVisible={2} itemTemplate={CourseTemplate} responsiveOptions={responsiveOptions} /> + <h2 className="ml-[6%] mt-4">Courses</h2> + <Carousel value={loading ? [{}, {}, {}] : [...processedCourses, ...processedCourses]} + numVisible={2} + itemTemplate={loading ? TemplateSkeleton : CourseTemplate} + responsiveOptions={responsiveOptions} /> </> ); } diff --git a/src/components/content/carousels/ResourcesCarousel.js b/src/components/content/carousels/ResourcesCarousel.js index 7eb0695..ccdfc11 100644 --- a/src/components/content/carousels/ResourcesCarousel.js +++ b/src/components/content/carousels/ResourcesCarousel.js @@ -5,6 +5,7 @@ import { useNostr } from '@/hooks/useNostr'; import { useImageProxy } from '@/hooks/useImageProxy'; import { parseEvent } from '@/utils/nostr'; import ResourceTemplate from '@/components/content/carousels/templates/ResourceTemplate'; +import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; const responsiveOptions = [ { @@ -26,36 +27,36 @@ const responsiveOptions = [ export default function ResourcesCarousel() { const [processedResources, setProcessedResources] = useState([]); - const [resources, setResources] = useState([]); - const router = useRouter(); + const [loading, setLoading] = useState(true); const { fetchResources } = useNostr(); - const { returnImageProxy } = useImageProxy(); useEffect(() => { const fetch = async () => { + setLoading(true); try { - const resources = await fetchResources(); - console.log('resources:', resources); - setResources(resources); + const fetchedResources = await fetchResources(); + if (fetchedResources && fetchedResources.length > 0) { + const processed = fetchedResources.map(resource => parseEvent(resource)); + setProcessedResources(processed); + } else { + console.log('No resources fetched or empty array returned'); + } + setLoading(false); } catch (error) { console.error('Error fetching resources:', error); + setLoading(false); } }; fetch(); }, [fetchResources]); - useEffect(() => { - const processResources = resources.map(resource => { - const { id, content, title, summary, image, published_at } = parseEvent(resource); - return { id, content, title, summary, image, published_at }; - }); - setProcessedResources(processResources); - }, [resources]); - return ( <> - <h2 className="ml-[6%] mt-4">resources</h2> - <Carousel value={[...processedResources, ...processedResources]} numVisible={2} itemTemplate={ResourceTemplate} responsiveOptions={responsiveOptions} /> + <h2 className="ml-[6%] mt-4">Resources</h2> + <Carousel value={loading ? [{}, {}, {}] : [...processedResources, ...processedResources]} + numVisible={2} + itemTemplate={loading ? TemplateSkeleton : ResourceTemplate} + responsiveOptions={responsiveOptions} /> </> ); } diff --git a/src/components/content/carousels/WorkshopsCarousel.js b/src/components/content/carousels/WorkshopsCarousel.js index 2de7b7e..f16db51 100644 --- a/src/components/content/carousels/WorkshopsCarousel.js +++ b/src/components/content/carousels/WorkshopsCarousel.js @@ -5,6 +5,7 @@ import { useNostr } from '@/hooks/useNostr'; import { useImageProxy } from '@/hooks/useImageProxy'; import { parseEvent } from '@/utils/nostr'; import WorkshopTemplate from '@/components/content/carousels/templates/WorkshopTemplate'; +import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton'; const responsiveOptions = [ { @@ -26,36 +27,36 @@ const responsiveOptions = [ export default function WorkshopsCarousel() { const [processedWorkshops, setProcessedWorkshops] = useState([]); - const [workshops, setWorkshops] = useState([]); - const router = useRouter(); + const [loading, setLoading] = useState(true); const { fetchWorkshops } = useNostr(); - const { returnImageProxy } = useImageProxy(); useEffect(() => { const fetch = async () => { + setLoading(true); try { - const workshops = await fetchWorkshops(); - console.log('workshops:', workshops); - setWorkshops(workshops); + const fetchedWorkshops = await fetchWorkshops(); + if (fetchedWorkshops && fetchedWorkshops.length > 0) { + const processed = fetchedWorkshops.map(workshop => parseEvent(workshop)); + setProcessedWorkshops(processed); + } else { + console.log('No workshops fetched or empty array returned'); + } + setLoading(false); } catch (error) { console.error('Error fetching workshops:', error); + setLoading(false); } }; fetch(); }, [fetchWorkshops]); - useEffect(() => { - const processWorkshops = workshops.map(workshop => { - const { id, content, title, summary, image, published_at } = parseEvent(workshop); - return { id, content, title, summary, image, published_at }; - }); - setProcessedWorkshops(processWorkshops); - }, [workshops]); - return ( <> - <h2 className="ml-[6%] mt-4">workshops</h2> - <Carousel value={[...processedWorkshops, ...processedWorkshops]} numVisible={2} itemTemplate={WorkshopTemplate} responsiveOptions={responsiveOptions} /> + <h2 className="ml-[6%] mt-4">Workshops</h2> + <Carousel value={loading ? [{}, {}, {}] : [...processedWorkshops, ...processedWorkshops]} + numVisible={2} + itemTemplate={loading ? TemplateSkeleton : WorkshopTemplate} + responsiveOptions={responsiveOptions} /> </> ); } diff --git a/src/components/content/carousels/skeletons/TemplateSkeleton.js b/src/components/content/carousels/skeletons/TemplateSkeleton.js new file mode 100644 index 0000000..a5d42d8 --- /dev/null +++ b/src/components/content/carousels/skeletons/TemplateSkeleton.js @@ -0,0 +1,28 @@ +import React from "react"; +import { Skeleton } from "primereact/skeleton"; + +const TemplateSkeleton = () => { + return ( + <div className="flex flex-col items-start mx-auto px-4 mt-8 rounded-md"> + {/* Image Skeleton */} + {/* <div className="w-full" style={{ paddingBottom: "56.25%" }}> */} + <Skeleton width="100%" height="18rem"></Skeleton> + {/* </div> */} + + {/* Title Skeleton */} + <Skeleton width="70%" className="mt-4 mb-2" height="2rem"></Skeleton> + + {/* Summary Skeleton */} + <Skeleton width="90%" className="mb-2" height="1rem"></Skeleton> + <Skeleton width="90%" className="mb-4" height="1rem"></Skeleton> + + {/* Date and Zap Amount Skeleton */} + <div className="flex justify-between w-full"> + <Skeleton width="30%" height="1rem"></Skeleton> + <Skeleton width="5%" height="1rem"></Skeleton> + </div> + </div> + ); +}; + +export default TemplateSkeleton; diff --git a/src/components/content/carousels/templates/CourseTemplate.js b/src/components/content/carousels/templates/CourseTemplate.js index 0f117ba..1b6fdc6 100644 --- a/src/components/content/carousels/templates/CourseTemplate.js +++ b/src/components/content/carousels/templates/CourseTemplate.js @@ -40,7 +40,7 @@ const CourseTemplate = (course) => { return ( <div - className="flex flex-col items-center mx-auto px-4 cursor-pointer mt-8 rounded-md" + className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md" > <div onClick={() => router.push(`/details/${course.id}`)} @@ -65,8 +65,8 @@ const CourseTemplate = (course) => { <p className="text-xs text-gray-400"> {formatTimestampToHowLongAgo(course.published_at)} </p> - <p className="text-xs"> - <i className="pi pi-bolt"></i> {zapAmount} + <p className="text-xs cursor-pointer"> + <i className="pi pi-bolt text-yellow-300"></i> {zapAmount} </p> </div> </div> diff --git a/src/components/content/carousels/templates/ResourceTemplate.js b/src/components/content/carousels/templates/ResourceTemplate.js index efea36f..acac2e4 100644 --- a/src/components/content/carousels/templates/ResourceTemplate.js +++ b/src/components/content/carousels/templates/ResourceTemplate.js @@ -40,7 +40,7 @@ const ResourceTemplate = (resource) => { return ( <div - className="flex flex-col items-center mx-auto px-4 cursor-pointer mt-8 rounded-md" + className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md" > {/* Wrap the image in a div with a relative class with a padding-bottom of 56.25% representing the aspect ratio of 16:9 */} <div @@ -66,8 +66,8 @@ const ResourceTemplate = (resource) => { <p className="text-xs text-gray-400"> {formatTimestampToHowLongAgo(resource.published_at)} </p> - <p className="text-xs"> - <i className="pi pi-bolt"></i> {zapAmount} + <p className="text-xs cursor-pointer"> + <i className="pi pi-bolt text-yellow-300"></i> {zapAmount} </p> </div> </div> diff --git a/src/components/content/carousels/templates/WorkshopTemplate.js b/src/components/content/carousels/templates/WorkshopTemplate.js index 7fd8559..7946b19 100644 --- a/src/components/content/carousels/templates/WorkshopTemplate.js +++ b/src/components/content/carousels/templates/WorkshopTemplate.js @@ -40,7 +40,7 @@ const WorkshopTemplate = (workshop) => { return ( <div - className="flex flex-col items-center mx-auto px-4 cursor-pointer mt-8 rounded-md" + className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md" > <div onClick={() => router.push(`/details/${workshop.id}`)} @@ -65,8 +65,8 @@ const WorkshopTemplate = (workshop) => { <p className="text-xs text-gray-400"> {formatTimestampToHowLongAgo(workshop.published_at)} </p> - <p className="text-xs"> - <i className="pi pi-bolt"></i> {zapAmount} + <p className="text-xs cursor-pointer"> + <i className="pi pi-bolt text-yellow-300"></i> {zapAmount} </p> </div> </div>