summaryrefslogtreecommitdiffstats
path: root/src/pages
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-04-29 12:13:34 +0200
committerArmand Philippot <git@armandphilippot.com>2022-04-29 18:30:05 +0200
commit7e16f500cb7bc0cfd8bafbf6bb1555704f771231 (patch)
treebfc2b4a475cb06a787e2c4bdf284165644e82952 /src/pages
parent5324664e87bedfaa01ba62c0c847ef5b861e69b3 (diff)
chore: remove old pages, components, helpers and types
Since I'm using new components, I will also rewrite the GraphQL queries so it is easier to start from scratch.
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/404.tsx85
-rw-r--r--src/pages/_app.tsx9
-rw-r--r--src/pages/article/[slug].tsx291
-rw-r--r--src/pages/blog/index.tsx269
-rw-r--r--src/pages/blog/page/[id].tsx205
-rw-r--r--src/pages/contact.tsx151
-rw-r--r--src/pages/cv.tsx181
-rw-r--r--src/pages/index.tsx241
-rw-r--r--src/pages/mentions-legales.tsx150
-rw-r--r--src/pages/projet/[slug].tsx186
-rw-r--r--src/pages/projets.tsx128
-rw-r--r--src/pages/recherche/index.tsx213
-rw-r--r--src/pages/sujet/[slug].tsx224
-rw-r--r--src/pages/thematique/[slug].tsx214
14 files changed, 4 insertions, 2543 deletions
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
deleted file mode 100644
index 24c6951..0000000
--- a/src/pages/404.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { settings } from '@utils/config';
-import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import Link from 'next/link';
-import { FormattedMessage, useIntl } from 'react-intl';
-
-const Error404: NextPageWithLayout = () => {
- const intl = useIntl();
-
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Error 404: Page not found - {websiteName}',
- description: '404Page: SEO - Page title',
- id: '310o3F',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage({
- defaultMessage: 'Page not found.',
- description: '404Page: SEO - Meta description',
- id: '48Ww//',
- });
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- </Head>
- <div className={`${styles.article} ${styles['article--no-comments']}`}>
- <PostHeader
- title={intl.formatMessage({
- defaultMessage: 'Page not found',
- description: '404Page: page title',
- id: 'OccTWi',
- })}
- />
- <div className={styles.body}>
- <FormattedMessage
- defaultMessage="Sorry, it seems that the page your are looking for does not exist. If you think this path should work, feel free to <link>contact me</link> with the necessary information so that I can fix the problem."
- description="404Page: page body"
- id="ZWh78Y"
- values={{
- link: (chunks: string) => (
- <Link href="/contact/">
- <a>{chunks}</a>
- </Link>
- ),
- }}
- />
- </div>
- </div>
- </>
- );
-};
-
-Error404.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const intl = await getIntlInstance();
- const breadcrumbTitle = intl.formatMessage({
- defaultMessage: 'Error 404',
- description: '404Page: breadcrumb item',
- id: 'ywkCsK',
- });
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- translation,
- },
- };
-};
-
-export default Error404;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 84c2469..939b337 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,17 +1,16 @@
-import { AppPropsWithLayout } from '@ts/types/app';
import { settings } from '@utils/config';
import { AckeeProvider } from '@utils/providers/ackee';
import { PrismThemeProvider } from '@utils/providers/prism-theme';
import { ThemeProvider } from 'next-themes';
+import { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import { IntlProvider } from 'react-intl';
import '../styles/globals.scss';
-const MyApp = ({ Component, pageProps }: AppPropsWithLayout) => {
+const App = ({ Component, pageProps }: AppProps) => {
const { locale, defaultLocale } = useRouter();
const appLocale: string = locale || settings.locales.defaultLocale;
- const getLayout = Component.getLayout ?? ((page) => page);
return (
<AckeeProvider domain={settings.ackee.url} siteId={settings.ackee.siteId}>
<IntlProvider
@@ -25,7 +24,7 @@ const MyApp = ({ Component, pageProps }: AppPropsWithLayout) => {
enableSystem={true}
>
<PrismThemeProvider>
- {getLayout(<Component {...pageProps} />)}
+ <Component {...pageProps} />
</PrismThemeProvider>
</ThemeProvider>
</IntlProvider>
@@ -33,4 +32,4 @@ const MyApp = ({ Component, pageProps }: AppPropsWithLayout) => {
);
};
-export default MyApp;
+export default App;
diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
deleted file mode 100644
index 27a6f7b..0000000
--- a/src/pages/article/[slug].tsx
+++ /dev/null
@@ -1,291 +0,0 @@
-import CommentForm from '@components/CommentForm/CommentForm';
-import CommentsList from '@components/CommentsList/CommentsList';
-import { getLayout } from '@components/Layouts/Layout';
-import PostFooter from '@components/PostFooter/PostFooter';
-import PostHeader from '@components/PostHeader/PostHeader';
-import Sidebar from '@components/Sidebar/Sidebar';
-import Spinner from '@components/Spinner/Spinner';
-import { Sharing, ToC } from '@components/Widgets';
-import {
- getAllPostsSlug,
- getCommentsByPostId,
- getPostBySlug,
-} from '@services/graphql/queries';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { ArticleMeta, ArticleProps } from '@ts/types/articles';
-import { PrismDefaultPlugins, PrismPlugins } from '@ts/types/prism';
-import { settings } from '@utils/config';
-import { getFormattedPaths } from '@utils/helpers/format';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { addPrismClasses } from '@utils/helpers/prism';
-import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import Prism from 'prismjs';
-import { ParsedUrlQuery } from 'querystring';
-import { useCallback, useEffect, useMemo } from 'react';
-import { useIntl } from 'react-intl';
-import { Blog, BlogPosting, Graph, WebPage } from 'schema-dts';
-
-const SingleArticle: NextPageWithLayout<ArticleProps> = ({
- comments,
- post,
-}) => {
- const intl = useIntl();
- const router = useRouter();
-
- const loadPrismPlugins = useCallback(
- async (prismPlugins: (PrismDefaultPlugins | PrismPlugins)[]) => {
- for (const plugin of prismPlugins) {
- try {
- if (plugin === 'color-scheme') {
- await import(`@utils/plugins/prism-${plugin}`);
- } else {
- await import(`prismjs/plugins/${plugin}/prism-${plugin}.min.js`);
-
- if (plugin === 'autoloader')
- Prism.plugins.autoloader.languages_path = '/prism/';
- }
- } catch (error) {
- console.error('Article: an error occurred with Prism.');
- console.error(error);
- }
- }
- },
- []
- );
-
- const plugins: (PrismDefaultPlugins | PrismPlugins)[] = useMemo(
- () => [
- 'autoloader',
- 'toolbar',
- 'show-language',
- 'copy-to-clipboard',
- 'color-scheme',
- 'command-line',
- 'line-numbers',
- 'match-braces',
- 'normalize-whitespace',
- ],
- []
- );
-
- useEffect(() => {
- loadPrismPlugins(plugins).then(() => {
- addPrismClasses();
- Prism.highlightAll();
- });
- }, [plugins, loadPrismPlugins]);
-
- if (router.isFallback) return <Spinner />;
-
- const {
- author,
- commentCount,
- content,
- databaseId,
- dates,
- featuredImage,
- info,
- intro,
- seo,
- topics,
- thematics,
- title,
- } = post;
-
- const meta: ArticleMeta = {
- author,
- commentCount: commentCount || undefined,
- dates,
- readingTime: info.readingTime,
- thematics,
- wordsCount: info.wordsCount,
- };
-
- const articleUrl = `${settings.url}${router.asPath}`;
-
- const webpageSchema: WebPage = {
- '@id': `${articleUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- lastReviewed: dates.update,
- name: seo.title,
- description: seo.metaDesc,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${articleUrl}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const blogSchema: Blog = {
- '@id': `${settings.url}/#blog`,
- '@type': 'Blog',
- blogPost: { '@id': `${settings.url}/#article` },
- isPartOf: {
- '@id': `${articleUrl}`,
- },
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- };
-
- const publicationDate = new Date(dates.publication);
- const updateDate = new Date(dates.update);
-
- const blogPostSchema: BlogPosting = {
- '@id': `${settings.url}/#article`,
- '@type': 'BlogPosting',
- name: title,
- description: intro,
- articleBody: content,
- author: { '@id': `${settings.url}/#branding` },
- commentCount: commentCount || undefined,
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- discussionUrl: `${articleUrl}/#comments`,
- editor: { '@id': `${settings.url}/#branding` },
- headline: title,
- image: featuredImage?.sourceUrl,
- inLanguage: settings.locales.defaultLocale,
- isPartOf: {
- '@id': `${settings.url}/blog`,
- },
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${articleUrl}` },
- thumbnailUrl: featuredImage?.sourceUrl,
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, blogSchema, blogPostSchema],
- };
-
- const copyText = intl.formatMessage({
- defaultMessage: 'Copy',
- description: 'Prism: copy button text (no clicked)',
- id: '/ly3AC',
- });
- const copiedText = intl.formatMessage({
- defaultMessage: 'Copied!',
- description: 'Prism: copy button text (clicked)',
- id: 'OV9r1K',
- });
- const errorText = intl.formatMessage({
- defaultMessage: 'Use Ctrl+c to copy',
- description: 'Prism: error text',
- id: 'z9qkcQ',
- });
- const darkTheme = intl.formatMessage({
- defaultMessage: 'Dark Theme 🌙',
- description: 'Prism: toggle dark theme button text',
- id: 'nFMdWI',
- });
- const lightTheme = intl.formatMessage({
- defaultMessage: 'Light Theme 🌞',
- description: 'Prism: toggle light theme button text',
- id: 'Ua2g2p',
- });
-
- return (
- <>
- <Head>
- <title>{seo.title}</title>
- <meta name="description" content={seo.metaDesc} />
- <meta property="og:url" content={`${articleUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={title} />
- <meta property="og:description" content={intro} />
- <meta property="og:image" content={featuredImage?.sourceUrl} />
- <meta property="og:image:alt" content={featuredImage?.altText} />
- </Head>
- <Script
- id="schema-article"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="article"
- className={styles.article}
- data-prismjs-copy={copyText}
- data-prismjs-copy-success={copiedText}
- data-prismjs-copy-error={errorText}
- data-prismjs-color-scheme-dark={darkTheme}
- data-prismjs-color-scheme-light={lightTheme}
- >
- <PostHeader intro={intro} meta={meta} title={title} />
- <Sidebar
- position="left"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Table of Contents',
- description: 'ArticlePage: ToC sidebar aria-label',
- id: '9nhYRA',
- })}
- >
- <ToC />
- </Sidebar>
- <div
- className={styles.body}
- dangerouslySetInnerHTML={{ __html: content }}
- ></div>
- <PostFooter topics={topics} />
- <Sidebar
- position="right"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Sidebar',
- description: 'ArticlePage: right sidebar aria-label',
- id: 'JeYOeA',
- })}
- >
- <Sharing title={title} excerpt={intro} />
- </Sidebar>
- <section id="comments" className={styles.comments}>
- <CommentsList articleId={databaseId} comments={comments} />
- <CommentForm articleId={databaseId} />
- </section>
- </article>
- </>
- );
-};
-
-SingleArticle.getLayout = getLayout;
-
-interface PostParams extends ParsedUrlQuery {
- slug: string;
-}
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const { locale } = context;
- const translation = await loadTranslation(locale);
- const { slug } = context.params as PostParams;
- const post = await getPostBySlug(slug);
- const comments = await getCommentsByPostId(post.databaseId);
- const breadcrumbTitle = post.title;
-
- return {
- props: {
- breadcrumbTitle,
- comments,
- post,
- translation,
- },
- };
-};
-
-export const getStaticPaths: GetStaticPaths = async () => {
- const allSlugs = await getAllPostsSlug();
- const paths = getFormattedPaths(allSlugs);
-
- return {
- paths,
- fallback: true,
- };
-};
-
-export default SingleArticle;
diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx
deleted file mode 100644
index b5ced07..0000000
--- a/src/pages/blog/index.tsx
+++ /dev/null
@@ -1,269 +0,0 @@
-import { Button } from '@components/Buttons';
-import { getLayout } from '@components/Layouts/Layout';
-import Pagination from '@components/Pagination/Pagination';
-import PaginationCursor from '@components/PaginationCursor/PaginationCursor';
-import PostHeader from '@components/PostHeader/PostHeader';
-import PostsList from '@components/PostsList/PostsList';
-import Sidebar from '@components/Sidebar/Sidebar';
-import Spinner from '@components/Spinner/Spinner';
-import { ThematicsList, TopicsList } from '@components/Widgets';
-import {
- getAllThematics,
- getAllTopics,
- getPostsTotal,
- getPublishedPosts,
-} from '@services/graphql/queries';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { BlogPageProps, PostsList as PostsListData } from '@ts/types/blog';
-import { settings } from '@utils/config';
-import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useEffect, useRef, useState } from 'react';
-import { useIntl } from 'react-intl';
-import { Blog as BlogSchema, Graph, WebPage } from 'schema-dts';
-import useSWRInfinite from 'swr/infinite';
-
-const Blog: NextPageWithLayout<BlogPageProps> = ({
- allThematics,
- allTopics,
- posts,
- totalPosts,
-}) => {
- const intl = useIntl();
- const lastPostRef = useRef<HTMLSpanElement>(null);
- const router = useRouter();
- const [isMounted, setIsMounted] = useState<boolean>(false);
-
- useEffect(() => {
- if (typeof window !== undefined) setIsMounted(true);
- }, []);
-
- const getKey = (pageIndex: number, previousData: PostsListData) => {
- if (previousData && !previousData.posts) return null;
-
- return pageIndex === 0
- ? { first: settings.postsPerPage }
- : {
- first: settings.postsPerPage,
- after: previousData.pageInfo.endCursor,
- };
- };
-
- const { data, error, size, setSize } = useSWRInfinite(
- getKey,
- getPublishedPosts,
- { fallbackData: [posts] }
- );
- const [totalPostsCount, setTotalPostsCount] = useState<number>(totalPosts);
-
- useEffect(() => {
- if (data) setTotalPostsCount(data[0].pageInfo.total);
- }, [data]);
-
- const [loadedPostsCount, setLoadedPostsCount] = useState<number>(
- settings.postsPerPage
- );
-
- useEffect(() => {
- if (data && data.length > 0) {
- const newCount =
- settings.postsPerPage +
- data[0].pageInfo.total -
- data[data.length - 1].pageInfo.total;
- setLoadedPostsCount(newCount);
- }
- }, [data]);
-
- const isLoadingInitialData = !data && !error;
- const isLoadingMore: boolean =
- isLoadingInitialData ||
- (size > 0 && data !== undefined && typeof data[size - 1] === 'undefined');
-
- const hasNextPage = data && data[data.length - 1].pageInfo.hasNextPage;
-
- const loadMorePosts = () => {
- if (lastPostRef.current) {
- lastPostRef.current.focus();
- }
- setSize(size + 1);
- };
-
- const getPostsList = () => {
- if (error)
- return intl.formatMessage({
- defaultMessage: 'Failed to load.',
- description: 'BlogPage: failed to load text',
- id: 'C/XGkH',
- });
- if (!data) return <Spinner />;
-
- return <PostsList ref={lastPostRef} data={data} showYears={true} />;
- };
-
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Blog: development, open source - {websiteName}',
- description: 'BlogPage: SEO - Page title',
- id: '+Y+tLK',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage:
- "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.",
- description: 'BlogPage: SEO - Meta description',
- id: '18h/t0',
- },
- { websiteName: settings.name }
- );
- const pageUrl = `${settings.url}${router.asPath}`;
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- inLanguage: settings.locales.defaultLocale,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const blogSchema: BlogSchema = {
- '@id': `${settings.url}/#blog`,
- '@type': 'Blog',
- author: { '@id': `${settings.url}/#branding` },
- creator: { '@id': `${settings.url}/#branding` },
- editor: { '@id': `${settings.url}/#branding` },
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, blogSchema],
- };
-
- const title = intl.formatMessage({
- defaultMessage: 'Blog',
- description: 'BlogPage: page title',
- id: '7TbbIk',
- });
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="website" />
- <meta property="og:title" content={title} />
- <meta property="og:description" content={pageDescription} />
- </Head>
- <Script
- id="schema-blog"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="blog"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader title={title} meta={{ results: totalPostsCount }} />
- <div className={styles.body}>
- {getPostsList()}
- {hasNextPage &&
- (isMounted ? (
- <>
- <PaginationCursor
- current={loadedPostsCount}
- total={totalPostsCount}
- />
- <Button
- isDisabled={isLoadingMore}
- clickHandler={loadMorePosts}
- position="center"
- spacing={true}
- >
- {intl.formatMessage({
- defaultMessage: 'Load more?',
- description: 'BlogPage: load more text',
- id: 'Kqq2cm',
- })}
- </Button>
- </>
- ) : (
- <Pagination baseUrl="/blog" total={totalPostsCount} />
- ))}
- </div>
- <Sidebar
- position="right"
- title={intl.formatMessage({
- defaultMessage: 'Filter by:',
- description: 'BlogPage: sidebar title',
- id: 'KERk7L',
- })}
- >
- <ThematicsList
- initialData={allThematics}
- title={intl.formatMessage({
- defaultMessage: 'Thematics',
- description: 'BlogPage: thematics list widget title',
- id: 'HriY57',
- })}
- />
- <TopicsList
- initialData={allTopics}
- title={intl.formatMessage({
- defaultMessage: 'Topics',
- description: 'BlogPage: topics list widget title',
- id: '2D9tB5',
- })}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-Blog.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const intl = await getIntlInstance();
- const breadcrumbTitle = intl.formatMessage({
- defaultMessage: 'Blog',
- description: 'BlogPage: breadcrumb item',
- id: 'R0eDmw',
- });
- const firstPosts = await getPublishedPosts({ first: settings.postsPerPage });
- const totalPosts = await getPostsTotal();
- const allThematics = await getAllThematics();
- const allTopics = await getAllTopics();
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- allThematics,
- allTopics,
- breadcrumbTitle,
- locale,
- posts: firstPosts,
- totalPosts,
- translation,
- },
- };
-};
-
-export default Blog;
diff --git a/src/pages/blog/page/[id].tsx b/src/pages/blog/page/[id].tsx
deleted file mode 100644
index 6c4d2f8..0000000
--- a/src/pages/blog/page/[id].tsx
+++ /dev/null
@@ -1,205 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import Pagination from '@components/Pagination/Pagination';
-import PostHeader from '@components/PostHeader/PostHeader';
-import PostsList from '@components/PostsList/PostsList';
-import Sidebar from '@components/Sidebar/Sidebar';
-import { ThematicsList, TopicsList } from '@components/Widgets';
-import {
- getAllThematics,
- getAllTopics,
- getEndCursor,
- getPostsTotal,
- getPublishedPosts,
-} from '@services/graphql/queries';
-import { NextPageWithLayout } from '@ts/types/app';
-import { BlogPageProps } from '@ts/types/blog';
-import { settings } from '@utils/config';
-import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useIntl } from 'react-intl';
-import { Blog, Graph, WebPage } from 'schema-dts';
-import styles from '@styles/pages/Page.module.scss';
-import { getFormattedPageNumbers } from '@utils/helpers/format';
-import { useEffect } from 'react';
-import Spinner from '@components/Spinner/Spinner';
-
-const BlogPage: NextPageWithLayout<BlogPageProps> = ({
- allThematics,
- allTopics,
- posts,
- totalPosts,
-}) => {
- const intl = useIntl();
- const router = useRouter();
- const pageNumber = Number(router.query.id);
-
- useEffect(() => {
- if (router.query.id === '1') router.push('/blog');
- }, [router]);
-
- if (router.isFallback) return <Spinner />;
-
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Blog - Page {number} - {websiteName}',
- description: 'BlogPage: SEO - Page title',
- id: '8w+jnD',
- },
- { number: pageNumber, websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage:
- "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.",
- description: 'BlogPage: SEO - Meta description',
- id: '18h/t0',
- },
- { websiteName: settings.name }
- );
- const pageUrl = `${settings.url}${router.asPath}`;
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- inLanguage: settings.locales.defaultLocale,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const blogSchema: Blog = {
- '@id': `${settings.url}/#blog`,
- '@type': 'Blog',
- author: { '@id': `${settings.url}/#branding` },
- creator: { '@id': `${settings.url}/#branding` },
- editor: { '@id': `${settings.url}/#branding` },
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, blogSchema],
- };
-
- const title = intl.formatMessage({
- defaultMessage: 'Blog',
- description: 'BlogPage: page title',
- id: '7TbbIk',
- });
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="website" />
- <meta property="og:title" content={title} />
- <meta property="og:description" content={pageDescription} />
- </Head>
- <Script
- id="schema-blog"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="blog"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader title={title} meta={{ results: totalPosts }} />
- <div className={styles.body}>
- <PostsList data={[posts]} showYears={true} />
- <Pagination baseUrl="/blog" total={totalPosts} />
- </div>
- <Sidebar
- position="right"
- title={intl.formatMessage({
- defaultMessage: 'Filter by:',
- description: 'BlogPage: sidebar title',
- id: 'KERk7L',
- })}
- >
- <ThematicsList
- initialData={allThematics}
- title={intl.formatMessage({
- defaultMessage: 'Thematics',
- description: 'BlogPage: thematics list widget title',
- id: 'HriY57',
- })}
- />
- <TopicsList
- initialData={allTopics}
- title={intl.formatMessage({
- defaultMessage: 'Topics',
- description: 'BlogPage: topics list widget title',
- id: '2D9tB5',
- })}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-BlogPage.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const intl = await getIntlInstance();
- const breadcrumbTitle = intl.formatMessage({
- defaultMessage: 'Blog',
- description: 'BlogPage: breadcrumb item',
- id: 'R0eDmw',
- });
- const { locale, params } = context;
- const queriedPageNumber = params ? Number(params.id) : 1;
- const queriedPostsNumber = settings.postsPerPage * queriedPageNumber;
- const endCursor =
- queriedPostsNumber === 1
- ? undefined
- : await getEndCursor({ first: queriedPostsNumber });
- const posts = await getPublishedPosts({
- first: settings.postsPerPage,
- after: endCursor,
- });
- const totalPosts = await getPostsTotal();
- const allThematics = await getAllThematics();
- const allTopics = await getAllTopics();
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- allThematics,
- allTopics,
- breadcrumbTitle,
- locale,
- posts,
- totalPosts,
- translation,
- },
- };
-};
-
-export default BlogPage;
-
-export const getStaticPaths: GetStaticPaths = async () => {
- const totalPosts = await getPostsTotal();
- const totalPages = Math.floor(totalPosts / settings.postsPerPage);
- const paths = getFormattedPageNumbers(totalPages);
-
- return {
- paths,
- fallback: true,
- };
-};
diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx
deleted file mode 100644
index 5934dd9..0000000
--- a/src/pages/contact.tsx
+++ /dev/null
@@ -1,151 +0,0 @@
-import ContactForm from '@components/ContactForm/ContactForm';
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import Sidebar from '@components/Sidebar/Sidebar';
-import { SocialMedia } from '@components/Widgets';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { settings } from '@utils/config';
-import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useIntl } from 'react-intl';
-import { ContactPage as ContactPageSchema, Graph, WebPage } from 'schema-dts';
-
-const ContactPage: NextPageWithLayout = () => {
- const intl = useIntl();
- const router = useRouter();
-
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Contact form - {websiteName}',
- description: 'ContactPage: SEO - Page title',
- id: 'Y3qRib',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage:
- "Contact {websiteName} through its website. All you need to do it's to fill the contact form.",
- description: 'ContactPage: SEO - Meta description',
- id: 'OIffB4',
- },
- { websiteName: settings.name }
- );
- const pageUrl = `${settings.url}${router.asPath}`;
- const title = intl.formatMessage({
- defaultMessage: 'Contact',
- description: 'ContactPage: page title',
- id: 'AN9iy7',
- });
- const intro = intl.formatMessage({
- defaultMessage: 'Please fill the form to contact me.',
- description: 'ContactPage: page introduction',
- id: '8Ls2mD',
- });
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${pageUrl}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const contactSchema: ContactPageSchema = {
- '@id': `${settings.url}/#contact`,
- '@type': 'ContactPage',
- name: title,
- description: intro,
- author: { '@id': `${settings.url}/#branding` },
- creator: { '@id': `${settings.url}/#branding` },
- editor: { '@id': `${settings.url}/#branding` },
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, contactSchema],
- };
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={title} />
- <meta property="og:description" content={intro} />
- </Head>
- <Script
- id="schema-contact"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="contact"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader title={title} intro={intro} />
- <div className={styles.body}>
- <p>
- {intl.formatMessage({
- defaultMessage: 'All fields marked with * are required.',
- description: 'ContactPage: required fields text',
- id: 'txusHd',
- })}
- </p>
- <ContactForm />
- </div>
- <Sidebar position="right">
- <SocialMedia
- title={intl.formatMessage({
- defaultMessage: 'Find me elsewhere',
- description: 'ContactPage: social media widget title',
- id: 'Qh2CwH',
- })}
- github={true}
- gitlab={true}
- linkedin={true}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-ContactPage.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const intl = await getIntlInstance();
- const breadcrumbTitle = intl.formatMessage({
- defaultMessage: 'Contact',
- description: 'ContactPage: breadcrumb item',
- id: 'CzTbM4',
- });
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- translation,
- },
- };
-};
-
-export default ContactPage;
diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx
deleted file mode 100644
index 71eb449..0000000
--- a/src/pages/cv.tsx
+++ /dev/null
@@ -1,181 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import Sidebar from '@components/Sidebar/Sidebar';
-import { CVPreview, SocialMedia, ToC } from '@components/Widgets';
-import CVContent, { intro, meta, pdf, image } from '@content/pages/cv.mdx';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { ArticleMeta } from '@ts/types/articles';
-import { settings } from '@utils/config';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useIntl } from 'react-intl';
-import { AboutPage, Graph, WebPage } from 'schema-dts';
-
-const CV: NextPageWithLayout = () => {
- const intl = useIntl();
- const router = useRouter();
- const dates = {
- publication: meta.publishedOn,
- update: meta.updatedOn,
- };
-
- const pageMeta: ArticleMeta = {
- dates,
- };
- const pageUrl = `${settings.url}${router.asPath}`;
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'CV Front-end developer - {websiteName}',
- description: 'CVPage: SEO - Page title',
- id: 'Y1ZdJ6',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage:
- 'Discover the curriculum of {websiteName}, front-end developer located in France: skills, experiences and training.',
- description: 'CVPage: SEO - Meta description',
- id: 'bBdMGm',
- },
- { websiteName: settings.name }
- );
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${pageUrl}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const publicationDate = new Date(dates.publication);
- const updateDate = new Date(dates.update);
-
- const cvSchema: AboutPage = {
- '@id': `${settings.url}/#cv`,
- '@type': 'AboutPage',
- name: pageTitle,
- description: intro,
- author: { '@id': `${settings.url}/#branding` },
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- image,
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- thumbnailUrl: image,
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, cvSchema],
- };
-
- const title = intl.formatMessage(
- {
- defaultMessage: "{name}'s CV",
- description: 'CVPage: page title',
- id: 'Mj2BQf',
- },
- { name: settings.name }
- );
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={title} />
- <meta property="og:description" content={intro} />
- <meta property="og:image" content={image} />
- <meta property="og:image:alt" content={title} />
- </Head>
- <Script
- id="schema-cv"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="cv"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader intro={intro} meta={pageMeta} title={meta.title} />
- <Sidebar
- position="left"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Table of Contents',
- description: 'CVPage: ToC sidebar aria-label',
- id: 'g4DckL',
- })}
- >
- <ToC />
- </Sidebar>
- <div className={styles.body}>
- <CVContent />
- </div>
- <Sidebar
- position="right"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Sidebar',
- description: 'CVPage: right sidebar aria-label',
- id: 'QHOm5t',
- })}
- >
- <CVPreview
- title={intl.formatMessage({
- defaultMessage: 'Others formats',
- description: 'CVPage: cv preview widget title',
- id: 'B9OCyV',
- })}
- imgSrc={image}
- pdf={pdf}
- />
- <SocialMedia
- title={intl.formatMessage({
- defaultMessage: 'Open-source projects',
- description: 'CVPage: social media widget title',
- id: '+Dre5J',
- })}
- github={true}
- gitlab={true}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-CV.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const breadcrumbTitle = meta.title;
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- translation,
- },
- };
-};
-
-export default CV;
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
deleted file mode 100644
index ca0a809..0000000
--- a/src/pages/index.tsx
+++ /dev/null
@@ -1,241 +0,0 @@
-import FeedIcon from '@assets/images/icon-feed.svg';
-import { ButtonLink } from '@components/Buttons';
-import { ContactIcon } from '@components/Icons';
-import Layout from '@components/Layouts/Layout';
-import { ResponsiveImage } from '@components/MDX';
-import { RecentPosts } from '@components/Widgets';
-import HomePageContent from '@content/pages/homepage.mdx';
-import { getPublishedPosts } from '@services/graphql/queries';
-import styles from '@styles/pages/Home.module.scss';
-import { NextPageWithLayout, ResponsiveImageProps } from '@ts/types/app';
-import { PostsList } from '@ts/types/blog';
-import { settings } from '@utils/config';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { NestedMDXComponents } from 'mdx/types';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import Script from 'next/script';
-import type { ReactElement } from 'react';
-import { useIntl } from 'react-intl';
-import { Graph, WebPage } from 'schema-dts';
-
-type HomePageProps = {
- recentPosts: PostsList;
-};
-
-const Home: NextPageWithLayout<HomePageProps> = ({
- recentPosts,
-}: {
- recentPosts: PostsList;
-}) => {
- const intl = useIntl();
-
- const CodingLinks = () => {
- return (
- <ul className={styles['links-list']}>
- <li>
- <ButtonLink target="/thematique/developpement-web">
- {intl.formatMessage({
- defaultMessage: 'Web development',
- description: 'HomePage: link to web development thematic',
- id: 'vkF/RP',
- })}
- </ButtonLink>
- </li>
- <li>
- <ButtonLink target="/projets">
- {intl.formatMessage({
- defaultMessage: 'Projects',
- description: 'HomePage: link to projects',
- id: 'N44SOc',
- })}
- </ButtonLink>
- </li>
- </ul>
- );
- };
-
- const ColdarkRepos = () => {
- return (
- <ul className={styles['links-list']}>
- <li>
- <ButtonLink
- target="https://github.com/ArmandPhilippot/coldark"
- isExternal={true}
- >
- Github
- </ButtonLink>
- </li>
- <li>
- <ButtonLink
- target="https://gitlab.com/ArmandPhilippot/coldark"
- isExternal={true}
- >
- Gitlab
- </ButtonLink>
- </li>
- </ul>
- );
- };
-
- const LibreLinks = () => {
- return (
- <ul className={styles['links-list']}>
- <li>
- <ButtonLink target="/thematique/libre">
- {intl.formatMessage({
- defaultMessage: 'Free',
- description: 'HomePage: link to free thematic',
- id: 'w8GrOf',
- })}
- </ButtonLink>
- </li>
- <li>
- <ButtonLink target="/thematique/linux">
- {intl.formatMessage({
- defaultMessage: 'Linux',
- description: 'HomePage: link to Linux thematic',
- id: 'jASD7k',
- })}
- </ButtonLink>
- </li>
- </ul>
- );
- };
-
- const ShaarliLink = () => {
- return (
- <ul className={styles['links-list']}>
- <li>
- <ButtonLink target="https://shaarli.armandphilippot.com/">
- {intl.formatMessage({
- defaultMessage: 'Shaarli',
- description: 'HomePage: link to Shaarli',
- id: 'i5L19t',
- })}
- </ButtonLink>
- </li>
- </ul>
- );
- };
-
- const MoreLinks = () => {
- return (
- <ul className={styles['links-list']}>
- <li>
- <ButtonLink target="/contact">
- <ContactIcon />
- {intl.formatMessage({
- defaultMessage: 'Contact me',
- description: 'HomePage: contact button text',
- id: 'sO/Iwj',
- })}
- </ButtonLink>
- </li>
- <li>
- <ButtonLink target="/feed">
- <FeedIcon className={styles['icon--feed']} />
- {intl.formatMessage({
- defaultMessage: 'Subscribe',
- description: 'HomePage: RSS feed subscription text',
- id: 'T4YA64',
- })}
- </ButtonLink>
- </li>
- </ul>
- );
- };
-
- const getRecentPosts = () => {
- return <RecentPosts posts={recentPosts} />;
- };
-
- const components: NestedMDXComponents = {
- CodingLinks: CodingLinks,
- ColdarkRepos: ColdarkRepos,
- Image: (props: ResponsiveImageProps) => ResponsiveImage({ ...props }),
- LibreLinks: LibreLinks,
- MoreLinks: MoreLinks,
- RecentPosts: getRecentPosts,
- ShaarliLink: ShaarliLink,
- };
-
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: '{websiteName} | Front-end developer: WordPress/React',
- description: 'HomePage: SEO - Page title',
- id: 'PXp2hv',
- },
- { websiteName: settings.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: settings.name }
- );
-
- const webpageSchema: WebPage = {
- '@id': `${settings.url}/#home`,
- '@type': 'WebPage',
- name: pageTitle,
- description: pageDescription,
- author: { '@id': `${settings.url}/#branding` },
- creator: { '@id': `${settings.url}/#branding` },
- editor: { '@id': `${settings.url}/#branding` },
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema],
- };
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:type" content="website" />
- <meta property="og:url" content={`${settings.url}`} />
- <meta property="og:title" content={pageTitle} />
- <meta property="og:description" content={pageDescription} />
- </Head>
- <Script
- id="schema-homepage"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <div id="home">
- <HomePageContent components={components} />
- </div>
- </>
- );
-};
-
-Home.getLayout = function getLayout(page: ReactElement) {
- return <Layout isHome={true}>{page}</Layout>;
-};
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const { locale } = context;
- const translation = await loadTranslation(locale);
- const recentPosts = await getPublishedPosts({ first: 3 });
-
- return {
- props: {
- recentPosts,
- translation,
- },
- };
-};
-
-export default Home;
diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx
deleted file mode 100644
index b103b5e..0000000
--- a/src/pages/mentions-legales.tsx
+++ /dev/null
@@ -1,150 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import { Link } from '@components/MDX';
-import PostHeader from '@components/PostHeader/PostHeader';
-import Sidebar from '@components/Sidebar/Sidebar';
-import { ToC } from '@components/Widgets';
-import LegalNoticeContent, {
- intro,
- meta,
-} from '@content/pages/legal-notice.mdx';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { ArticleMeta } from '@ts/types/articles';
-import { settings } from '@utils/config';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { NestedMDXComponents } from 'mdx/types';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useIntl } from 'react-intl';
-import { Article, Graph, WebPage } from 'schema-dts';
-
-const LegalNotice: NextPageWithLayout = () => {
- const intl = useIntl();
- const router = useRouter();
- const dates = {
- publication: meta.publishedOn,
- update: meta.updatedOn,
- };
-
- const pageMeta: ArticleMeta = {
- dates,
- };
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Legal notice - {websiteName}',
- description: 'LegalNoticePage: SEO - Page title',
- id: '4zAUSu',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage: "Discover the legal notice of {websiteName}'s website.",
- description: 'LegalNoticePage: SEO - Meta description',
- id: 'uvB+32',
- },
- { websiteName: settings.name }
- );
- const pageUrl = `${settings.url}${router.asPath}`;
- const title = intl.formatMessage({
- defaultMessage: 'Legal notice',
- description: 'LegalNoticePage: page title',
- id: '/IirIt',
- });
- const publicationDate = new Date(dates.publication);
- const updateDate = new Date(dates.update);
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${pageUrl}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const articleSchema: Article = {
- '@id': `${settings.url}/#legal-notice`,
- '@type': 'Article',
- name: title,
- description: intro,
- author: { '@id': `${settings.url}/#branding` },
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- headline: title,
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, articleSchema],
- };
-
- const components: NestedMDXComponents = {
- Link: (props) => Link(props),
- };
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={pageTitle} />
- <meta property="og:description" content={intro} />
- </Head>
- <Script
- id="schema-legal-notice"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="legal-notice"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader intro={intro} meta={pageMeta} title={meta.title} />
- <Sidebar position="left">
- <ToC />
- </Sidebar>
- <div className={styles.body}>
- <LegalNoticeContent components={components} />
- </div>
- </article>
- </>
- );
-};
-
-LegalNotice.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const breadcrumbTitle = meta.title;
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- translation,
- },
- };
-};
-
-export default LegalNotice;
diff --git a/src/pages/projet/[slug].tsx b/src/pages/projet/[slug].tsx
deleted file mode 100644
index 1f09fed..0000000
--- a/src/pages/projet/[slug].tsx
+++ /dev/null
@@ -1,186 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import { CodeBlock, Gallery, Link, ResponsiveImage } from '@components/MDX';
-import PostHeader from '@components/PostHeader/PostHeader';
-import ProjectSummary from '@components/ProjectSummary/ProjectSummary';
-import Sidebar from '@components/Sidebar/Sidebar';
-import { Sharing, ToC } from '@components/Widgets';
-import styles from '@styles/pages/Page.module.scss';
-import {
- NextPageWithLayout,
- Project as ProjectData,
- ProjectProps,
-} from '@ts/types/app';
-import { settings } from '@utils/config';
-import { loadTranslation } from '@utils/helpers/i18n';
-import {
- getAllProjectsFilename,
- getProjectData,
-} from '@utils/helpers/projects';
-import { MDXComponents, NestedMDXComponents } from 'mdx/types';
-import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { ParsedUrlQuery } from 'querystring';
-import { ComponentType } from 'react';
-import { useIntl } from 'react-intl';
-import { Article, Graph, WebPage } from 'schema-dts';
-
-const Project: NextPageWithLayout<ProjectProps> = ({
- project,
-}: {
- project: ProjectData;
-}) => {
- const intl = useIntl();
- const router = useRouter();
- const projectUrl = `${settings.url}${router.asPath}`;
- const { id, intro, meta, title, seo } = project;
- const dates = {
- publication: meta.publishedOn,
- update: meta.updatedOn,
- };
-
- const components: NestedMDXComponents = {
- CodeBlock: (props) => CodeBlock(props),
- Gallery: (props) => Gallery(props),
- Image: (props) => ResponsiveImage({ caption: props.caption, ...props }),
- Link: (props) => Link(props),
- pre: ({ children }) => CodeBlock(children.props),
- };
-
- const ProjectContent: ComponentType<MDXComponents> =
- require(`../../content/projects/${id}.mdx`).default;
-
- const webpageSchema: WebPage = {
- '@id': `${projectUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: seo.title,
- description: seo.description,
- inLanguage: settings.locales.defaultLocale,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const publicationDate = new Date(dates.publication);
- const updateDate = new Date(dates.update);
-
- const articleSchema: Article = {
- '@id': `${settings.url}/project`,
- '@type': 'Article',
- name: title,
- description: intro,
- author: { '@id': `${settings.url}/#branding` },
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- headline: title,
- thumbnailUrl: meta.hasCover ? `/projects/${id}.jpg` : '',
- image: meta.hasCover ? `/projects/${id}.jpg` : '',
- inLanguage: settings.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} />
- </Head>
- <Script
- id="schema-project"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="project"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader title={title} intro={intro} meta={{ dates }} />
- <Sidebar
- position="left"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Table of Contents',
- description: 'ProjectPage: ToC sidebar aria-label',
- id: '6dXfvr',
- })}
- >
- <ToC />
- </Sidebar>
- <div className={styles.body}>
- <ProjectSummary id={id} title={title} meta={meta} />
- <ProjectContent components={components} />
- </div>
- <Sidebar
- position="right"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Sidebar',
- description: 'ProjectPage: right sidebar aria-label',
- id: 'hHrNd0',
- })}
- >
- <Sharing title={title} excerpt={intro} />
- </Sidebar>
- </article>
- </>
- );
-};
-
-Project.getLayout = getLayout;
-
-interface ProjectParams extends ParsedUrlQuery {
- slug: string;
-}
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const { locale } = context;
- const translation = await loadTranslation(locale);
- const { slug } = context.params as ProjectParams;
- const project = await getProjectData(slug);
- const breadcrumbTitle = project.title;
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- 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;
diff --git a/src/pages/projets.tsx b/src/pages/projets.tsx
deleted file mode 100644
index 8a81f39..0000000
--- a/src/pages/projets.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import ProjectsList from '@components/ProjectsList/ProjectsList';
-import PageContent, { meta } from '@content/pages/projects.mdx';
-import styles from '@styles/pages/Projects.module.scss';
-import { Project } from '@ts/types/app';
-import { settings } from '@utils/config';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { getSortedProjects } from '@utils/helpers/projects';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { useIntl } from 'react-intl';
-import { Article, Graph, WebPage } from 'schema-dts';
-
-const Projects = ({ projects }: { projects: Project[] }) => {
- const intl = useIntl();
- const dates = {
- publication: meta.publishedOn,
- update: meta.updatedOn,
- };
- const publicationDate = new Date(dates.publication);
- const updateDate = new Date(dates.update);
- const router = useRouter();
- const pageUrl = `${settings.url}${router.asPath}`;
- const pageTitle = intl.formatMessage(
- {
- defaultMessage: 'Projects: open-source makings - {websiteName}',
- description: 'ProjectsPage: SEO - Page title',
- id: 'SX1z3t',
- },
- { websiteName: settings.name }
- );
- const pageDescription = intl.formatMessage(
- {
- defaultMessage:
- 'Discover {websiteName} projects. Mostly related to web development and open source.',
- description: 'ProjectsPage: SEO - Meta description',
- id: 's6U1Xt',
- },
- { websiteName: settings.name }
- );
-
- const webpageSchema: WebPage = {
- '@id': `${pageUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: pageTitle,
- description: pageDescription,
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${pageUrl}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const articleSchema: Article = {
- '@id': `${settings.url}/#projects`,
- '@type': 'Article',
- name: meta.title,
- description: pageDescription,
- author: { '@id': `${settings.url}/#branding` },
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- headline: meta.title,
- inLanguage: settings.locales.defaultLocale,
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${pageUrl}` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, articleSchema],
- };
-
- return (
- <>
- <Head>
- <title>{pageTitle}</title>
- <meta name="description" content={pageDescription} />
- <meta property="og:url" content={`${pageUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={meta.title} />
- <meta property="og:description" content={pageDescription} />
- </Head>
- <Script
- id="schema-projects"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article id="projects" className={styles.article}>
- <PostHeader title={meta.title} intro={<PageContent />} />
- <div className={styles.body}>
- {projects.length > 0 && <ProjectsList projects={projects} />}
- </div>
- </article>
- </>
- );
-};
-
-Projects.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const breadcrumbTitle = meta.title;
- const { locale } = context;
- const projects: Project[] = await getSortedProjects();
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- projects,
- translation,
- },
- };
-};
-
-export default Projects;
diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx
deleted file mode 100644
index b843f8d..0000000
--- a/src/pages/recherche/index.tsx
+++ /dev/null
@@ -1,213 +0,0 @@
-import { Button } from '@components/Buttons';
-import { getLayout } from '@components/Layouts/Layout';
-import PaginationCursor from '@components/PaginationCursor/PaginationCursor';
-import PostHeader from '@components/PostHeader/PostHeader';
-import PostsList from '@components/PostsList/PostsList';
-import Sidebar from '@components/Sidebar/Sidebar';
-import Spinner from '@components/Spinner/Spinner';
-import { ThematicsList, TopicsList } from '@components/Widgets';
-import { getPublishedPosts } from '@services/graphql/queries';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { PostsList as PostsListData } from '@ts/types/blog';
-import { settings } from '@utils/config';
-import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import { useEffect, useRef, useState } from 'react';
-import { useIntl } from 'react-intl';
-import useSWRInfinite from 'swr/infinite';
-
-const Search: NextPageWithLayout = () => {
- const intl = useIntl();
- const [query, setQuery] = useState('');
- const router = useRouter();
- const lastPostRef = useRef<HTMLSpanElement>(null);
-
- useEffect(() => {
- if (!router.isReady) return;
-
- if (router.query?.s && typeof router.query.s === 'string') {
- setQuery(router.query.s);
- }
- }, [router.isReady, router.query.s]);
-
- const getKey = (pageIndex: number, previousData: PostsListData) => {
- if (previousData && !previousData.posts) return null;
-
- return pageIndex === 0
- ? { first: settings.postsPerPage, searchQuery: query }
- : {
- first: settings.postsPerPage,
- after: previousData.pageInfo.endCursor,
- searchQuery: query,
- };
- };
-
- const { data, error, size, setSize } = useSWRInfinite(
- getKey,
- getPublishedPosts
- );
- const [totalPostsCount, setTotalPostsCount] = useState<number>(0);
-
- useEffect(() => {
- if (data) setTotalPostsCount(data[0].pageInfo.total);
- }, [data]);
-
- const [loadedPostsCount, setLoadedPostsCount] = useState<number>(
- settings.postsPerPage
- );
-
- useEffect(() => {
- if (data && data.length > 0) {
- const newCount =
- settings.postsPerPage +
- data[0].pageInfo.total -
- data[data.length - 1].pageInfo.total;
- setLoadedPostsCount(newCount);
- }
- }, [data]);
-
- const isLoadingInitialData = !data && !error;
- const isLoadingMore: boolean =
- isLoadingInitialData ||
- (size > 0 && data !== undefined && typeof data[size - 1] === 'undefined');
-
- const hasNextPage = data && data[data.length - 1].pageInfo.hasNextPage;
-
- const title = query
- ? intl.formatMessage(
- {
- defaultMessage: 'Search results for {query}',
- description: 'SearchPage: search results text',
- id: 'VSGuGE',
- },
- { query }
- )
- : intl.formatMessage({
- defaultMessage: 'Search',
- description: 'SearchPage: page title',
- id: 'U+35YD',
- });
-
- const description = query
- ? intl.formatMessage(
- {
- defaultMessage: 'Discover search results for {query}',
- description: 'SearchPage: meta description with query',
- id: 'A4LTGq',
- },
- { query }
- )
- : intl.formatMessage(
- {
- defaultMessage: 'Search for a post on {websiteName}',
- description: 'SearchPage: meta description without query',
- id: 'PrIz5o',
- },
- { websiteName: settings.name }
- );
-
- const head = {
- title: `${title} | ${settings.name}`,
- description,
- };
-
- const loadMorePosts = () => {
- if (lastPostRef.current) {
- lastPostRef.current.focus();
- }
- setSize(size + 1);
- };
-
- const getPostsList = () => {
- if (error)
- return intl.formatMessage({
- defaultMessage: 'Failed to load.',
- description: 'SearchPage: failed to load text',
- id: 'fOe8rH',
- });
- if (!data) return <Spinner />;
-
- return <PostsList ref={lastPostRef} data={data} showYears={false} />;
- };
-
- return (
- <>
- <Head>
- <title>{head.title}</title>
- <meta name="description" content={head.description} />
- </Head>
- <article
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader title={title} meta={{ results: totalPostsCount }} />
- <div className={styles.body}>
- {getPostsList()}
- {hasNextPage && (
- <>
- <PaginationCursor
- current={loadedPostsCount}
- total={totalPostsCount}
- />
- <Button
- isDisabled={isLoadingMore}
- clickHandler={loadMorePosts}
- position="center"
- spacing={true}
- >
- {intl.formatMessage({
- defaultMessage: 'Load more?',
- description: 'SearchPage: load more text',
- id: 'pEtJik',
- })}
- </Button>
- </>
- )}
- </div>
- <Sidebar position="right">
- <ThematicsList
- title={intl.formatMessage({
- defaultMessage: 'Thematics',
- description: 'SearchPage: thematics list widget title',
- id: 'Dq6+WH',
- })}
- />
- <TopicsList
- title={intl.formatMessage({
- defaultMessage: 'Topics',
- description: 'SearchPage: topics list widget title',
- id: 'N804XO',
- })}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-Search.getLayout = getLayout;
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const intl = await getIntlInstance();
- const breadcrumbTitle = intl.formatMessage({
- defaultMessage: 'Search',
- description: 'SearchPage: breadcrumb item',
- id: 'TfU6Qm',
- });
- const { locale } = context;
- const translation = await loadTranslation(locale);
-
- return {
- props: {
- breadcrumbTitle,
- locale,
- translation,
- },
- };
-};
-
-export default Search;
diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx
deleted file mode 100644
index 30dd36c..0000000
--- a/src/pages/sujet/[slug].tsx
+++ /dev/null
@@ -1,224 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import PostPreview from '@components/PostPreview/PostPreview';
-import Sidebar from '@components/Sidebar/Sidebar';
-import Spinner from '@components/Spinner/Spinner';
-import { RelatedThematics, ToC, TopicsList } from '@components/Widgets';
-import {
- getAllTopics,
- getAllTopicsSlug,
- getTopicBySlug,
-} from '@services/graphql/queries';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { ArticleMeta } from '@ts/types/articles';
-import { TopicProps, ThematicPreview } from '@ts/types/taxonomies';
-import { settings } from '@utils/config';
-import { getFormattedPaths } from '@utils/helpers/format';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { ParsedUrlQuery } from 'querystring';
-import { useRef } from 'react';
-import { useIntl } from 'react-intl';
-import { Article as Article, Graph, WebPage } from 'schema-dts';
-
-const Topic: NextPageWithLayout<TopicProps> = ({ topic, allTopics }) => {
- const intl = useIntl();
- const relatedThematics = useRef<ThematicPreview[]>([]);
- const router = useRouter();
-
- if (router.isFallback) return <Spinner />;
-
- const updateRelatedThematics = (newThematics: ThematicPreview[]) => {
- newThematics.forEach((thematic) => {
- const thematicIndex = relatedThematics.current.findIndex(
- (relatedThematic) => relatedThematic.id === thematic.id
- );
- const hasThematic = thematicIndex === -1 ? false : true;
-
- if (!hasThematic) relatedThematics.current.push(thematic);
- });
- };
-
- const getPostsList = () => {
- return [...topic.posts].reverse().map((post) => {
- updateRelatedThematics(post.thematics);
-
- return (
- <li key={post.id} className={styles.item}>
- <PostPreview post={post} titleLevel={3} />
- </li>
- );
- });
- };
-
- const meta: ArticleMeta = {
- dates: topic.dates,
- results: topic.posts.length,
- website: topic.officialWebsite,
- };
- const topicUrl = `${settings.url}${router.asPath}`;
-
- const webpageSchema: WebPage = {
- '@id': `${topicUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: topic.seo.title,
- description: topic.seo.metaDesc,
- inLanguage: settings.locales.defaultLocale,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- isPartOf: {
- '@id': `${settings.url}`,
- },
- };
-
- const publicationDate = new Date(topic.dates.publication);
- const updateDate = new Date(topic.dates.update);
-
- const articleSchema: Article = {
- '@id': `${settings.url}/#topic`,
- '@type': 'Article',
- name: topic.title,
- description: topic.intro,
- author: { '@id': `${settings.url}/#branding` },
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- headline: topic.title,
- thumbnailUrl: topic.featuredImage?.sourceUrl,
- image: topic.featuredImage?.sourceUrl,
- inLanguage: settings.locales.defaultLocale,
- isPartOf: { '@id': `${settings.url}/blog` },
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${topicUrl}` },
- subjectOf: { '@id': `${settings.url}/blog` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, articleSchema],
- };
-
- return (
- <>
- <Head>
- <title>{topic.seo.title}</title>
- <meta name="description" content={topic.seo.metaDesc} />
- <meta property="og:url" content={`${topicUrl}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={topic.title} />
- <meta property="og:description" content={topic.intro} />
- <meta property="og:image" content={topic.featuredImage?.sourceUrl} />
- <meta property="og:image:alt" content={topic.featuredImage?.altText} />
- </Head>
- <Script
- id="schema-subject"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="topic"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader
- cover={topic.featuredImage}
- intro={topic.intro}
- meta={meta}
- title={topic.title}
- />
- <Sidebar
- position="left"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Table of Contents',
- description: 'TopicPage: ToC sidebar aria-label',
- id: 'lsDB5G',
- })}
- >
- <ToC />
- </Sidebar>
- <div className={styles.body}>
- <div dangerouslySetInnerHTML={{ __html: topic.content }}></div>
- {topic.posts.length > 0 && (
- <section className={styles.section}>
- <h2>
- {intl.formatMessage(
- {
- defaultMessage: 'All posts in {name}',
- description: 'TopicPage: posts list title',
- id: 'FLkF2R',
- },
- { name: topic.title }
- )}
- </h2>
- <ol className={styles.list}>{getPostsList()}</ol>
- </section>
- )}
- </div>
- <Sidebar
- position="right"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Sidebar',
- description: 'TopicPage: right sidebar aria-label',
- id: 'eu3beS',
- })}
- >
- <RelatedThematics thematics={relatedThematics.current} />
- <TopicsList
- initialData={allTopics}
- title={intl.formatMessage({
- defaultMessage: 'Others topics',
- description: 'TopicPage: topics list widget title',
- id: '+4tiVb',
- })}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-Topic.getLayout = getLayout;
-
-interface PostParams extends ParsedUrlQuery {
- slug: string;
-}
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const { locale } = context;
- const translation = await loadTranslation(locale);
- const { slug } = context.params as PostParams;
- const topic = await getTopicBySlug(slug);
- const allTopics = await getAllTopics();
- const breadcrumbTitle = topic.title;
-
- return {
- props: {
- allTopics,
- breadcrumbTitle,
- locale,
- topic,
- translation,
- },
- };
-};
-
-export const getStaticPaths: GetStaticPaths = async () => {
- const allTopics = await getAllTopicsSlug();
- const paths = getFormattedPaths(allTopics);
-
- return {
- paths,
- fallback: true,
- };
-};
-
-export default Topic;
diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx
deleted file mode 100644
index db22214..0000000
--- a/src/pages/thematique/[slug].tsx
+++ /dev/null
@@ -1,214 +0,0 @@
-import { getLayout } from '@components/Layouts/Layout';
-import PostHeader from '@components/PostHeader/PostHeader';
-import PostPreview from '@components/PostPreview/PostPreview';
-import Sidebar from '@components/Sidebar/Sidebar';
-import Spinner from '@components/Spinner/Spinner';
-import { RelatedTopics, ThematicsList, ToC } from '@components/Widgets';
-import {
- getAllThematics,
- getAllThematicsSlug,
- getThematicBySlug,
-} from '@services/graphql/queries';
-import styles from '@styles/pages/Page.module.scss';
-import { NextPageWithLayout } from '@ts/types/app';
-import { ArticleMeta } from '@ts/types/articles';
-import { TopicPreview, ThematicProps } from '@ts/types/taxonomies';
-import { settings } from '@utils/config';
-import { getFormattedPaths } from '@utils/helpers/format';
-import { loadTranslation } from '@utils/helpers/i18n';
-import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next';
-import Head from 'next/head';
-import { useRouter } from 'next/router';
-import Script from 'next/script';
-import { ParsedUrlQuery } from 'querystring';
-import { useRef } from 'react';
-import { useIntl } from 'react-intl';
-import { Article, Graph, WebPage } from 'schema-dts';
-
-const Thematic: NextPageWithLayout<ThematicProps> = ({
- thematic,
- allThematics,
-}) => {
- const intl = useIntl();
- const relatedTopics = useRef<TopicPreview[]>([]);
- const router = useRouter();
-
- if (router.isFallback) return <Spinner />;
-
- const updateRelatedTopics = (newTopics: TopicPreview[]) => {
- newTopics.forEach((topic) => {
- const topicIndex = relatedTopics.current.findIndex(
- (relatedTopic) => relatedTopic.id === topic.id
- );
- const hasTopic = topicIndex === -1 ? false : true;
-
- if (!hasTopic) relatedTopics.current.push(topic);
- });
- };
-
- const getPostsList = () => {
- return [...thematic.posts].reverse().map((post) => {
- updateRelatedTopics(post.topics);
-
- return (
- <li key={post.id} className={styles.item}>
- <PostPreview post={post} titleLevel={3} />
- </li>
- );
- });
- };
-
- const meta: ArticleMeta = {
- dates: thematic.dates,
- results: thematic.posts.length,
- };
- const thematicUrl = `${settings.url}${router.asPath}`;
-
- const webpageSchema: WebPage = {
- '@id': `${thematicUrl}`,
- '@type': 'WebPage',
- breadcrumb: { '@id': `${settings.url}/#breadcrumb` },
- name: thematic.seo.title,
- description: thematic.seo.metaDesc,
- inLanguage: settings.locales.defaultLocale,
- reviewedBy: { '@id': `${settings.url}/#branding` },
- url: `${settings.url}`,
- };
-
- const publicationDate = new Date(thematic.dates.publication);
- const updateDate = new Date(thematic.dates.update);
-
- const articleSchema: Article = {
- '@id': `${settings.url}/#thematic`,
- '@type': 'Article',
- name: thematic.title,
- description: thematic.intro,
- author: { '@id': `${settings.url}/#branding` },
- copyrightYear: publicationDate.getFullYear(),
- creator: { '@id': `${settings.url}/#branding` },
- dateCreated: publicationDate.toISOString(),
- dateModified: updateDate.toISOString(),
- datePublished: publicationDate.toISOString(),
- editor: { '@id': `${settings.url}/#branding` },
- headline: thematic.title,
- inLanguage: settings.locales.defaultLocale,
- isPartOf: { '@id': `${settings.url}/blog` },
- license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
- mainEntityOfPage: { '@id': `${thematicUrl}` },
- subjectOf: { '@id': `${settings.url}/blog` },
- };
-
- const schemaJsonLd: Graph = {
- '@context': 'https://schema.org',
- '@graph': [webpageSchema, articleSchema],
- };
-
- return (
- <>
- <Head>
- <title>{thematic.seo.title}</title>
- <meta name="description" content={thematic.seo.metaDesc} />
- <meta property="og:url" content={`${thematic}`} />
- <meta property="og:type" content="article" />
- <meta property="og:title" content={thematic.title} />
- <meta property="og:description" content={thematic.intro} />
- </Head>
- <Script
- id="schema-thematic"
- type="application/ld+json"
- dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- />
- <article
- id="thematic"
- className={`${styles.article} ${styles['article--no-comments']}`}
- >
- <PostHeader intro={thematic.intro} meta={meta} title={thematic.title} />
- <Sidebar
- position="left"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Table of Contents',
- description: 'ThematicPage: ToC sidebar aria-label',
- id: 'YwvYfw',
- })}
- >
- <ToC />
- </Sidebar>
- <div className={styles.body}>
- <div dangerouslySetInnerHTML={{ __html: thematic.content }}></div>
- {thematic.posts.length > 0 && (
- <section className={styles.section}>
- <h2>
- {intl.formatMessage(
- {
- defaultMessage: 'All posts in {name}',
- description: 'ThematicPage: posts list title',
- id: 'P7fxX2',
- },
- { name: thematic.title }
- )}
- </h2>
- <ol className={styles.list}>{getPostsList()}</ol>
- </section>
- )}
- </div>
- <Sidebar
- position="right"
- ariaLabel={intl.formatMessage({
- defaultMessage: 'Sidebar',
- description: 'ThematicPage: right sidebar aria-label',
- id: 'syLgY9',
- })}
- >
- <RelatedTopics topics={relatedTopics.current} />
- <ThematicsList
- initialData={allThematics}
- title={intl.formatMessage({
- defaultMessage: 'Others thematics',
- description: 'ThematicPage: thematics list widget title',
- id: 'norrGp',
- })}
- />
- </Sidebar>
- </article>
- </>
- );
-};
-
-Thematic.getLayout = getLayout;
-
-interface PostParams extends ParsedUrlQuery {
- slug: string;
-}
-
-export const getStaticProps: GetStaticProps = async (
- context: GetStaticPropsContext
-) => {
- const { locale } = context;
- const translation = await loadTranslation(locale);
- const { slug } = context.params as PostParams;
- const thematic = await getThematicBySlug(slug);
- const allThematics = await getAllThematics();
- const breadcrumbTitle = thematic.title;
-
- return {
- props: {
- allThematics,
- breadcrumbTitle,
- locale,
- thematic,
- translation,
- },
- };
-};
-
-export const getStaticPaths: GetStaticPaths = async () => {
- const allSlugs = await getAllThematicsSlug();
- const paths = getFormattedPaths(allSlugs);
-
- return {
- paths,
- fallback: true,
- };
-};
-
-export default Thematic;