diff options
Diffstat (limited to 'src/components/organisms/layout/posts-list.tsx')
| -rw-r--r-- | src/components/organisms/layout/posts-list.tsx | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/src/components/organisms/layout/posts-list.tsx b/src/components/organisms/layout/posts-list.tsx index daf4491..4d77d20 100644 --- a/src/components/organisms/layout/posts-list.tsx +++ b/src/components/organisms/layout/posts-list.tsx @@ -1,10 +1,11 @@ +import Button from '@components/atoms/buttons/button'; import Heading, { type HeadingLevel } from '@components/atoms/headings/heading'; -import { FC } from 'react'; +import ProgressBar from '@components/atoms/loaders/progress-bar'; +import Spinner from '@components/atoms/loaders/spinner'; +import { FC, Fragment, useRef } from 'react'; import { useIntl } from 'react-intl'; -import Summary, { type SummaryProps } from './summary'; import styles from './posts-list.module.scss'; -import ProgressBar from '@components/atoms/loaders/progress-bar'; -import Button from '@components/atoms/buttons/button'; +import Summary, { type SummaryProps } from './summary'; export type Post = SummaryProps & { /** @@ -23,10 +24,22 @@ export type PostsListProps = { */ byYear?: boolean; /** + * Determine if the data is loading. + */ + isLoading?: boolean; + /** + * Load more button handler. + */ + loadMore?: () => void; + /** * The posts data. */ posts: Post[]; /** + * Determine if the load more button should be visible. + */ + showLoadMoreBtn?: boolean; + /** * The posts heading level (hn). */ titleLevel?: HeadingLevel; @@ -62,29 +75,42 @@ const sortPostsByYear = (data: Post[]): YearCollection => { */ const PostsList: FC<PostsListProps> = ({ byYear = false, + isLoading = false, + loadMore, posts, + showLoadMoreBtn = false, titleLevel, total, }) => { const intl = useIntl(); + const lastPostRef = useRef<HTMLSpanElement>(null); /** * Retrieve the list of posts. * - * @param {Posts[]} data - A collection fo posts. + * @param {Posts[]} allPosts - A collection fo posts. * @param {HeadingLevel} [headingLevel] - The posts heading level (hn). * @returns {JSX.Element} The list of posts. */ const getList = ( - data: Post[], + allPosts: Post[], headingLevel: HeadingLevel = 2 ): JSX.Element => { + const lastPostId = allPosts[allPosts.length - 1].id; + return ( <ol className={styles.list}> - {data.map(({ id, ...post }) => ( - <li key={id} className={styles.item}> - <Summary {...post} titleLevel={headingLevel} /> - </li> + {allPosts.map(({ id, ...post }) => ( + <Fragment key={id}> + <li className={styles.item}> + <Summary {...post} titleLevel={headingLevel} /> + </li> + {id === lastPostId && ( + <li> + <span ref={lastPostRef} tabIndex={-1} /> + </li> + )} + </Fragment> ))} </ol> ); @@ -93,7 +119,7 @@ const PostsList: FC<PostsListProps> = ({ /** * Retrieve the list of posts. * - * @returns {JSX.Element | JSX.Element[]} - The posts list. + * @returns {JSX.Element | JSX.Element[]} The posts list. */ const getPosts = (): JSX.Element | JSX.Element[] => { if (!byYear) return getList(posts); @@ -123,12 +149,23 @@ const PostsList: FC<PostsListProps> = ({ { articlesCount: posts.length, total: total } ); - const loadMore = intl.formatMessage({ + const loadMoreBody = intl.formatMessage({ defaultMessage: 'Load more articles?', id: 'uaqd5F', description: 'PostsList: load more button', }); + /** + * Load more posts handler. + */ + const loadMorePosts = () => { + if (lastPostRef.current) { + lastPostRef.current.focus(); + } + + loadMore && loadMore(); + }; + return posts.length === 0 ? ( <p> {intl.formatMessage({ @@ -140,13 +177,23 @@ const PostsList: FC<PostsListProps> = ({ ) : ( <> {getPosts()} + {isLoading && <Spinner />} <ProgressBar min={1} max={total} current={posts.length} info={progressInfo} /> - <Button className={styles.btn}>{loadMore}</Button> + {showLoadMoreBtn && ( + <Button + kind="tertiary" + onClick={loadMorePosts} + disabled={isLoading} + className={styles.btn} + > + {loadMoreBody} + </Button> + )} </> ); }; |
