From 53b63ac27c2275262db9a04be02210a3287aa71d Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 1 Dec 2023 19:34:58 +0100 Subject: refactor(pages): refine Blog pages * replace usePostsList with useArticlesList to keep names coherent * remove useIsMounted hook * rewrite useRedirection hook * add redirect in getStaticProps to avoid unecessary fetching * move Pagination component in a noscript tag * use hooks to refresh thematics and topics lists * complete Cypress tests --- src/pages/blog/index.tsx | 305 +++++++++++++++++++++++++++-------------------- 1 file changed, 174 insertions(+), 131 deletions(-) (limited to 'src/pages/blog/index.tsx') diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx index 12bc03e..df25cd2 100644 --- a/src/pages/blog/index.tsx +++ b/src/pages/blog/index.tsx @@ -1,9 +1,8 @@ /* eslint-disable max-statements */ import type { GetStaticProps } from 'next'; import Head from 'next/head'; -import { useRouter } from 'next/router'; import Script from 'next/script'; -import { useCallback, useRef } from 'react'; +import { useCallback } from 'react'; import { useIntl } from 'react-intl'; import { getLayout, @@ -18,11 +17,11 @@ import { PageHeader, PageBody, PageSidebar, + Spinner, } from '../../components'; import { convertWPThematicPreviewToPageLink, convertWPTopicPreviewToPageLink, - fetchPostsCount, fetchPostsList, fetchThematicsCount, fetchThematicsList, @@ -47,71 +46,30 @@ import { getWebPageSchema, } from '../../utils/helpers'; import { loadTranslation, type Messages } from '../../utils/helpers/server'; -import { useBreadcrumb, useIsMounted, usePostsList } from '../../utils/hooks'; +import { + useArticlesList, + useBreadcrumb, + useThematicsList, + useTopicsList, +} from '../../utils/hooks'; + +const renderPaginationLink: RenderPaginationLink = (pageNum) => + `${ROUTES.BLOG}/page/${pageNum}`; type BlogPageProps = { - posts: GraphQLConnection; - thematicsList: WPThematicPreview[]; - topicsList: WPTopicPreview[]; - totalArticles: number; + data: { + posts: GraphQLConnection; + thematics: GraphQLConnection; + topics: GraphQLConnection; + }; translation: Messages; }; /** * Blog index page. */ -const BlogPage: NextPageWithLayout = ({ - posts, - thematicsList, - topicsList, - totalArticles, -}) => { +const BlogPage: NextPageWithLayout = ({ data }) => { const intl = useIntl(); - const title = intl.formatMessage({ - defaultMessage: 'Blog', - description: 'BlogPage: page title', - id: '7TbbIk', - }); - const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ - title, - url: ROUTES.BLOG, - }); - const postsListRef = useRef(null); - const isMounted = useIsMounted(postsListRef); - const { asPath } = useRouter(); - const page = { - title: intl.formatMessage( - { - defaultMessage: 'Blog: development, open source - {websiteName}', - description: 'BlogPage: SEO - Page title', - id: '+Y+tLK', - }, - { websiteName: CONFIG.name } - ), - url: `${CONFIG.url}${asPath}`, - }; - const pageDescription = intl.formatMessage( - { - defaultMessage: - "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.", - description: 'BlogPage: SEO - Meta description', - id: '18h/t0', - }, - { websiteName: CONFIG.name } - ); - const webpageSchema = getWebPageSchema({ - description: pageDescription, - locale: CONFIG.locales.defaultLocale, - slug: asPath, - title, - }); - const blogSchema = getBlogSchema({ - isSinglePage: false, - locale: CONFIG.locales.defaultLocale, - slug: asPath, - }); - const schemaJsonLd = getSchemaJson([webpageSchema, blogSchema]); - const { articles, error, @@ -121,27 +79,101 @@ const BlogPage: NextPageWithLayout = ({ isRefreshing, hasNextPage, loadMore, - } = usePostsList({ - fallback: [posts], - fetcher: fetchPostsList, + } = useArticlesList({ + fallback: [data.posts], perPage: CONFIG.postsPerPage, }); + const { isLoading: areThematicsLoading, thematics } = useThematicsList({ + fallback: data.thematics, + input: { first: data.thematics.pageInfo.total }, + }); + const { isLoading: areTopicsLoading, topics } = useTopicsList({ + fallback: data.topics, + input: { first: data.topics.pageInfo.total }, + }); - const thematicsListTitle = intl.formatMessage({ - defaultMessage: 'Thematics', - description: 'BlogPage: thematics list widget title', - id: 'HriY57', + const messages = { + loading: { + thematicsList: intl.formatMessage({ + defaultMessage: 'Thematics are loading...', + description: 'BlogPage: loading thematics message', + id: 'y37FuH', + }), + topicsList: intl.formatMessage({ + defaultMessage: 'Topics are loading...', + description: 'BlogPage: loading topics message', + id: 'OsclKU', + }), + }, + pageTitle: intl.formatMessage({ + defaultMessage: 'Blog', + description: 'BlogPage: page title', + id: '7TbbIk', + }), + pagination: { + noJS: intl.formatMessage({ + defaultMessage: + "You can't load more articles without Javascript, please use the pagination instead.", + description: 'BlogPage: pagination no script message', + id: 'ZMES/E', + }), + title: intl.formatMessage({ + defaultMessage: 'Pagination', + description: 'BlogPage: pagination accessible name', + id: 'AXe1Iz', + }), + }, + seo: { + metaDesc: intl.formatMessage( + { + defaultMessage: + "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.", + description: 'BlogPage: SEO - Meta description', + id: '18h/t0', + }, + { websiteName: CONFIG.name } + ), + title: intl.formatMessage( + { + defaultMessage: 'Blog: development, open source - {websiteName}', + description: 'BlogPage: SEO - Page title', + id: '+Y+tLK', + }, + { websiteName: CONFIG.name } + ), + }, + widgets: { + thematicsListTitle: intl.formatMessage({ + defaultMessage: 'Thematics', + description: 'BlogPage: thematics list widget title', + id: 'HriY57', + }), + topicsListTitle: intl.formatMessage({ + defaultMessage: 'Topics', + description: 'BlogPage: topics list widget title', + id: '2D9tB5', + }), + }, + }; + + const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ + title: messages.pageTitle, + url: ROUTES.BLOG, }); - const topicsListTitle = intl.formatMessage({ - defaultMessage: 'Topics', - description: 'BlogPage: topics list widget title', - id: '2D9tB5', + const webpageSchema = getWebPageSchema({ + description: messages.seo.metaDesc, + locale: CONFIG.locales.defaultLocale, + slug: ROUTES.BLOG, + title: messages.pageTitle, }); - const renderPaginationLink: RenderPaginationLink = useCallback( - (pageNum) => `${ROUTES.BLOG}/page/${pageNum}`, - [] - ); + const blogSchema = getBlogSchema({ + isSinglePage: false, + locale: CONFIG.locales.defaultLocale, + slug: ROUTES.BLOG, + }); + const schemaJsonLd = getSchemaJson([webpageSchema, blogSchema]); + const renderPaginationLabel: RenderPaginationItemAriaLabel = useCallback( ({ kind, pageNumber: number, isCurrentPage }) => { switch (kind) { @@ -187,27 +219,19 @@ const BlogPage: NextPageWithLayout = ({ [intl] ); - const paginationAriaLabel = intl.formatMessage({ - defaultMessage: 'Pagination', - description: 'BlogPage: pagination accessible name', - id: 'AXe1Iz', - }); - - const blogArticles = articles?.flatMap((p) => - p.edges.map((edge) => edge.node) - ); + const pageUrl = `${CONFIG.url}${ROUTES.BLOG}`; return ( - {page.title} + {messages.seo.title} {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} - - + + {/*eslint-disable-next-line react/jsx-no-literals -- Content allowed */} - - + +