diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-06 18:08:04 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:15:27 +0100 |
| commit | c9c1c90b30e243563bb4f731da15b3fe657556d2 (patch) | |
| tree | 8263c176b4096e2893b9d9319bfa7edb01fce188 /src/components/organisms/layout/summary.tsx | |
| parent | 2771de88f40a5f4ed7480bd8614532dda72deeda (diff) | |
refactor(components): replace Summary component with PostPreview
* rename component to PostPreview because Summary is an HTML element
and it could lead to confusion
* replace `title` and `titleLevel` with `heading` and `headingLvl`
because `title` is a native attribute
* rename `intro` prop to `excerpt`
* extract `cover` from `meta` prop
* rewrite meta type
* extract meta logic into a new component
Diffstat (limited to 'src/components/organisms/layout/summary.tsx')
| -rw-r--r-- | src/components/organisms/layout/summary.tsx | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/src/components/organisms/layout/summary.tsx b/src/components/organisms/layout/summary.tsx deleted file mode 100644 index 0c95f90..0000000 --- a/src/components/organisms/layout/summary.tsx +++ /dev/null @@ -1,235 +0,0 @@ -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 { useReadingTime } from '../../../utils/hooks'; -import { ButtonLink, type HeadingLevel, Icon, Link, Time } from '../../atoms'; -import { - Card, - CardActions, - CardBody, - CardCover, - CardFooter, - CardHeader, - CardMeta, - CardTitle, - type MetaItemData, -} from '../../molecules'; -import styles from './summary.module.scss'; - -export type Cover = Pick<NextImageProps, 'alt' | 'src' | 'width' | 'height'>; - -export type SummaryMeta = Pick< - MetaType<'article'>, - | 'author' - | 'commentsCount' - | 'cover' - | 'dates' - | 'thematics' - | 'topics' - | 'wordsCount' ->; - -export type SummaryProps = Pick<Article, 'intro' | 'title'> & { - /** - * 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<SummaryProps> = ({ - intro, - meta, - title, - titleLevel = 2, - url, -}) => { - const intl = useIntl(); - const figureLabel = intl.formatMessage( - { - defaultMessage: '{title} cover', - description: 'Summary: figure (cover) accessible name', - id: 'RNVe1W', - }, - { title } - ); - const readMore = intl.formatMessage( - { - defaultMessage: 'Read more<a11y> about {title}</a11y>', - description: 'Summary: read more link', - id: 'Zpgv+f', - }, - { - title, - a11y: (chunks: ReactNode) => ( - // eslint-disable-next-line react/jsx-no-literals -- SR class allowed - <span className="screen-reader-text">{chunks}</span> - ), - } - ); - const readingTime = useReadingTime(meta.wordsCount, true); - - const getMetaItems = (): MetaItemData[] => { - const summaryMeta: MetaItemData[] = [ - { - id: 'publication-date', - label: intl.formatMessage({ - defaultMessage: 'Published on:', - description: 'Summary: publication date label', - id: 'TvQ2Ee', - }), - value: <Time date={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: <Time date={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 ( - <Card - className={styles.wrapper} - cover={ - meta.cover ? ( - <CardCover aria-label={figureLabel} hasBorders> - <NextImage {...meta.cover} /> - </CardCover> - ) : undefined - } - meta={<CardMeta items={getMetaItems()} />} - > - <CardHeader> - <CardTitle className={styles.title} level={titleLevel}> - <Link href={url}>{title}</Link> - </CardTitle> - </CardHeader> - <CardBody> - <div - className={styles.intro} - // eslint-disable-next-line react/no-danger - dangerouslySetInnerHTML={{ __html: intro }} - /> - </CardBody> - <CardFooter> - <CardActions> - <ButtonLink 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" - /> - </ButtonLink> - </CardActions> - </CardFooter> - </Card> - ); -}; |
