import React, { forwardRef, useImperativeHandle, useState, useEffect, useRef } from 'react'; import { Section } from '../../types/Conversation'; import SectionItem from './SectionItem'; export interface ScrollingSectionsProps { sections: Section[]; onSectionChange?: (index: number) => void; displayProp: string; showProgress?: boolean; displayBeforeAndAfter?: boolean; startAtTop?: boolean; onComplete?: () => void; } export interface ScrollingSectionsRef { play: () => void; pause: () => void; goToSection: (index: number) => void; } const ScrollingSections = forwardRef( ({ sections, onSectionChange, displayProp, showProgress = true, displayBeforeAndAfter = true, startAtTop = false, onComplete }, ref) => { const [activeIndex, setActiveIndex] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [progress, setProgress] = useState(0); const progressIntervalRef = useRef(null); const sectionTimeoutRef = useRef(null); const [elapsedTime, setElapsedTime] = useState(0); // in milliseconds const startProgress = () => { if (!isPlaying) return; const currentDuration = sections[activeIndex]?.duration || 10; const totalDurationMs = currentDuration * 1000; const startTime = Date.now() - elapsedTime; if (progressIntervalRef.current) { window.clearInterval(progressIntervalRef.current); } progressIntervalRef.current = window.setInterval(() => { const now = Date.now(); const newElapsed = now - startTime; const newProgress = (newElapsed / totalDurationMs) * 100; if (newProgress >= 100) { window.clearInterval(progressIntervalRef.current!); setProgress(100); setElapsedTime(0); goToNextSection(); } else { setProgress(newProgress); setElapsedTime(newElapsed); } }, 100); }; const goToNextSection = () => { setActiveIndex((prev) => (prev + 1) % sections.length); onSectionChange?.((activeIndex + 1) % sections.length); if ((activeIndex + 1) % sections.length === 0) { pause(); onComplete?.(); } }; const goToSection = (index: number) => { if (index >= 0 && index < sections.length) { setActiveIndex(index); setProgress(0); setElapsedTime(0); // reset elapsed time onSectionChange?.(index); } }; const play = () => { setIsPlaying(true); }; const pause = () => { setIsPlaying(false); if (progressIntervalRef.current) { window.clearInterval(progressIntervalRef.current); } if (sectionTimeoutRef.current) { window.clearTimeout(sectionTimeoutRef.current); } }; useImperativeHandle(ref, () => ({ play, pause, goToSection })); useEffect(() => { if (isPlaying) { startProgress(); } return () => { if (progressIntervalRef.current) { window.clearInterval(progressIntervalRef.current); } if (sectionTimeoutRef.current) { window.clearTimeout(sectionTimeoutRef.current); } }; }, [activeIndex, isPlaying]); const getSectionPosition = (index: number) => { if (index === activeIndex) return 'active'; if (index === activeIndex - 1 && displayBeforeAndAfter) return 'before'; if (index === (activeIndex + 1) % sections.length && displayBeforeAndAfter) return 'after'; return null; }; if (!sections || sections.length === 0) { return
No sections available
; } return (
{sections.map((section, index) => { const position = getSectionPosition(index); if (position) { return ( ); } return null; })}
{showProgress && (
)}
); } ); export default ScrollingSections;