diff --git a/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx new file mode 100644 index 00000000..1d6c3ad0 --- /dev/null +++ b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { ReactNode, useEffect, startTransition } from 'react'; +import { Center, Button, Stack } from '@mantine/core'; +import { useInViewport } from '@mantine/hooks'; + +interface Props { + children: ReactNode; + dataLength: number; + hasMore: boolean; + isInitialLoading: boolean; + isLoading: boolean; + loadMore: () => void; + loader?: ReactNode; + manualLoadButton?: boolean; +} + +export default function InfiniteScroll(props: Props) { + const { ref, inViewport } = useInViewport(); + + useEffect(() => { + startTransition(() => { + if (inViewport && props.hasMore && !props.isLoading) { + props.loadMore(); + } + }); + }, [inViewport, props.hasMore, props.isLoading, props.loadMore]); + + return ( + + {props.children} + {props.isLoading && props.loader} + +
+ {!props.isLoading && props.hasMore && props.manualLoadButton && ( + + )} +
+
+ ); +} diff --git a/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx b/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx index 37631fe5..b5cee771 100644 --- a/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx +++ b/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx @@ -1,13 +1,13 @@ 'use client'; -import { Container, Grid, Stack, Button, Text, Center } from '@mantine/core'; +import { Center, Container, Grid, Loader, Stack } from '@mantine/core'; import useCards from '../../lib/queries/useCards'; import UrlCard from '@/features/cards/components/urlCard/UrlCard'; import CardsContainerError from './Error.CardsContainer'; import CardsContainerSkeleton from './Skeleton.CardsContainer'; -import { Fragment, useState } from 'react'; import ProfileEmptyTab from '@/features/profile/components/profileEmptyTab/ProfileEmptyTab'; import { FaRegNoteSticky } from 'react-icons/fa6'; +import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; interface Props { handle: string; @@ -43,39 +43,34 @@ export default function CardsContainer(props: Props) { return ( - - - - {allCards.map((card) => ( - - - - ))} - - - {hasNextPage && ( -
- -
- )} -
-
+ + + + } + > + + {allCards.map((card) => ( + + + + ))} + +
); } diff --git a/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx b/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx index b7ecb4c5..5b9be3b4 100644 --- a/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx +++ b/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx @@ -1,12 +1,13 @@ 'use client'; -import { Button, Container, Stack, SimpleGrid, Center } from '@mantine/core'; +import { Button, Container, Stack, SimpleGrid } from '@mantine/core'; import useCollections from '../../lib/queries/useCollections'; import CollectionCard from '../../components/collectionCard/CollectionCard'; import CreateCollectionDrawer from '../../components/createCollectionDrawer/CreateCollectionDrawer'; import { useState } from 'react'; import ProfileEmptyTab from '@/features/profile/components/profileEmptyTab/ProfileEmptyTab'; import { BiCollection } from 'react-icons/bi'; +import InfiniteLoadTrigger from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; interface Props { handle: string; @@ -32,28 +33,21 @@ export default function CollectionsContainer(props: Props) { return ( - + Loading...} // replace with your loader component if you want + > {collections.map((collection) => ( ))} - - {hasNextPage && ( -
- -
- )} -
+
) : ( - - - {allActivities.map((item, i) => ( - - ))} + + + + } + > + + + {allActivities.map((item) => ( + + ))} + - - {hasNextPage && ( -
- -
- )} -
+ )}