diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-01-20 16:23:48 +0100 | 
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-01-20 16:23:48 +0100 | 
| commit | 8966fde6ff520cfbe74c031c8b2e3a66d298b172 (patch) | |
| tree | 9144e961db587adb22bff88a23c6881ea7a935f9 /src/pages/projet | |
| parent | f5ba1046b13acd239c472e361f345902937662fb (diff) | |
chore: add single project view
Diffstat (limited to 'src/pages/projet')
| -rw-r--r-- | src/pages/projet/[slug].tsx | 154 | 
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; | 
