From 9bd5a9f7c9d23a0cbdf5171a79a74e42e72f6228 Mon Sep 17 00:00:00 2001 From: "Malin J." Date: Tue, 21 Jan 2025 13:47:54 +0100 Subject: [PATCH] Rewriting of scheduling logic #15 --- studio/schemaTypes/documents/slide.tsx | 13 +++++- web/app/[slug]/page.tsx | 24 +++-------- web/components/sections/Slideshow.tsx | 58 ++++++++++++++++++++++---- web/sanity/lib/queries.ts | 1 + 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/studio/schemaTypes/documents/slide.tsx b/studio/schemaTypes/documents/slide.tsx index 96f4809..d2f898e 100644 --- a/studio/schemaTypes/documents/slide.tsx +++ b/studio/schemaTypes/documents/slide.tsx @@ -36,6 +36,14 @@ export default { {type: 'testSlide'}, ].filter((e) => e), }), + defineField({ + name: 'duration', + type: 'number', + title: 'Slide Duration (seconds)', + description: 'Optional duration for the slide in seconds. Default is 30 seconds', + validation: (Rule) => + Rule.min(1).integer().positive().warning('Duration should be a positive whole number'), + }), ].filter((e) => e), orderings: [ { @@ -47,12 +55,13 @@ export default { preview: { select: { title: 'title', + duration: 'duration', }, prepare(selection: any) { - const {title} = selection + const {title, duration} = selection return { title: title, - subtitle: 'Slide ', + subtitle: `Duration: ${duration || 30} seconds`, } }, }, diff --git a/web/app/[slug]/page.tsx b/web/app/[slug]/page.tsx index abb0fa0..172eaad 100644 --- a/web/app/[slug]/page.tsx +++ b/web/app/[slug]/page.tsx @@ -1,20 +1,13 @@ import { getSlideshowsQuery, pagesSlugs } from '@/sanity/lib/queries' -import Slideshow from '@/components/sections/Slideshow' import { sanityFetch } from '@/sanity/lib/live' -import isSlideActive from '@/common/helpers/isSlideActive' - -type Props = { - params: Promise<{ slug: string }> -} +import Slideshow from '@/components/sections/Slideshow' export const revalidate = 60 export const dynamicParams = true export async function generateStaticParams() { - /** Fetching all locations to create separate route for each */ const { data } = await sanityFetch({ query: pagesSlugs, - // // Use the published perspective in generateStaticParams perspective: 'published', stega: false, }) @@ -22,20 +15,15 @@ export async function generateStaticParams() { return data } -export default async function Page(props: Props) { - const params = await props.params - const { data: slideshows } = await sanityFetch({ query: getSlideshowsQuery, params }) - - const filteredSlideshows = slideshows.map((show: any) => { - return { - ...show, - slides: show.slides?.filter(isSlideActive) || [], - } +export default async function Page({ params }: { params: { slug: string } }) { + const { data: slideshows } = await sanityFetch({ + query: getSlideshowsQuery, + params, }) return (
- +
) } diff --git a/web/components/sections/Slideshow.tsx b/web/components/sections/Slideshow.tsx index 7ac5fea..a668aed 100644 --- a/web/components/sections/Slideshow.tsx +++ b/web/components/sections/Slideshow.tsx @@ -2,21 +2,63 @@ import { useEffect, useState } from 'react' import SectionMapper from './SectionMapper' +import isSlideActive from '@/common/helpers/isSlideActive' + +type Slide = { + content: any + duration?: number | null + scheduling?: any +} type SlideshowProps = { - slideshows: any[] + slideshows: { + slides: Slide[] + }[] } export default function Slideshow({ slideshows }: SlideshowProps) { - const [activeSlideIndex, setActiveSlideIndex] = useState(0) + const [activeSlides, setActiveSlides] = useState([]) + const [currentIndex, setCurrentIndex] = useState(0) useEffect(() => { - const interval = setInterval(() => setActiveSlideIndex((i) => (i + 1) % slideshows?.[0]?.slides.length), 30000) + if (!slideshows[0]) return + const initiallyActive = slideshows[0].slides.filter(isSlideActive) || [] + setActiveSlides(initiallyActive) + setCurrentIndex(0) + }, [slideshows]) + + useEffect(() => { + if (activeSlides.length === 0) return + const currentSlide = activeSlides[currentIndex] + const durationMs = (currentSlide?.duration || 30) * 1000 + + const timer = setTimeout(() => { + const refreshed = slideshows[0]?.slides?.filter(isSlideActive) || [] + + setActiveSlides((prevActive) => { + if (refreshed.length !== prevActive.length && currentIndex >= refreshed.length) { + setCurrentIndex(0) + } + return refreshed + }) + + setCurrentIndex((prev) => { + if (refreshed.length === 0) return 0 + return (prev + 1) % refreshed.length + }) + }, durationMs) + + return () => clearTimeout(timer) + }, [activeSlides, currentIndex, slideshows]) + + if (activeSlides.length === 0) { + return
No active slides
+ } - return () => { - clearInterval(interval) - } - }, []) + const slide = activeSlides[currentIndex] + if (!slide || !slide.content || slide.content.length === 0) { + return
This slide has no content
+ } - return + return } diff --git a/web/sanity/lib/queries.ts b/web/sanity/lib/queries.ts index 53b6633..5ca2e22 100644 --- a/web/sanity/lib/queries.ts +++ b/web/sanity/lib/queries.ts @@ -35,6 +35,7 @@ export const getSlideshowsQuery = defineQuery(` scheduling{ ..., }, + duration, content[]{ _type == "infoBoard" => { "type": _type,