import { useEffect, useRef, useState } from 'preact/hooks'; import useScroll from '../utils/useScroll'; import useTitle from '../utils/useTitle'; import Icon from './icon'; import Link from './link'; import Loader from './loader'; import Status from './status'; function Timeline({ title, path, id, emptyText, errorText, fetchItems = () => {}, }) { if (title) { useTitle(title, path); } const [items, setItems] = useState([]); const [uiState, setUIState] = useState('default'); const [showMore, setShowMore] = useState(false); const scrollableRef = useRef(null); const { nearReachEnd, reachStart } = useScroll({ scrollableElement: scrollableRef.current, }); const loadItems = (firstLoad) => { setUIState('loading'); (async () => { try { const { done, value } = await fetchItems(firstLoad); if (value?.length) { if (firstLoad) { setItems(value); } else { setItems([...items, ...value]); } setShowMore(!done); } else { setShowMore(false); } setUIState('default'); } catch (e) { console.error(e); setUIState('error'); } })(); }; useEffect(() => { scrollableRef.current?.scrollTo({ top: 0 }); loadItems(true); }, []); useEffect(() => { if (reachStart) { loadItems(true); } }, [reachStart]); useEffect(() => { if (nearReachEnd && showMore) { loadItems(); } }, [nearReachEnd, showMore]); return (
{ if (e.target === e.currentTarget) { scrollableRef.current?.scrollTo({ top: 0, behavior: 'smooth', }); } }} >

{title}

{!!items.length ? ( <> {showMore && ( )} ) : uiState === 'loading' ? ( ) : ( uiState !== 'loading' &&

{emptyText}

)} {uiState === 'error' ? (

{errorText}

) : ( uiState !== 'loading' && !!items.length && !showMore &&

The end.

)}
); } export default Timeline;