diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-09-26 15:54:28 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-10-24 12:23:48 +0200 |
| commit | 70efcfeaa0603415dd992cb662d8efb960e6e49a (patch) | |
| tree | 5d37e98fae9aa7e5c3d8ef30a10db9fed9b63e36 /src/pages/projets | |
| parent | 31695306bfed44409f03006ea717fd2cceff8f87 (diff) | |
refactor(routes): replace hardcoded routes with constants
It makes it easier to change a route if needed and it avoid typo
mistakes.
I also refactored a bit the concerned files to be complient with the
new ESlint config. However, I should rewrite the pages to reduce
the number of statements.
Diffstat (limited to 'src/pages/projets')
| -rw-r--r-- | src/pages/projets/[slug].tsx | 134 | ||||
| -rw-r--r-- | src/pages/projets/index.tsx | 37 |
2 files changed, 91 insertions, 80 deletions
diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx index ba03d9b..9981868 100644 --- a/src/pages/projets/[slug].tsx +++ b/src/pages/projets/[slug].tsx @@ -1,10 +1,11 @@ -import { MDXComponents } from 'mdx/types'; -import { GetStaticPaths, GetStaticProps } from 'next'; +/* eslint-disable max-statements */ +import type { MDXComponents } from 'mdx/types'; +import type { GetStaticPaths, GetStaticProps } from 'next'; import dynamic from 'next/dynamic'; import Head from 'next/head'; import { useRouter } from 'next/router'; import Script from 'next/script'; -import { ComponentType } from 'react'; +import type { ComponentType } from 'react'; import { useIntl } from 'react-intl'; import { Code, @@ -14,20 +15,17 @@ import { Overview, type OverviewMeta, PageLayout, - type PageLayoutProps, ResponsiveImage, type ResponsiveImageProps, Sharing, SocialLink, type SocialWebsite, Spinner, + type MetaData, } from '../../components'; import styles from '../../styles/pages/project.module.scss'; -import { - type NextPageWithLayout, - type ProjectPreview, - type Repos, -} from '../../types'; +import type { NextPageWithLayout, ProjectPreview, Repos } from '../../types'; +import { ROUTES } from '../../utils/constants'; import { capitalize, getSchemaJson, @@ -40,15 +38,17 @@ import { loadTranslation, type Messages, } from '../../utils/helpers/server'; -import { - type RepoData, - useBreadcrumb, - useGithubApi, - useSettings, -} from '../../utils/hooks'; +import { useBreadcrumb, useGithubApi, useSettings } from '../../utils/hooks'; -const BorderedImage = (props: ResponsiveImageProps) => { - return <ResponsiveImage withBorders={true} {...props} />; +const BorderedImage = (props: ResponsiveImageProps) => ( + <ResponsiveImage withBorders={true} {...props} /> +); + +const components: MDXComponents = { + Code, + Gallery, + Image: BorderedImage, + Link, }; type ProjectPageProps = { @@ -65,28 +65,24 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { const intl = useIntl(); const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ title, - url: `/projets/${id}`, + url: `${ROUTES.PROJECTS}/${id}`, }); const ProjectContent: ComponentType<MDXComponents> = dynamic( - () => import(`../../content/projects/${id}.mdx`), + async () => import(`../../content/projects/${id}.mdx`), { loading: () => <Spinner />, } ); - const components: MDXComponents = { - Code, - Gallery, - Image: BorderedImage, - Link, - }; - const { website } = useSettings(); const { asPath } = useRouter(); - const pageUrl = `${website.url}${asPath}`; + const page = { + title: `${seo.title} - ${website.name}`, + url: `${website.url}${asPath}`, + }; - const headerMeta: PageLayoutProps['headerMeta'] = { + const headerMeta: MetaData = { publication: { date: dates.publication }, update: dates.update && dates.update !== dates.publication @@ -97,7 +93,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { /** * Retrieve the repositories links. * - * @param {Repos} repos - A repositories object. + * @param {Repos} repositories - A repositories object. * @returns {JSX.Element[]} - An array of SocialLink. */ const getReposLinks = (repositories: Repos): JSX.Element[] => { @@ -113,43 +109,45 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { return links; }; - const { isError, isLoading, data } = useGithubApi(meta.repos!.github!); + const { isError, isLoading, data } = useGithubApi( + /* + * Repo should be defined for each project so for now it is safe for my + * use-case. However, I should refactored it to handle cases where it is + * not defined. The logic should be extracted in another component I think. + * + * TODO: fix this hardly readable argument + */ + meta.repos ? meta.repos.github ?? '' : '' + ); + + if (isError) return 'Error'; + if (isLoading || !data) return <Spinner />; - const getGithubData = (key: keyof RepoData) => { - if (isError) return 'Error'; - if (isLoading || !data) return <Spinner />; + const getRepoPopularity = (repo: string) => { + const stars = intl.formatMessage( + { + defaultMessage: + '{starsCount, plural, =0 {No stars on Github} one {# star on Github} other {# stars on Github}}', + description: 'ProjectsPage: Github stars count', + id: 'sI7gJK', + }, + { starsCount: data.stargazers_count } + ); + const popularityUrl = `https://github.com/${repo}/stargazers`; - switch (key) { - case 'created_at': - return data.created_at; - case 'updated_at': - return data.updated_at; - case 'stargazers_count': - const stars = intl.formatMessage( - { - defaultMessage: - '{starsCount, plural, =0 {No stars on Github} one {# star on Github} other {# stars on Github}}', - id: 'Gnf1Si', - description: 'Projets: Github stars count', - }, - { starsCount: data.stargazers_count } - ); - return ( - <> - ⭐ - <Link href={`https://github.com/${repos!.github}/stargazers`}> - {stars} - </Link> - </> - ); - } + return ( + <> + ⭐ + <Link href={popularityUrl}>{stars}</Link> + </> + ); }; const overviewData: OverviewMeta = { - creation: data && { date: getGithubData('created_at') as string }, - update: data && { date: getGithubData('updated_at') as string }, + creation: { date: data.created_at }, + update: { date: data.updated_at }, license, - popularity: data && getGithubData('stargazers_count'), + popularity: repos?.github && getRepoPopularity(repos.github), repositories: repos ? getReposLinks(repos) : undefined, technologies, }; @@ -176,16 +174,20 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { return ( <> <Head> - <title>{`${seo.title} - ${website.name}`}</title> + <title>{page.title}</title> + {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} <meta name="description" content={seo.description} /> - <meta property="og:url" content={`${pageUrl}`} /> + <meta property="og:url" content={page.url} /> + {/*eslint-disable-next-line react/jsx-no-literals -- Content allowed */} <meta property="og:type" content="article" /> <meta property="og:title" content={title} /> <meta property="og:description" content={intro} /> </Head> <Script + // eslint-disable-next-line react/jsx-no-literals -- Id allowed id="schema-project" type="application/ld+json" + // eslint-disable-next-line react/no-danger -- Necessary for schema dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }} /> <PageLayout @@ -197,8 +199,9 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => { withToC={true} widgets={[ <Sharing + // eslint-disable-next-line react/jsx-no-literals -- Key allowed key="sharing-widget" - data={{ excerpt: intro, title, url: pageUrl }} + data={{ excerpt: intro, title, url: page.url }} media={[ 'diaspora', 'email', @@ -226,8 +229,7 @@ export const getStaticProps: GetStaticProps<ProjectPageProps> = async ({ params, }) => { const translation = await loadTranslation(locale); - const { slug } = params!; - const project = await getProjectData(slug as string); + const project = await getProjectData(params ? (params.slug as string) : ''); return { props: { @@ -237,7 +239,7 @@ export const getStaticProps: GetStaticProps<ProjectPageProps> = async ({ }; }; -export const getStaticPaths: GetStaticPaths = async () => { +export const getStaticPaths: GetStaticPaths = () => { const filenames = getProjectFilenames(); const paths = filenames.map((filename) => { return { diff --git a/src/pages/projets/index.tsx b/src/pages/projets/index.tsx index a145401..97963dd 100644 --- a/src/pages/projets/index.tsx +++ b/src/pages/projets/index.tsx @@ -1,5 +1,5 @@ -import { MDXComponents } from 'mdx/types'; -import { GetStaticProps } from 'next'; +import type { MDXComponents } from 'mdx/types'; +import type { GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; import Script from 'next/script'; @@ -12,12 +12,13 @@ import { } from '../../components'; import PageContent, { meta } from '../../content/pages/projects.mdx'; import styles from '../../styles/pages/projects.module.scss'; -import { type NextPageWithLayout, type ProjectCard } from '../../types'; +import type { NextPageWithLayout, ProjectCard } from '../../types'; +import { ROUTES } from '../../utils/constants'; import { getSchemaJson, getSinglePageSchema, getWebPageSchema, -} from '../../utils/helpers/'; +} from '../../utils/helpers'; import { getProjectsCard, loadTranslation, @@ -25,6 +26,10 @@ import { } from '../../utils/helpers/server'; import { useBreadcrumb, useSettings } from '../../utils/hooks'; +const components: MDXComponents = { + Link, +}; + type ProjectsPageProps = { projects: ProjectCard[]; translation?: Messages; @@ -37,7 +42,7 @@ const ProjectsPage: NextPageWithLayout<ProjectsPageProps> = ({ projects }) => { const { dates, seo, title } = meta; const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ title, - url: `/projets`, + url: ROUTES.PROJECTS, }); const items: CardsListItem[] = projects.map( @@ -47,18 +52,14 @@ const ProjectsPage: NextPageWithLayout<ProjectsPageProps> = ({ projects }) => { return { cover, id: id as string, - meta: { technologies: technologies }, + meta: { technologies }, tagline, title: projectTitle, - url: `/projets/${slug}`, + url: `${ROUTES.PROJECTS}/${slug}`, }; } ); - const components: MDXComponents = { - Link, - }; - const { website } = useSettings(); const { asPath } = useRouter(); const webpageSchema = getWebPageSchema({ @@ -78,20 +79,28 @@ const ProjectsPage: NextPageWithLayout<ProjectsPageProps> = ({ projects }) => { title, }); const schemaJsonLd = getSchemaJson([webpageSchema, articleSchema]); + const page = { + title: `${seo.title} - ${website.name}`, + url: `${website.url}${asPath}`, + }; return ( <> <Head> - <title>{`${seo.title} - ${website.name}`}</title> + <title>{page.title}</title> + {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} <meta name="description" content={seo.description} /> - <meta property="og:url" content={`${website.url}${asPath}`} /> + <meta property="og:url" content={page.url} /> + {/*eslint-disable-next-line react/jsx-no-literals -- Content allowed */} <meta property="og:type" content="article" /> - <meta property="og:title" content={`${seo.title} - ${website.name}`} /> + <meta property="og:title" content={page.title} /> <meta property="og:description" content={seo.description} /> </Head> <Script + // eslint-disable-next-line react/jsx-no-literals -- Id allowed id="schema-projects" type="application/ld+json" + // eslint-disable-next-line react/no-danger -- Necessary for schema dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }} /> <PageLayout |
