Added loading skeletons for carousels

This commit is contained in:
austinkelsay 2024-04-22 15:46:52 -05:00
parent f258866e07
commit edf97c74fa
7 changed files with 90 additions and 59 deletions

View File

@ -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} />
</>
);
}

View File

@ -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} />
</>
);
}

View File

@ -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} />
</>
);
}

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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>