summaryrefslogtreecommitdiffstats
path: root/src/pages
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-01-20 16:23:48 +0100
committerArmand Philippot <git@armandphilippot.com>2022-01-20 16:23:48 +0100
commit8966fde6ff520cfbe74c031c8b2e3a66d298b172 (patch)
tree9144e961db587adb22bff88a23c6881ea7a935f9 /src/pages
parentf5ba1046b13acd239c472e361f345902937662fb (diff)
chore: add single project view
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/projet/[slug].tsx154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/pages/projet/[slug].tsx b/src/pages/projet/[slug].tsx
new file mode 100644
index 0000000..03aa6ea
--- /dev/null
+++ b/src/pages/projet/[slug].tsx
@@ -0,0 +1,154 @@
+import { getLayout } from '@components/Layouts/Layout';
+import PostHeader from '@components/PostHeader/PostHeader';
+import Sidebar from '@components/Sidebar/Sidebar';
+import { ToC } from '@components/Widgets';
+import { config } from '@config/website';
+import styles from '@styles/pages/Page.module.scss';
+import {
+ NextPageWithLayout,
+ Project as ProjectData,
+ ProjectProps,
+} from '@ts/types/app';
+import { loadTranslation } from '@utils/helpers/i18n';
+import {
+ getAllProjectsFilename,
+ getProjectData,
+} from '@utils/helpers/projects';
+import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
+import dynamic from 'next/dynamic';
+import Head from 'next/head';
+import { useRouter } from 'next/router';
+import { ParsedUrlQuery } from 'querystring';
+import { Article, Graph, WebPage } from 'schema-dts';
+
+const Project: NextPageWithLayout<ProjectProps> = ({
+ project,
+}: {
+ project: ProjectData;
+}) => {
+ const router = useRouter();
+ const projectUrl = `${config.url}${router.asPath}`;
+ const { cover, id, intro, meta, title, seo } = project;
+ const dates = {
+ publication: meta.publishedOn,
+ update: meta.updatedOn,
+ };
+
+ const ProjectContent = dynamic(
+ () => import(`../../content/projects/${id}.mdx`)
+ );
+
+ const webpageSchema: WebPage = {
+ '@id': `${projectUrl}`,
+ '@type': 'WebPage',
+ breadcrumb: { '@id': `${config.url}/#breadcrumb` },
+ name: seo.title,
+ description: seo.description,
+ inLanguage: config.locales.defaultLocale,
+ reviewedBy: { '@id': `${config.url}/#branding` },
+ url: `${config.url}`,
+ isPartOf: {
+ '@id': `${config.url}`,
+ },
+ };
+
+ const publicationDate = new Date(dates.publication);
+ const updateDate = new Date(dates.update);
+
+ const articleSchema: Article = {
+ '@id': `${config.url}/subject`,
+ '@type': 'Article',
+ name: title,
+ description: intro,
+ author: { '@id': `${config.url}/#branding` },
+ copyrightYear: publicationDate.getFullYear(),
+ creator: { '@id': `${config.url}/#branding` },
+ dateCreated: publicationDate.toISOString(),
+ dateModified: updateDate.toISOString(),
+ datePublished: publicationDate.toISOString(),
+ editor: { '@id': `${config.url}/#branding` },
+ thumbnailUrl: cover,
+ image: cover,
+ inLanguage: config.locales.defaultLocale,
+ license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
+ mainEntityOfPage: { '@id': `${projectUrl}` },
+ };
+
+ const schemaJsonLd: Graph = {
+ '@context': 'https://schema.org',
+ '@graph': [webpageSchema, articleSchema],
+ };
+
+ return (
+ <>
+ <Head>
+ <title>{seo.title}</title>
+ <meta name="description" content={seo.description} />
+ <meta property="og:url" content={`${projectUrl}`} />
+ <meta property="og:type" content="article" />
+ <meta property="og:title" content={title} />
+ <meta property="og:description" content={intro} />
+ <script
+ type="application/ld+json"
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
+ ></script>
+ </Head>
+ <article
+ id="project"
+ className={`${styles.article} ${styles['article--no-comments']}`}
+ >
+ <PostHeader title={title} intro={intro} meta={{ dates }} />
+ <Sidebar position="left">
+ <ToC />
+ </Sidebar>
+ <div className={styles.body}>
+ <ProjectContent />
+ </div>
+ </article>
+ </>
+ );
+};
+
+Project.getLayout = getLayout;
+
+interface ProjectParams extends ParsedUrlQuery {
+ slug: string;
+}
+
+export const getStaticProps: GetStaticProps = async (
+ context: GetStaticPropsContext
+) => {
+ const translation = await loadTranslation(
+ context.locale!,
+ process.env.NODE_ENV === 'production'
+ );
+ const breadcrumbTitle = '';
+ const { slug } = context.params as ProjectParams;
+ const project = await getProjectData(slug);
+
+ return {
+ props: {
+ breadcrumbTitle,
+ project,
+ translation,
+ },
+ };
+};
+
+export const getStaticPaths: GetStaticPaths = async () => {
+ const filenames = getAllProjectsFilename();
+ const paths = filenames.map((filename) => {
+ return {
+ params: {
+ slug: filename,
+ },
+ };
+ });
+
+ return {
+ paths,
+ fallback: false,
+ };
+};
+
+export default Project;