From b9c1953c79688fc3f536b7927692309c9780b5da Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 6 Jan 2022 17:55:24 +0100 Subject: refactor: reuse PostMeta components on single articles/pages --- src/components/PostHeader/PostHeader.tsx | 82 +++++++-------------- src/components/PostMeta/PostMeta.module.scss | 51 +++++++++++--- src/components/PostMeta/PostMeta.tsx | 102 +++++++++++++++++---------- src/components/PostPreview/PostPreview.tsx | 15 ++-- src/pages/article/[slug].tsx | 25 ++++--- src/pages/contact.tsx | 8 ++- src/pages/cv.tsx | 24 +++++-- src/pages/mentions-legales.tsx | 28 ++++++-- src/pages/sujet/[slug].tsx | 34 ++++----- src/pages/thematique/[slug].tsx | 6 +- src/ts/types/articles.ts | 8 +++ 11 files changed, 220 insertions(+), 163 deletions(-) (limited to 'src') diff --git a/src/components/PostHeader/PostHeader.tsx b/src/components/PostHeader/PostHeader.tsx index 3ee6705..e445b58 100644 --- a/src/components/PostHeader/PostHeader.tsx +++ b/src/components/PostHeader/PostHeader.tsx @@ -1,71 +1,37 @@ -import { t } from '@lingui/macro'; -import { Dates } from '@ts/types/app'; -import { ArticleAuthor } from '@ts/types/articles'; -import { ThematicPreview } from '@ts/types/taxonomies'; -import Link from 'next/link'; -import { useRouter } from 'next/router'; +import PostMeta from '@components/PostMeta/PostMeta'; +import { ArticleMeta } from '@ts/types/articles'; +import { Cover } from '@ts/types/cover'; +import Image from 'next/image'; import styles from './PostHeader.module.scss'; const PostHeader = ({ - author, - dates, + cover, intro, title, - thematics, + meta, }: { - author: ArticleAuthor; - dates: Dates; + cover?: Cover; intro: string; + meta?: ArticleMeta; title: string; - thematics: ThematicPreview[]; }) => { - const { locale } = useRouter(); - - const getAuthor = () => { - return author.firstName - ? `${author.firstName} ${author.lastName}` - : author.name; - }; - - const getLocaleDate = (date: string) => { - const dateOptions: Intl.DateTimeFormatOptions = { - day: 'numeric', - month: 'long', - year: 'numeric', - }; - return new Date(date).toLocaleDateString(locale, dateOptions); - }; - - const getThematics = () => { - return thematics.map((thematic) => { - return ( -
- - {thematic.title} - -
- ); - }); - }; - return ( -
-

{title}

- -
+
+
+

+ {cover && ( + + {cover.altText} + + )} + {title} +

+ {meta && } +
+
); }; diff --git a/src/components/PostMeta/PostMeta.module.scss b/src/components/PostMeta/PostMeta.module.scss index 3ec7daf..ac25828 100644 --- a/src/components/PostMeta/PostMeta.module.scss +++ b/src/components/PostMeta/PostMeta.module.scss @@ -2,17 +2,50 @@ @use "@styles/abstracts/mixins" as mix; .wrapper { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - margin-top: var(--spacing-md); - font-size: var(--font-size-sm); + &--list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-top: var(--spacing-md); + font-size: var(--font-size-sm); - @include mix.media("screen") { - @include mix.dimensions("sm") { + @include mix.media("screen") { + @include mix.dimensions("sm") { + display: flex; + flex-flow: column nowrap; + margin: 0; + composes: meta from "@components/PostPreview/PostPreview.module.scss"; + } + } + } + + &--single { + flex-flow: column wrap; + margin: 0; + padding: 0 var(--spacing-md); + + @include mix.media("screen") { + @include mix.dimensions("xs") { + font-size: var(--font-size-sm); + } + } + + .item { display: flex; - flex-flow: column nowrap; - margin: 0; - composes: meta from "@components/PostPreview/PostPreview.module.scss"; + flex-flow: row wrap; + } + + .term { + margin-right: var(--spacing-2xs); + color: var(--color-primary-darker); + } + + .description { + &:not(:first-of-type) { + &::before { + content: "/"; + margin: 0 var(--spacing-2xs); + } + } } } } diff --git a/src/components/PostMeta/PostMeta.tsx b/src/components/PostMeta/PostMeta.tsx index 776d912..6d40048 100644 --- a/src/components/PostMeta/PostMeta.tsx +++ b/src/components/PostMeta/PostMeta.tsx @@ -1,20 +1,19 @@ import { t } from '@lingui/macro'; -import { ThematicPreview } from '@ts/types/taxonomies'; +import { ArticleMeta } from '@ts/types/articles'; import Link from 'next/link'; import { useRouter } from 'next/router'; import styles from './PostMeta.module.scss'; +type PostMetaMode = 'list' | 'single'; + const PostMeta = ({ - commentCount, - publicationDate, - updateDate, - thematics, + meta, + mode = 'list', }: { - commentCount: number | null; - publicationDate: string; - updateDate: string; - thematics: ThematicPreview[]; + meta: ArticleMeta; + mode?: PostMetaMode; }) => { + const { author, commentCount, dates, thematics, website } = meta; const { locale } = useRouter(); const dateOptions: Intl.DateTimeFormatOptions = { day: 'numeric', @@ -23,20 +22,22 @@ const PostMeta = ({ }; const getThematics = () => { - return thematics.map((thematic) => { - return ( -
- - {thematic.title} - -
- ); - }); + return ( + thematics && + thematics.map((thematic) => { + return ( +
+ + {thematic.title} + +
+ ); + }) + ); }; const getCommentsCount = () => { switch (commentCount) { - case null: case 0: return t`No comments`; case 1: @@ -46,32 +47,57 @@ const PostMeta = ({ } }; + const wrapperClass = styles[`wrapper--${mode}`]; + return ( -
-
-
{t`Published on`}
-
- {new Date(publicationDate).toLocaleDateString(locale, dateOptions)} -
-
- {publicationDate !== updateDate && ( -
-
{t`Updated on`}
-
- {new Date(updateDate).toLocaleDateString(locale, dateOptions)} +
+ {author && ( +
+
{t`Written by`}
+
{author.name}
+
+ )} + {dates && ( +
+
{t`Published on`}
+
+ {new Date(dates.publication).toLocaleDateString( + locale, + dateOptions + )}
)} - {thematics.length > 0 && ( -
-
{thematics.length > 1 ? t`Thematics` : t`Thematic`}
+ {dates && dates.publication !== dates.update && ( +
+
{t`Updated on`}
+
+ {new Date(dates.update).toLocaleDateString(locale, dateOptions)} +
+
+ )} + {thematics && thematics.length > 0 && ( +
+
+ {thematics.length > 1 ? t`Thematics` : t`Thematic`} +
{getThematics()}
)} -
-
{t`Comments`}
- {getCommentsCount()} -
+ {website && ( +
+
{t`Website`}
+
+ {website} +
+
+ )} + {commentCount !== undefined && ( +
+
{t`Comments`}
+ {getCommentsCount()} +
+ )}
); }; diff --git a/src/components/PostPreview/PostPreview.tsx b/src/components/PostPreview/PostPreview.tsx index ccbb9e5..fa8bfd0 100644 --- a/src/components/PostPreview/PostPreview.tsx +++ b/src/components/PostPreview/PostPreview.tsx @@ -1,6 +1,6 @@ import PostMeta from '@components/PostMeta/PostMeta'; import { t } from '@lingui/macro'; -import { ArticlePreview } from '@ts/types/articles'; +import { ArticleMeta, ArticlePreview } from '@ts/types/articles'; import Link from 'next/link'; import styles from './PostPreview.module.scss'; import Image from 'next/image'; @@ -18,6 +18,12 @@ const PostPreview = ({ }) => { const TitleTag = `h${titleLevel}` as keyof JSX.IntrinsicElements; + const meta: ArticleMeta = { + commentCount: post.commentCount ? post.commentCount : 0, + dates: post.dates, + thematics: post.thematics, + }; + return (
{post.featuredImage && Object.keys(post.featuredImage).length > 0 && ( @@ -55,12 +61,7 @@ const PostPreview = ({ - +
); }; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index 493f061..e8df85e 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -9,7 +9,7 @@ import { config } from '@config/website'; import { t } from '@lingui/macro'; import { getAllPostsSlug, getPostBySlug } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; -import { ArticleProps } from '@ts/types/articles'; +import { ArticleMeta, ArticleProps } from '@ts/types/articles'; import { loadTranslation } from '@utils/helpers/i18n'; import { addPrismClasses, translateCopyButton } from '@utils/helpers/prism'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; @@ -32,6 +32,13 @@ const SingleArticle: NextPageWithLayout = ({ post }) => { title, } = post; + const meta: ArticleMeta = { + author, + commentCount: comments.length, + dates, + thematics, + }; + const router = useRouter(); const locale = router.locale ? router.locale : config.defaultLocale; @@ -51,17 +58,15 @@ const SingleArticle: NextPageWithLayout = ({ post }) => {
- - + +
- +

{t`Comments`}

diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx index 3ce6098..ca82f5b 100644 --- a/src/pages/contact.tsx +++ b/src/pages/contact.tsx @@ -9,6 +9,7 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import { FormEvent, useState } from 'react'; +import PostHeader from '@components/PostHeader/PostHeader'; const ContactPage: NextPageWithLayout = () => { const [name, setName] = useState(''); @@ -48,6 +49,9 @@ const ContactPage: NextPageWithLayout = () => { } }; + const title = t`Contact`; + const intro = t`Please fill the form to contact me.`; + return ( <> @@ -55,9 +59,7 @@ const ContactPage: NextPageWithLayout = () => {
-
-

{t`Contact`}

-
+

{t`All fields marked with * are required.`}

{status &&

{status}

} diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx index 5107f6a..3faa941 100644 --- a/src/pages/cv.tsx +++ b/src/pages/cv.tsx @@ -6,8 +6,19 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import CVContent, { intro, meta } from '@content/pages/cv.mdx'; +import PostHeader from '@components/PostHeader/PostHeader'; +import { ArticleMeta } from '@ts/types/articles'; const CV: NextPageWithLayout = () => { + const dates = { + publication: meta.publishedOn, + update: meta.updatedOn, + }; + + const pageMeta: ArticleMeta = { + dates, + }; + return ( <> @@ -15,12 +26,13 @@ const CV: NextPageWithLayout = () => {
-
-

{meta.title}

-
-
- - + + +
+ +
); diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx index 6bb1a55..d8dfe49 100644 --- a/src/pages/mentions-legales.tsx +++ b/src/pages/mentions-legales.tsx @@ -5,9 +5,23 @@ import { NextPageWithLayout } from '@ts/types/app'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; -import LegalNoticeContent, { meta } from '@content/pages/legal-notice.mdx'; +import LegalNoticeContent, { + intro, + meta, +} from '@content/pages/legal-notice.mdx'; +import PostHeader from '@components/PostHeader/PostHeader'; +import { ArticleMeta } from '@ts/types/articles'; const LegalNotice: NextPageWithLayout = () => { + const dates = { + publication: meta.publishedOn, + update: meta.updatedOn, + }; + + const pageMeta: ArticleMeta = { + dates, + }; + return ( <> @@ -15,11 +29,13 @@ const LegalNotice: NextPageWithLayout = () => {
-
-

{meta.title}

-
- - + + +
+ +
); diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx index 527d529..bcea544 100644 --- a/src/pages/sujet/[slug].tsx +++ b/src/pages/sujet/[slug].tsx @@ -5,13 +5,14 @@ import { NextPageWithLayout } from '@ts/types/app'; import { SubjectProps } from '@ts/types/taxonomies'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; -import Image from 'next/image'; import { ParsedUrlQuery } from 'querystring'; import styles from '@styles/pages/Subject.module.scss'; import { getAllSubjectsSlug, getSubjectBySlug, } from '@services/graphql/queries'; +import PostHeader from '@components/PostHeader/PostHeader'; +import { ArticleMeta } from '@ts/types/articles'; const Subject: NextPageWithLayout = ({ subject }) => { const getPostsList = () => { @@ -22,29 +23,18 @@ const Subject: NextPageWithLayout = ({ subject }) => { )); }; + const meta: ArticleMeta = { + website: subject.officialWebsite, + }; + return (
-
-

- {subject.featuredImage && ( - - {subject.featuredImage.altText} - - )} - {subject.title} -

- {subject.officialWebsite && ( -
-
{t`Official website:`}
-
{subject.officialWebsite}
-
- )} -
-
+
{subject.posts.length > 0 && (
diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx index 74c2212..dca8f25 100644 --- a/src/pages/thematique/[slug].tsx +++ b/src/pages/thematique/[slug].tsx @@ -11,6 +11,7 @@ import { getAllThematicsSlug, getThematicBySlug, } from '@services/graphql/queries'; +import PostHeader from '@components/PostHeader/PostHeader'; const Thematic: NextPageWithLayout = ({ thematic }) => { const getPostsList = () => { @@ -23,10 +24,7 @@ const Thematic: NextPageWithLayout = ({ thematic }) => { return (
-
-

{thematic.title}

-
-
+
{thematic.posts.length > 0 && (
diff --git a/src/ts/types/articles.ts b/src/ts/types/articles.ts index dc5bbe4..44c1d79 100644 --- a/src/ts/types/articles.ts +++ b/src/ts/types/articles.ts @@ -24,6 +24,14 @@ export type ACFPosts = { postsInThematic: ThematicPreview[] | null; }; +export type ArticleMeta = { + author?: ArticleAuthor; + commentCount?: number; + dates?: Dates; + thematics?: ThematicPreview[]; + website?: string; +}; + export type Article = { author: ArticleAuthor; commentCount: number | null; -- cgit v1.2.3