aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/organisms')
-rw-r--r--src/components/organisms/comment/approved-comment/approved-comment.tsx26
-rw-r--r--src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx220
-rw-r--r--src/components/organisms/project-overview/project-overview.tsx40
3 files changed, 125 insertions, 161 deletions
diff --git a/src/components/organisms/comment/approved-comment/approved-comment.tsx b/src/components/organisms/comment/approved-comment/approved-comment.tsx
index db5345b..233146d 100644
--- a/src/components/organisms/comment/approved-comment/approved-comment.tsx
+++ b/src/components/organisms/comment/approved-comment/approved-comment.tsx
@@ -12,6 +12,7 @@ import {
CardTitle,
CardFooter,
CardActions,
+ MetaItem,
} from '../../../molecules';
import styles from './approved-comment.module.scss';
@@ -138,20 +139,17 @@ const ApprovedCommentWithRef: ForwardRefRenderFunction<
author.name
)}
</CardTitle>
- <CardMeta
- hasInlinedItems
- items={[
- {
- id: 'publication-date',
- label: publicationDateLabel,
- value: (
- <Link href={commentLink}>
- <Time date={publicationDate} showTime />
- </Link>
- ),
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ isInline
+ label={publicationDateLabel}
+ value={
+ <Link href={commentLink}>
+ <Time date={publicationDate} showTime />
+ </Link>
+ }
+ />
+ </CardMeta>
</CardHeader>
<CardBody
className={styles.body}
diff --git a/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx b/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
index 5a342da..54e359e 100644
--- a/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
+++ b/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
@@ -1,12 +1,13 @@
-import type { FC, ReactNode } from 'react';
+import type { FC, ReactElement, ReactNode } from 'react';
import { useIntl } from 'react-intl';
import type { PageLink } from '../../../../types';
import { getReadingTimeFrom } from '../../../../utils/helpers';
import { Link, Time, VisuallyHidden } from '../../../atoms';
import {
CardMeta,
- type MetaItemData,
type CardMetaProps,
+ MetaItem,
+ type MetaItemProps,
} from '../../../molecules';
const a11y = (chunks: ReactNode) => <VisuallyHidden>{chunks}</VisuallyHidden>;
@@ -57,20 +58,7 @@ export type PostPreviewMetaData = {
wordsCount?: number;
};
-const validMetaKeys = [
- 'author',
- 'comments',
- 'publicationDate',
- 'thematics',
- 'topics',
- 'updateDate',
- 'wordsCount',
-] satisfies (keyof PostPreviewMetaData)[];
-
-const isValidMetaKey = (key: string): key is keyof PostPreviewMetaData =>
- (validMetaKeys as string[]).includes(key);
-
-export type PostPreviewMetaProps = Omit<CardMetaProps, 'items'> & {
+export type PostPreviewMetaProps = Omit<CardMetaProps, 'children' | 'items'> & {
/**
* The post meta.
*/
@@ -83,23 +71,20 @@ export const PostPreviewMeta: FC<PostPreviewMetaProps> = ({
}) => {
const intl = useIntl();
- const getAuthor = (): MetaItemData | undefined => {
- if (!meta.author) return undefined;
-
- return {
- id: 'author',
- label: intl.formatMessage({
+ const getAuthor = (author: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Written by:',
description: 'PostPreviewMeta: author label',
id: '2U7ixo',
- }),
- value: meta.author,
- };
- };
-
- const getCommentsCount = (): MetaItemData | undefined => {
- if (!meta.comments) return undefined;
-
+ })}
+ value={author}
+ />
+ );
+
+ const getComments = (
+ comments: PostPreviewMetaComment
+ ): ReactElement<MetaItemProps> => {
const commentsLabel = intl.formatMessage<ReactNode>(
{
defaultMessage:
@@ -109,146 +94,121 @@ export const PostPreviewMeta: FC<PostPreviewMetaProps> = ({
},
{
a11y,
- commentsCount: meta.comments.count,
- title: meta.comments.postHeading,
+ commentsCount: comments.count,
+ title: comments.postHeading,
}
);
- return {
- id: 'comments',
- label: intl.formatMessage({
- defaultMessage: 'Comments:',
- description: 'PostPreviewMeta: comments label',
- id: 'FCpPCm',
- }),
- value: meta.comments.url ? (
- <Link href={meta.comments.url}>{commentsLabel}</Link>
- ) : (
- <>{commentsLabel}</>
- ),
- };
+ return (
+ <MetaItem
+ label={intl.formatMessage({
+ defaultMessage: 'Comments:',
+ description: 'PostPreviewMeta: comments label',
+ id: 'FCpPCm',
+ })}
+ value={
+ comments.url ? (
+ <Link href={comments.url}>{commentsLabel}</Link>
+ ) : (
+ <>{commentsLabel}</>
+ )
+ }
+ />
+ );
};
- const getPublicationDate = (): MetaItemData | undefined => {
- if (!meta.publicationDate) return undefined;
-
- return {
- id: 'publication-date',
- label: intl.formatMessage({
+ const getPublicationDate = (date: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Published on:',
description: 'PostPreviewMeta: publication date label',
id: '+6f4p1',
- }),
- value: <Time date={meta.publicationDate} />,
- };
- };
-
- const getThematics = (): MetaItemData | undefined => {
- if (!meta.thematics?.length) return undefined;
-
- return {
- id: 'thematics',
- label: intl.formatMessage(
+ })}
+ value={<Time date={date} />}
+ />
+ );
+
+ const getThematics = (thematics: PageLink[]): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage(
{
defaultMessage:
'{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}',
description: 'PostPreviewMeta: thematics label',
id: '9MTBCG',
},
- { thematicsCount: meta.thematics.length }
- ),
- value: meta.thematics.map((thematic) => {
+ { thematicsCount: thematics.length }
+ )}
+ value={thematics.map((thematic) => {
return {
id: `thematic-${thematic.id}`,
value: <Link href={thematic.url}>{thematic.name}</Link>,
};
- }),
- };
- };
-
- const getTopics = (): MetaItemData | undefined => {
- if (!meta.topics?.length) return undefined;
+ })}
+ />
+ );
- return {
- id: 'topics',
- label: intl.formatMessage(
+ const getTopics = (topics: PageLink[]): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage(
{
defaultMessage:
'{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}',
description: 'PostPreviewMeta: topics label',
id: 'aBQYbE',
},
- { topicsCount: meta.topics.length }
- ),
- value: meta.topics.map((topic) => {
+ { topicsCount: topics.length }
+ )}
+ value={topics.map((topic) => {
return {
id: `topic-${topic.id}`,
value: <Link href={topic.url}>{topic.name}</Link>,
};
- }),
- };
- };
+ })}
+ />
+ );
- const getUpdateDate = (): MetaItemData | undefined => {
- if (!meta.updateDate || meta.updateDate === meta.publicationDate)
- return undefined;
-
- return {
- id: 'update-date',
- label: intl.formatMessage({
+ const getUpdateDate = (date: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Updated on:',
description: 'PostPreviewMeta: update date label',
id: 'ZmRh0V',
- }),
- value: <Time date={meta.updateDate} />,
- };
- };
-
- const getReadingTime = (): MetaItemData | undefined => {
- if (!meta.wordsCount) return undefined;
-
- return {
- id: 'reading-time',
- label: intl.formatMessage({
+ })}
+ value={<Time date={date} />}
+ />
+ );
+
+ const getReadingTime = (wordsCount: number): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Reading time:',
description: 'PostPreviewMeta: reading time label',
id: 'B1lS/v',
- }),
- value: intl.formatMessage(
+ })}
+ value={intl.formatMessage(
{
defaultMessage:
'{minutesCount, plural, =0 {Less than one minute} one {# minute} other {# minutes}}',
description: 'PostPreviewMeta: rounded minutes count',
id: 'y+13Ax',
},
- { minutesCount: getReadingTimeFrom(meta.wordsCount).inMinutes() }
- ),
- };
- };
-
- const items: MetaItemData[] = Object.keys(meta)
- .filter(isValidMetaKey)
- .map((key): MetaItemData | undefined => {
- switch (key) {
- case 'author':
- return getAuthor();
- case 'comments':
- return getCommentsCount();
- case 'publicationDate':
- return getPublicationDate();
- case 'thematics':
- return getThematics();
- case 'topics':
- return getTopics();
- case 'updateDate':
- return getUpdateDate();
- case 'wordsCount':
- return getReadingTime();
- default:
- throw new Error('Unsupported meta key.');
- }
- })
- .filter((item): item is MetaItemData => item !== undefined);
-
- return <CardMeta {...props} items={items} />;
+ { minutesCount: getReadingTimeFrom(wordsCount).inMinutes() }
+ )}
+ />
+ );
+
+ return (
+ <CardMeta {...props}>
+ {meta.author ? getAuthor(meta.author) : null}
+ {meta.publicationDate ? getPublicationDate(meta.publicationDate) : null}
+ {meta.updateDate && meta.updateDate !== meta.publicationDate
+ ? getUpdateDate(meta.updateDate)
+ : null}
+ {meta.wordsCount ? getReadingTime(meta.wordsCount) : null}
+ {meta.thematics ? getThematics(meta.thematics) : null}
+ {meta.topics ? getTopics(meta.topics) : null}
+ {meta.comments ? getComments(meta.comments) : null}
+ </CardMeta>
+ );
};
diff --git a/src/components/organisms/project-overview/project-overview.tsx b/src/components/organisms/project-overview/project-overview.tsx
index 2b8be0e..f524120 100644
--- a/src/components/organisms/project-overview/project-overview.tsx
+++ b/src/components/organisms/project-overview/project-overview.tsx
@@ -6,7 +6,7 @@ import {
type ReactElement,
} from 'react';
import { useIntl } from 'react-intl';
-import type { Maybe, ValueOf } from '../../../types';
+import type { ValueOf } from '../../../types';
import {
Time,
type SocialWebsite,
@@ -14,7 +14,7 @@ import {
SocialLink,
Figure,
} from '../../atoms';
-import { MetaList, type MetaItemData } from '../../molecules';
+import { MetaItem, type MetaItemProps, MetaList } from '../../molecules';
import styles from './project-overview.module.scss';
export type Repository = {
@@ -155,27 +155,31 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction<
[intl]
);
- const getMetaItems = useCallback((): MetaItemData[] => {
+ const getMetaItems = useCallback(() => {
const keys = Object.keys(meta).filter(isValidMetaKey);
return keys
- .map((key): Maybe<MetaItemData> => {
+ .map((key) => {
const value = meta[key];
- return value
- ? {
- id: key,
- label: metaLabels[key],
- value: getMetaValue(key, value),
- hasBorderedValues: key === 'technologies',
- hasInlinedValues:
- (key === 'technologies' || key === 'repositories') &&
- Array.isArray(value) &&
- value.length > 1,
+ return value ? (
+ <MetaItem
+ hasBorderedValues={key === 'technologies'}
+ hasInlinedValues={
+ (key === 'technologies' || key === 'repositories') &&
+ Array.isArray(value) &&
+ value.length > 1
}
- : undefined;
+ key={key}
+ label={metaLabels[key]}
+ value={getMetaValue(key, value)}
+ />
+ ) : undefined;
})
- .filter((item): item is MetaItemData => typeof item !== 'undefined');
+ .filter(
+ (item): item is ReactElement<MetaItemProps> =>
+ typeof item !== 'undefined'
+ );
}, [getMetaValue, meta, metaLabels]);
return (
@@ -185,7 +189,9 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction<
{cover}
</Figure>
) : null}
- <MetaList className={styles.meta} isInline items={getMetaItems()} />
+ <MetaList className={styles.meta} isInline>
+ {getMetaItems()}
+ </MetaList>
</div>
);
};