diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/PostFooter/PostFooter.module.scss | 5 | ||||
| -rw-r--r-- | src/components/PostFooter/PostFooter.tsx | 35 | ||||
| -rw-r--r-- | src/components/PostHeader/PostHeader.module.scss | 7 | ||||
| -rw-r--r-- | src/components/PostHeader/PostHeader.tsx | 72 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 21 | ||||
| -rw-r--r-- | src/services/graphql/post.ts | 9 | ||||
| -rw-r--r-- | src/ts/types/articles.ts | 10 |
7 files changed, 153 insertions, 6 deletions
diff --git a/src/components/PostFooter/PostFooter.module.scss b/src/components/PostFooter/PostFooter.module.scss new file mode 100644 index 0000000..e80f5ed --- /dev/null +++ b/src/components/PostFooter/PostFooter.module.scss @@ -0,0 +1,5 @@ +@use "@styles/abstracts/placeholders"; + +.list { + @extend %flex-list; +} diff --git a/src/components/PostFooter/PostFooter.tsx b/src/components/PostFooter/PostFooter.tsx new file mode 100644 index 0000000..8c09d69 --- /dev/null +++ b/src/components/PostFooter/PostFooter.tsx @@ -0,0 +1,35 @@ +import { t } from '@lingui/macro'; +import { SubjectPreview } from '@ts/types/taxonomies'; +import Link from 'next/link'; +import styles from './PostFooter.module.scss'; + +const PostFooter = ({ subjects }: { subjects: SubjectPreview[] }) => { + const getSubjects = () => { + return subjects.map((subject) => { + return ( + <li key={subject.id}> + <Link href={`/sujet/${subject.slug}`}> + <a>{subject.title}</a> + </Link> + </li> + ); + }); + }; + + return ( + <footer> + {subjects.length > 0 && ( + <> + <dl className={styles.meta}> + <dt>{t`Subjects:`}</dt> + <dd> + <ul className={styles.list}>{getSubjects()}</ul> + </dd> + </dl> + </> + )} + </footer> + ); +}; + +export default PostFooter; diff --git a/src/components/PostHeader/PostHeader.module.scss b/src/components/PostHeader/PostHeader.module.scss new file mode 100644 index 0000000..f013651 --- /dev/null +++ b/src/components/PostHeader/PostHeader.module.scss @@ -0,0 +1,7 @@ +.meta { + font-size: var(--font-size-sm); +} + +.label { + font-weight: inherit; +} diff --git a/src/components/PostHeader/PostHeader.tsx b/src/components/PostHeader/PostHeader.tsx new file mode 100644 index 0000000..5c5aff4 --- /dev/null +++ b/src/components/PostHeader/PostHeader.tsx @@ -0,0 +1,72 @@ +import { t } from '@lingui/macro'; +import { ArticleAuthor, ArticleDates } from '@ts/types/articles'; +import { ThematicPreview } from '@ts/types/taxonomies'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import styles from './PostHeader.module.scss'; + +const PostHeader = ({ + author, + date, + intro, + title, + thematics, +}: { + author: ArticleAuthor; + date: ArticleDates; + intro: string; + 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 ( + <dd key={thematic.id}> + <Link href={`/thematique/${thematic.slug}`}> + <a>{thematic.title}</a> + </Link> + </dd> + ); + }); + }; + + return ( + <header> + <h1>{title}</h1> + <ul className={styles.meta}> + <li>{t`Written by ${getAuthor()} on ${getLocaleDate( + date.publication + )}.`}</li> + <li>{t`Last update on ${getLocaleDate(date.update)}.`}</li> + {thematics.length > 0 && ( + <li> + <dl> + <dt className={styles.label}>{t`Posted in:`}</dt> + {getThematics()} + </dl> + </li> + )} + </ul> + <div dangerouslySetInnerHTML={{ __html: intro }}></div> + </header> + ); +}; + +export default PostHeader; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index b3ab2ed..57982e9 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -1,5 +1,7 @@ import CommentsList from '@components/CommentsList/CommentsList'; import Layout from '@components/Layouts/Layout'; +import PostFooter from '@components/PostFooter/PostFooter'; +import PostHeader from '@components/PostHeader/PostHeader'; import { t } from '@lingui/macro'; import { fetchAllPostsSlug } from '@services/graphql/blog'; import { getPostBySlug } from '@services/graphql/post'; @@ -11,16 +13,23 @@ import { ParsedUrlQuery } from 'querystring'; import { ReactElement } from 'react'; const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => { + const { author, comments, content, date, intro, subjects, thematics, title } = + post; + return ( <article> - <header> - <h1>{post.title}</h1> - <div dangerouslySetInnerHTML={{ __html: post.intro }}></div> - </header> - <div dangerouslySetInnerHTML={{ __html: post.content }}></div> + <PostHeader + author={author} + date={date} + intro={intro} + title={title} + thematics={thematics} + /> + <div dangerouslySetInnerHTML={{ __html: content }}></div> + <PostFooter subjects={subjects} /> <section> <h2>{t`Comments`}</h2> - <CommentsList comments={post.comments} /> + <CommentsList comments={comments} /> </section> </article> ); diff --git a/src/services/graphql/post.ts b/src/services/graphql/post.ts index e827fd4..cc6232a 100644 --- a/src/services/graphql/post.ts +++ b/src/services/graphql/post.ts @@ -35,6 +35,13 @@ const fetchPostBySlug: FetchPostByReturn = async (slug: string) => { } } } + author { + node { + firstName + lastName + name + } + } commentCount comments { nodes { @@ -104,6 +111,7 @@ const fetchPostBySlug: FetchPostByReturn = async (slug: string) => { export const getPostBySlug: GetPostByReturn = async (slug: string) => { const rawPost = await fetchPostBySlug(slug); + const author = rawPost.postBy.author.node; const comments = rawPost.postBy.comments.nodes.reverse().map((comment) => { const author = comment.author.node; return { ...comment, author: author, replies: [] }; @@ -126,6 +134,7 @@ export const getPostBySlug: GetPostByReturn = async (slug: string) => { const formattedPost: Article = { ...rawPost.postBy, + author, comments, content, featuredImage, diff --git a/src/ts/types/articles.ts b/src/ts/types/articles.ts index 0bb85c8..afaa3e3 100644 --- a/src/ts/types/articles.ts +++ b/src/ts/types/articles.ts @@ -8,6 +8,12 @@ export type ArticleDates = { update: string; }; +export type ArticleAuthor = { + firstName: string; + lastName: string; + name: string; +}; + export type ArticlePreviewResponse = { acfPosts: { postsInSubject: SubjectPreview[] | null; @@ -40,6 +46,9 @@ export type ArticlePreview = { }; export type ArticleResponse = ArticlePreviewResponse & { + author: { + node: ArticleAuthor; + }; comments: CommentsResponse; contentParts: { afterMore: string; @@ -48,6 +57,7 @@ export type ArticleResponse = ArticlePreviewResponse & { }; export type Article = ArticlePreview & { + author: ArticleAuthor; comments: Comment[]; intro: string; seo: SEO; |
