diff --git a/client/src/app/hooks/useInterval.js b/client/src/app/hooks/useInterval.js new file mode 100644 index 000000000..6807be455 --- /dev/null +++ b/client/src/app/hooks/useInterval.js @@ -0,0 +1,19 @@ +import { useEffect, useRef } from "react"; + +export const useInterval = (callback, delay) => { + const savedCallback = useRef(); + + useEffect(() => { + savedCallback.current = callback; + }, [callback]); + + useEffect(() => { + function tick() { + savedCallback.current(); + } + if (delay !== null) { + let id = setInterval(tick, delay); + return () => clearInterval(id); + } + }, [delay]); +}; diff --git a/client/src/app/hooks/useTimeout.js b/client/src/app/hooks/useTimeout.js new file mode 100644 index 000000000..ae5681d5f --- /dev/null +++ b/client/src/app/hooks/useTimeout.js @@ -0,0 +1,38 @@ +import { useEffect } from 'react'; + +// +// useTimeout React Hook +// +// React hook for delaying calls with time +export const useTimeout = ( + callback, // function to call. No args passed. + timeout = 0, // delay, ms (default: immediately put into JS Event Queue) + { + // manage re-render behavior. + // by default, a re-render in your component will re-define the callback, + // which will cause this timeout to cancel itself. + // to avoid cancelling on re-renders (but still cancel on unmounts), + // set `persistRenders: true,`. + persistRenders = false, + } = {}, + // These dependencies are injected for testing purposes. + // (pure functions - where all dependencies are arguments - is often easier to test) + _setTimeout = setTimeout, + _clearTimeout = clearTimeout, + _useEffect = useEffect +) => { + let timeoutId; + const cancel = () => timeoutId && _clearTimeout(timeoutId); + + _useEffect( + () => { + timeoutId = _setTimeout(callback, timeout); + return cancel; + }, + persistRenders + ? [_setTimeout, _clearTimeout] + : [callback, timeout, _setTimeout, _clearTimeout] + ); + + return cancel; +}; diff --git a/client/src/features/viewers/backstage/Paginator.jsx b/client/src/features/viewers/backstage/Paginator.jsx new file mode 100644 index 000000000..ccf7ab0ad --- /dev/null +++ b/client/src/features/viewers/backstage/Paginator.jsx @@ -0,0 +1,82 @@ +import TodayItem from './TodayItem'; +import style from './Paginator.module.css'; +import { useEffect, useState } from 'react'; +import { useTimeout } from '../../../app/hooks/useTimeout'; +import { useInterval } from '../../../app/hooks/useInterval'; + +export default function Paginator(props) { + const { events, selectedId } = props; + const LIMIT_PER_PAGE = 3; + const SCROLL_TIME = 5000; + const SCROLL_PAST = false; + const [numEvents, setNumEvents] = useState(0); + const [page, setPage] = useState([]); + const [pages, setPages] = useState(0); + const [selPage, setSelPage] = useState(0); + + // Keep track of order + // 0 - events before + // 1 - running event + // 2 - future event + let selectedYet = 0; + + useEffect(() => { + if (events == null) return; + + console.log('debug events', events); + + // how many events in list + let n = events.length; + setNumEvents(n); + console.log('debug ne', n); + + // how many paginated views + let p = Math.ceil(n / LIMIT_PER_PAGE); + setPages(p); + console.log('debug np', p); + + // divide events in parts of LIMIT_PER_PAGE + const eventStart = LIMIT_PER_PAGE * selPage; + const eventEnd = LIMIT_PER_PAGE * (selPage + 1); + let e = events.slice(eventStart, eventEnd); + setPage(e); + console.log('debug show', e); + + // if array is completely in past, show depending on SCROLL_PAST + }, [events, selPage]); + + // every SCROLL_TIME go to the next array + useInterval(() => { + if (numEvents > LIMIT_PER_PAGE) { + const next = (selPage + 1) % pages; + setSelPage(next); + } + }, SCROLL_TIME); + + return ( + <> +