From d363306235f2a48f16e488f20f73e2233ddcf281 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Wed, 29 Nov 2023 18:07:20 +0100 Subject: refactor(pages): improve Homepage * move custom homepage components that does not require props to the MDX file (links should not need to be translated here but where they are defined) * move SEO title and meta desc to MDX file * make Page component the wrapper instead of using a React fragment * fix MDX module types --- src/pages/index.tsx | 347 +++++++++------------------------------- src/pages/thematique/[slug].tsx | 5 +- 2 files changed, 78 insertions(+), 274 deletions(-) (limited to 'src/pages') diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 7bd8aec..f4d36c1 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -3,10 +3,9 @@ import type { GetStaticProps } from 'next'; import Head from 'next/head'; import NextImage from 'next/image'; import Script from 'next/script'; -import type { FC, HTMLAttributes, ReactNode } from 'react'; +import type { FC } from 'react'; import { useIntl } from 'react-intl'; import { - ButtonLink, Card, CardCover, CardFooter, @@ -15,261 +14,77 @@ import { CardTitle, getLayout, Grid, - Icon, - List, - ListItem, Time, MetaItem, - type PageSectionProps, - PageSection, Page, } from '../components'; import { mdxComponents } from '../components/mdx'; -import HomePageContent from '../content/pages/homepage.mdx'; +import HomePageContent, { meta } from '../content/pages/homepage.mdx'; import { convertRecentPostToRecentArticle, fetchRecentPosts, } from '../services/graphql'; -import styles from '../styles/pages/home.module.scss'; import type { NextPageWithLayout, RecentArticle } from '../types'; import { CONFIG } from '../utils/config'; -import { PERSONAL_LINKS, ROUTES } from '../utils/constants'; +import { ROUTES } from '../utils/constants'; import { getSchemaJson, getWebPageSchema } from '../utils/helpers'; import { loadTranslation, type Messages } from '../utils/helpers/server'; import { useBreadcrumb } from '../utils/hooks'; -/** - * Column component. - * - * Render the body as a column. - */ -const Column = ({ children, ...props }: HTMLAttributes) => ( -
{children}
-); - -/** - * Retrieve a list of coding links. - * - * @returns {JSX.Element} - A list of links. - */ -const CodingLinks: FC = () => { - const intl = useIntl(); - - return ( - - - - {intl.formatMessage({ - defaultMessage: 'Web development', - description: 'HomePage: link to web development thematic', - id: 'vkF/RP', - })} - - - - - {intl.formatMessage({ - defaultMessage: 'Projects', - description: 'HomePage: link to projects', - id: 'N44SOc', - })} - - - - ); -}; - -/** - * Retrieve a list of Coldark repositories. - * - * @returns {JSX.Element} - A list of links. - */ -const ColdarkRepos: FC = () => { - const intl = useIntl(); - const repo = { - github: 'https://github.com/ArmandPhilippot/coldark', - gitlab: 'https://gitlab.com/ArmandPhilippot/coldark', - }; - - return ( - - - - {intl.formatMessage({ - defaultMessage: 'Github', - description: 'HomePage: Github link', - id: '3f3PzH', - })} - - - - - {intl.formatMessage({ - defaultMessage: 'Gitlab', - description: 'HomePage: Gitlab link', - id: '7AnwZ7', - })} - - - - ); -}; - -/** - * Retrieve a list of links related to Free thematic. - * - * @returns {JSX.Element} - A list of links. - */ -const LibreLinks: FC = () => { - const intl = useIntl(); - - return ( - - - - {intl.formatMessage({ - defaultMessage: 'Free', - description: 'HomePage: link to free thematic', - id: 'w8GrOf', - })} - - - - - {intl.formatMessage({ - defaultMessage: 'Linux', - description: 'HomePage: link to Linux thematic', - id: 'jASD7k', - })} - - - - ); -}; - -/** - * Retrieve the Shaarli link. - * - * @returns {JSX.Element} - A list of links - */ -const ShaarliLink: FC = () => { - const intl = useIntl(); - - return ( - - - - {intl.formatMessage({ - defaultMessage: 'Shaarli', - description: 'HomePage: link to Shaarli', - id: 'i5L19t', - })} - - - - ); -}; - -/** - * Retrieve the additional links. - * - * @returns {JSX.Element} - A list of links. - */ -const MoreLinks: FC = () => { - const intl = useIntl(); - - return ( - - - - - {intl.formatMessage({ - defaultMessage: 'Contact me', - description: 'HomePage: contact button text', - id: 'sO/Iwj', - })} - - - - - - {intl.formatMessage({ - defaultMessage: 'Subscribe', - description: 'HomePage: RSS feed subscription text', - id: 'T4YA64', - })} - - - - ); +type RecentPostsProps = { + posts: RecentArticle[]; }; -const StyledGrid = ({ children }: { children: ReactNode }) => ( - - {children} - -); - /** - * Create the page sections. + * Get a cards list of recent posts. * - * @param {object} obj - An object containing the section body. - * @param {ReactNode[]} obj.children - The section body. - * @returns {JSX.Element} A section element. - */ -const HomePageSection: FC = ({ - children, - hasBorder = true, - variant, -}) => ( - - {children} - -); - -type HomeProps = { - recentPosts: RecentArticle[]; - translation?: Messages; -}; - -/** - * Home page. + * @returns {JSX.Element} - The cards list. */ -const HomePage: NextPageWithLayout = ({ recentPosts }) => { +const RecentPosts: FC = ({ posts }): JSX.Element => { const intl = useIntl(); const publicationDate = intl.formatMessage({ defaultMessage: 'Published on:', description: 'HomePage: publication date label', id: 'pT5nHk', }); - const { schema: breadcrumbSchema } = useBreadcrumb({ - title: '', - url: `/`, - }); - - /** - * Get a cards list of recent posts. - * - * @returns {JSX.Element} - The cards list. - */ - const getRecentPosts = (): JSX.Element => { - const listClass = `${styles.list} ${styles['list--cards']}`; - return ( - - {recentPosts.map((post) => ( + return ( + + {posts.map((post) => { + const postUrl = `${ROUTES.ARTICLE}/${post.slug}`; + const cardLabel = intl.formatMessage( + { + defaultMessage: 'View {pageTitle}', + description: 'RecentPosts: card accessible name', + id: 'mWZU4R', + }, + { + pageTitle: post.title, + } + ); + const coverLabel = intl.formatMessage( + { + defaultMessage: 'Cover of {pageTitle}', + description: 'RecentPosts: card cover accessible name', + id: 'kq+fzI', + }, + { + pageTitle: post.title, + } + ); + + return ( - + + ) : undefined } @@ -285,65 +100,57 @@ const HomePage: NextPageWithLayout = ({ recentPosts }) => { } isCentered - linkTo={`${ROUTES.ARTICLE}/${post.slug}`} + linkTo={postUrl} > {post.title} - ))} - - ); - }; + ); + })} + + ); +}; - const components: MDXComponents = { +const getComponents = (recentPosts: RecentArticle[]): MDXComponents => { + return { ...mdxComponents, - CodingLinks, - ColdarkRepos, - Column, - Grid: StyledGrid, - LibreLinks, - MoreLinks, - RecentPosts: getRecentPosts, - Section: HomePageSection, - ShaarliLink, + RecentPosts: () => , }; +}; + +type HomeProps = { + recentPosts: RecentArticle[]; + translation?: Messages; +}; + +/** + * Home page. + */ +const HomePage: NextPageWithLayout = ({ recentPosts }) => { + const { schema: breadcrumbSchema } = useBreadcrumb({ + title: '', + url: ROUTES.HOME, + }); - const pageTitle = intl.formatMessage( - { - defaultMessage: '{websiteName} | Front-end developer: WordPress/React', - description: 'HomePage: SEO - Page title', - id: 'PXp2hv', - }, - { websiteName: CONFIG.name } - ); - const pageDescription = intl.formatMessage( - { - defaultMessage: - '{websiteName} is a front-end developer located in France. He codes and he writes mostly about web development and open-source.', - description: 'HomePage: SEO - Meta description', - id: 'tMuNTy', - }, - { websiteName: CONFIG.name } - ); const webpageSchema = getWebPageSchema({ - description: pageDescription, + description: meta.seo.description, locale: CONFIG.locales.defaultLocale, - slug: '', - title: pageTitle, + slug: ROUTES.HOME, + title: meta.seo.title, }); const schemaJsonLd = getSchemaJson([webpageSchema]); return ( - <> + - {pageTitle} + {meta.seo.title} {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} - + - - + +