aboutsummaryrefslogtreecommitdiffstats
path: root/src/pages/projets
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-09-26 15:54:28 +0200
committerArmand Philippot <git@armandphilippot.com>2023-10-24 12:23:48 +0200
commit70efcfeaa0603415dd992cb662d8efb960e6e49a (patch)
tree5d37e98fae9aa7e5c3d8ef30a10db9fed9b63e36 /src/pages/projets
parent31695306bfed44409f03006ea717fd2cceff8f87 (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].tsx134
-rw-r--r--src/pages/projets/index.tsx37
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 (
- <>
- ⭐&nbsp;
- <Link href={`https://github.com/${repos!.github}/stargazers`}>
- {stars}
- </Link>
- </>
- );
- }
+ return (
+ <>
+ ⭐&nbsp;
+ <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