diff options
Diffstat (limited to 'src/components/organisms/layout/summary.tsx')
| -rw-r--r-- | src/components/organisms/layout/summary.tsx | 175 |
1 files changed, 133 insertions, 42 deletions
diff --git a/src/components/organisms/layout/summary.tsx b/src/components/organisms/layout/summary.tsx index fa3dfe5..f5c16cd 100644 --- a/src/components/organisms/layout/summary.tsx +++ b/src/components/organisms/layout/summary.tsx @@ -2,6 +2,7 @@ import NextImage, { type ImageProps as NextImageProps } from 'next/image'; import type { FC, ReactNode } from 'react'; import { useIntl } from 'react-intl'; import type { Article, Meta as MetaType } from '../../../types'; +import { getFormattedDate } from '../../../utils/helpers'; import { useReadingTime } from '../../../utils/hooks'; import { ButtonLink, @@ -11,7 +12,7 @@ import { Link, Figure, } from '../../atoms'; -import { Meta, type MetaData } from '../../molecules'; +import { MetaList, type MetaItemData } from '../../molecules'; import styles from './summary.module.scss'; export type Cover = Pick<NextImageProps, 'alt' | 'src' | 'width' | 'height'>; @@ -69,42 +70,134 @@ export const Summary: FC<SummaryProps> = ({ ), } ); - const { author, commentsCount, cover, dates, thematics, topics, wordsCount } = - meta; - const readingTime = useReadingTime(wordsCount, true); + const readingTime = useReadingTime(meta.wordsCount, true); - const getMeta = (): MetaData => { - return { - author: author?.name, - publication: { date: dates.publication }, - update: - dates.update && dates.publication !== dates.update - ? { date: dates.update } - : undefined, - readingTime, - thematics: thematics?.map((thematic) => ( - <Link key={thematic.id} href={thematic.url}> - {thematic.name} - </Link> - )), - topics: topics?.map((topic) => ( - <Link key={topic.id} href={topic.url}> - {topic.name} - </Link> - )), - comments: { - about: title, - count: commentsCount ?? 0, - target: `${url}#comments`, + /** + * Retrieve a formatted date (and time). + * + * @param {string} date - A date string. + * @returns {JSX.Element} The formatted date wrapped in a time element. + */ + const getDate = (date: string): JSX.Element => { + const isoDate = new Date(`${date}`).toISOString(); + + return <time dateTime={isoDate}>{getFormattedDate(date)}</time>; + }; + + const getMetaItems = (): MetaItemData[] => { + const summaryMeta: MetaItemData[] = [ + { + id: 'publication-date', + label: intl.formatMessage({ + defaultMessage: 'Published on:', + description: 'Summary: publication date label', + id: 'TvQ2Ee', + }), + value: getDate(meta.dates.publication), }, - }; + ]; + + if (meta.dates.update && meta.dates.update !== meta.dates.publication) + summaryMeta.push({ + id: 'update-date', + label: intl.formatMessage({ + defaultMessage: 'Updated on:', + description: 'Summary: update date label', + id: 'f0Z/Po', + }), + value: getDate(meta.dates.update), + }); + + summaryMeta.push({ + id: 'reading-time', + label: intl.formatMessage({ + defaultMessage: 'Reading time:', + description: 'Summary: reading time label', + id: 'tyzdql', + }), + value: readingTime, + }); + + if (meta.author) + summaryMeta.push({ + id: 'author', + label: intl.formatMessage({ + defaultMessage: 'Written by:', + description: 'Summary: author label', + id: 'r/6HOI', + }), + value: meta.author.name, + }); + + if (meta.thematics) + summaryMeta.push({ + id: 'thematics', + label: intl.formatMessage({ + defaultMessage: 'Thematics:', + description: 'Summary: thematics label', + id: 'bk0WOp', + }), + value: meta.thematics.map((thematic) => { + return { + id: `thematic-${thematic.id}`, + value: <Link href={thematic.url}>{thematic.name}</Link>, + }; + }), + }); + + if (meta.topics) + summaryMeta.push({ + id: 'topics', + label: intl.formatMessage({ + defaultMessage: 'Topics:', + description: 'Summary: topics label', + id: 'yIZ+AC', + }), + value: meta.topics.map((topic) => { + return { + id: `topic-${topic.id}`, + value: <Link href={topic.url}>{topic.name}</Link>, + }; + }), + }); + + if (meta.commentsCount !== undefined) { + const commentsCount = intl.formatMessage( + { + defaultMessage: + '{commentsCount, plural, =0 {No comments} one {# comment} other {# comments}}<a11y> about {title}</a11y>', + description: 'Summary: comments count', + id: 'ye/vlA', + }, + { + a11y: (chunks: ReactNode) => ( + <span className="screen-reader-text">{chunks}</span> + ), + commentsCount: meta.commentsCount, + title, + } + ); + summaryMeta.push({ + id: 'comments-count', + label: intl.formatMessage({ + defaultMessage: 'Comments:', + description: 'Summary: comments label', + id: 'bfPp0g', + }), + value: ( + <Link href={`${url}#comments`}>{commentsCount as JSX.Element}</Link> + ), + }); + } + + return summaryMeta; }; return ( <article className={styles.wrapper}> - {cover ? ( + {meta.cover ? ( <Figure> - <NextImage {...cover} className={styles.cover} /> + <NextImage {...meta.cover} className={styles.cover} /> </Figure> ) : null} <header className={styles.header}> @@ -121,21 +214,19 @@ export const Summary: FC<SummaryProps> = ({ dangerouslySetInnerHTML={{ __html: intro }} /> <ButtonLink className={styles['read-more']} to={url}> - <> - {readMore} - <Icon - aria-hidden={true} - className={styles.icon} - // eslint-disable-next-line react/jsx-no-literals -- Direction allowed - orientation="right" - // eslint-disable-next-line react/jsx-no-literals -- Shape allowed - shape="arrow" - /> - </> + {readMore} + <Icon + aria-hidden={true} + className={styles.icon} + // eslint-disable-next-line react/jsx-no-literals -- Direction allowed + orientation="right" + // eslint-disable-next-line react/jsx-no-literals -- Shape allowed + shape="arrow" + /> </ButtonLink> </div> <footer className={styles.footer}> - <Meta className={styles.meta} data={getMeta()} spacing="xs" /> + <MetaList className={styles.meta} items={getMetaItems()} /> </footer> </article> ); |
