From 732d0943f8041d76262222a092b014f2557085ef Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 2 May 2022 18:57:29 +0200 Subject: chore: add homepage --- src/pages/index.tsx | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 src/pages/index.tsx (limited to 'src/pages/index.tsx') diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 0000000..c965320 --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,365 @@ +import FeedIcon from '@assets/images/icon-feed.svg'; +import ButtonLink from '@components/atoms/buttons/button-link'; +import Envelop from '@components/atoms/icons/envelop'; +import Column, { type ColumnProps } from '@components/atoms/layout/column'; +import Section, { type SectionProps } from '@components/atoms/layout/section'; +import List, { type ListItem } from '@components/atoms/lists/list'; +import ResponsiveImage, { + type ResponsiveImageProps, +} from '@components/molecules/images/responsive-image'; +import Columns, { + type ColumnsProps, +} from '@components/molecules/layout/columns'; +import CardsList, { + type CardsListItem, +} from '@components/organisms/layout/cards-list'; +import Layout from '@components/templates/layout/layout'; +import HomePageContent from '@content/pages/homepage.mdx'; +import { getArticlesCard } from '@services/graphql/articles'; +import styles from '@styles/pages/home.module.scss'; +import { ArticleCard } from '@ts/types/app'; +import { loadTranslation, type Messages } from '@utils/helpers/i18n'; +import useSettings from '@utils/hooks/use-settings'; +import { NestedMDXComponents } from 'mdx/types'; +import { GetStaticProps, NextPage } from 'next'; +import Head from 'next/head'; +import Script from 'next/script'; +import { ReactElement } from 'react'; +import { useIntl } from 'react-intl'; +import { Graph, WebPage } from 'schema-dts'; + +type HomeProps = { + recentPosts: ArticleCard[]; + translation?: Messages; +}; + +/** + * Home page. + */ +const HomePage: NextPage = ({ recentPosts }) => { + const intl = useIntl(); + + /** + * Retrieve a list of coding links. + * + * @returns {JSX.Element} - A list of links. + */ + const CodingLinks = (): JSX.Element => { + const links: ListItem[] = [ + { + id: 'web-development', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Web development', + description: 'HomePage: link to web development thematic', + id: 'vkF/RP', + })} + + ), + }, + { + id: 'projects', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Projects', + description: 'HomePage: link to projects', + id: 'N44SOc', + })} + + ), + }, + ]; + + return ; + }; + + /** + * Retrieve a list of Coldark repositories. + * + * @returns {JSX.Element} - A list of links. + */ + const ColdarkRepos = (): JSX.Element => { + const links: ListItem[] = [ + { + id: 'coldark-github', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Github', + description: 'HomePage: Github link', + id: '3f3PzH', + })} + + ), + }, + { + id: 'coldark-gitlab', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Gitlab', + description: 'HomePage: Gitlab link', + id: '7AnwZ7', + })} + + ), + }, + ]; + + return ; + }; + + /** + * Retrieve a list of links related to Free thematic. + * + * @returns {JSX.Element} - A list of links. + */ + const LibreLinks = (): JSX.Element => { + const links: ListItem[] = [ + { + id: 'free', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Free', + description: 'HomePage: link to free thematic', + id: 'w8GrOf', + })} + + ), + }, + { + id: 'linux', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Linux', + description: 'HomePage: link to Linux thematic', + id: 'jASD7k', + })} + + ), + }, + ]; + + return ; + }; + + /** + * Retrieve the Shaarli link. + * + * @returns {JSX.Element} - A list of links + */ + const ShaarliLink = (): JSX.Element => { + const links: ListItem[] = [ + { + id: 'shaarli', + value: ( + + {intl.formatMessage({ + defaultMessage: 'Shaarli', + description: 'HomePage: link to Shaarli', + id: 'i5L19t', + })} + + ), + }, + ]; + + return ; + }; + + /** + * Retrieve the additional links. + * + * @returns {JSX.Element} - A list of links. + */ + const MoreLinks = (): JSX.Element => { + const links: ListItem[] = [ + { + id: 'contact-me', + value: ( + + + {intl.formatMessage({ + defaultMessage: 'Contact me', + description: 'HomePage: contact button text', + id: 'sO/Iwj', + })} + + ), + }, + { + id: 'rss-feed', + value: ( + + + {intl.formatMessage({ + defaultMessage: 'Subscribe', + description: 'HomePage: RSS feed subscription text', + id: 'T4YA64', + })} + + ), + }, + ]; + + return ; + }; + + /** + * Get a cards list of recent posts. + * + * @returns {JSX.Element} - The cards list. + */ + const getRecentPosts = (): JSX.Element => { + const posts: CardsListItem[] = recentPosts.map((post) => { + return { + cover: post.cover, + id: post.slug, + meta: [ + { + id: 'publication', + term: intl.formatMessage({ + defaultMessage: 'Published on:', + description: 'HomePage: publication date label', + id: 'pT5nHk', + }), + value: [post.dates.publication], + }, + ], + title: post.title, + url: `/article/${post.slug}`, + }; + }); + + return ( + + ); + }; + + /** + * Create the page sections. + * + * @param {object} obj - An object containing the section body. + * @param {ReactElement[]} obj.children - The section body. + * @returns {JSX.Element} A section element. + */ + const getSection = ({ + children, + variant, + }: { + children: ReactElement[]; + variant: SectionProps['variant']; + }): JSX.Element => { + const [headingEl, ...content] = children; + const title = headingEl.props.children; + + return ( +
+ ); + }; + + const components: NestedMDXComponents = { + CodingLinks: CodingLinks, + ColdarkRepos: ColdarkRepos, + Column: (props: ColumnProps) => , + Columns: (props: ColumnsProps) => ( + + ), + Image: (props: ResponsiveImageProps) => , + LibreLinks: LibreLinks, + MoreLinks: MoreLinks, + RecentPosts: getRecentPosts, + Section: getSection, + ShaarliLink: ShaarliLink, + }; + + const { website } = useSettings(); + + const pageTitle = intl.formatMessage( + { + defaultMessage: '{websiteName} | Front-end developer: WordPress/React', + description: 'HomePage: SEO - Page title', + id: 'PXp2hv', + }, + { websiteName: website.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: website.name } + ); + + const webpageSchema: WebPage = { + '@id': `${website.url}/#home`, + '@type': 'WebPage', + name: pageTitle, + description: pageDescription, + author: { '@id': `${website.url}/#branding` }, + creator: { '@id': `${website.url}/#branding` }, + editor: { '@id': `${website.url}/#branding` }, + inLanguage: website.locales.default, + license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr', + reviewedBy: { '@id': `${website.url}/#branding` }, + url: `${website.url}`, + }; + + const schemaJsonLd: Graph = { + '@context': 'https://schema.org', + '@graph': [webpageSchema], + }; + + return ( + + + {pageTitle} + + + + + +