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, Heading, type HeadingLevel, Icon, Link, Figure, } from '../../atoms'; import { MetaList, type MetaItemData } from '../../molecules'; import styles from './summary.module.scss'; export type Cover = Pick; export type SummaryMeta = Pick< MetaType<'article'>, | 'author' | 'commentsCount' | 'cover' | 'dates' | 'thematics' | 'topics' | 'wordsCount' >; export type SummaryProps = Pick & { /** * The post metadata. */ meta: SummaryMeta; /** * The heading level (hn). */ titleLevel?: HeadingLevel; /** * The post url. */ url: string; }; /** * Summary component * * Render a page summary. */ export const Summary: FC = ({ intro, meta, title, titleLevel = 2, url, }) => { const intl = useIntl(); const readMore = intl.formatMessage( { defaultMessage: 'Read more about {title}', description: 'Summary: read more link', id: 'Zpgv+f', }, { title, a11y: (chunks: ReactNode) => ( // eslint-disable-next-line react/jsx-no-literals -- SR class allowed {chunks} ), } ); const readingTime = useReadingTime(meta.wordsCount, true); /** * 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 ; }; 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: {thematic.name}, }; }), }); 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: {topic.name}, }; }), }); if (meta.commentsCount !== undefined) { const commentsCount = intl.formatMessage( { defaultMessage: '{commentsCount, plural, =0 {No comments} one {# comment} other {# comments}} about {title}', description: 'Summary: comments count', id: 'ye/vlA', }, { a11y: (chunks: ReactNode) => ( {chunks} ), commentsCount: meta.commentsCount, title, } ); summaryMeta.push({ id: 'comments-count', label: intl.formatMessage({ defaultMessage: 'Comments:', description: 'Summary: comments label', id: 'bfPp0g', }), value: ( {commentsCount as JSX.Element} ), }); } return summaryMeta; }; return (
{meta.cover ? (
) : null}
{title}
{readMore}
); };