import React, { useCallback, useEffect, useRef, useState } from 'react' import ArtworkGallery from '../../artwork/ArtworkGallery' function FavSkeleton() { return (
) } /** * TabFavourites * Shows artworks the user has favourited. */ export default function TabFavourites({ favourites, isOwner, username }) { const initialItems = Array.isArray(favourites) ? favourites : (favourites?.data ?? []) const [items, setItems] = useState(initialItems) const [nextCursor, setNextCursor] = useState(favourites?.next_cursor ?? null) const [loadingMore, setLoadingMore] = useState(false) const loadMoreRef = useRef(null) useEffect(() => { setItems(initialItems) setNextCursor(favourites?.next_cursor ?? null) }, [favourites, initialItems]) const loadMore = useCallback(async () => { if (!nextCursor || loadingMore) return setLoadingMore(true) try { const res = await fetch( `/api/profile/${encodeURIComponent(username)}/favourites?cursor=${encodeURIComponent(nextCursor)}`, { headers: { Accept: 'application/json' } } ) if (res.ok) { const data = await res.json() setItems((prev) => [...prev, ...(data.data ?? data)]) setNextCursor(data.next_cursor ?? null) } } catch (_) {} setLoadingMore(false) }, [loadingMore, nextCursor, username]) useEffect(() => { const node = loadMoreRef.current if (!node || !nextCursor) { return undefined } const observer = new IntersectionObserver( (entries) => { if (entries.some((entry) => entry.isIntersecting)) { loadMore() } }, { rootMargin: '320px 0px', } ) observer.observe(node) return () => observer.disconnect() }, [loadMore, nextCursor]) return (

{isOwner ? 'Your Favourites' : 'Favourites'}

{items.length === 0 ? (

No favourites yet

Artworks added to favourites will appear here.

) : ( <> ({ loading: index < 8 ? 'eager' : 'lazy', })} > {loadingMore && Array.from({ length: 4 }).map((_, i) => )} {nextCursor && ( ) }