aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-12 17:24:13 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:14:41 +0100
commit00f147a7a687d5772bcc538bc606cfff972178cd (patch)
tree27eabeb83c05e14162c51b69d4a6f36d461947fc
parentc87c615b5866b8a8f361eeb0764bfdea85740e90 (diff)
feat(components): add a Time component
Instead of using helpers functions to format the date each time we need to use a time element, it makes more sense to create a new component dedicated to this task.
-rw-r--r--src/components/atoms/layout/copyright.tsx39
-rw-r--r--src/components/atoms/layout/index.ts1
-rw-r--r--src/components/atoms/layout/time/index.ts1
-rw-r--r--src/components/atoms/layout/time/time.stories.tsx32
-rw-r--r--src/components/atoms/layout/time/time.test.tsx39
-rw-r--r--src/components/atoms/layout/time/time.tsx136
-rw-r--r--src/components/organisms/layout/comment.fixture.ts4
-rw-r--r--src/components/organisms/layout/comment.test.tsx10
-rw-r--r--src/components/organisms/layout/comment.tsx20
-rw-r--r--src/components/organisms/layout/summary.tsx18
-rw-r--r--src/i18n/en.json8
-rw-r--r--src/i18n/fr.json8
-rw-r--r--src/pages/article/[slug].tsx18
-rw-r--r--src/pages/cv.tsx18
-rw-r--r--src/pages/index.tsx15
-rw-r--r--src/pages/mentions-legales.tsx18
-rw-r--r--src/pages/projets/[slug].tsx22
-rw-r--r--src/pages/sujet/[slug].tsx18
-rw-r--r--src/pages/thematique/[slug].tsx18
-rw-r--r--src/utils/helpers/dates.ts40
-rw-r--r--src/utils/helpers/index.ts1
21 files changed, 263 insertions, 221 deletions
diff --git a/src/components/atoms/layout/copyright.tsx b/src/components/atoms/layout/copyright.tsx
index c60ff8b..3d56059 100644
--- a/src/components/atoms/layout/copyright.tsx
+++ b/src/components/atoms/layout/copyright.tsx
@@ -1,5 +1,6 @@
import type { FC, ReactNode } from 'react';
import styles from './copyright.module.scss';
+import { Time } from './time';
export type CopyrightDates = {
/**
@@ -32,26 +33,18 @@ export type CopyrightProps = {
*
* Renders a copyright information (owner, dates, license icon).
*/
-export const Copyright: FC<CopyrightProps> = ({ owner, dates, icon }) => {
- const getFormattedDate = (date: string) => {
- const datetime = new Date(date).toISOString();
-
- return <time dateTime={datetime}>{date}</time>;
- };
-
- return (
- <div className={styles.wrapper}>
- <span className={styles.owner}>{owner}</span>
- {icon}
- {getFormattedDate(dates.start)}
- {dates.end ? (
- <>
- <span>-</span>
- {getFormattedDate(dates.end)}
- </>
- ) : (
- ''
- )}
- </div>
- );
-};
+export const Copyright: FC<CopyrightProps> = ({ owner, dates, icon }) => (
+ <div className={styles.wrapper}>
+ <span className={styles.owner}>{owner}</span>
+ {icon}
+ <Time date={dates.start} hideDay hideMonth />
+ {dates.end ? (
+ <>
+ <span>-</span>
+ <Time date={dates.end} hideDay hideMonth />
+ </>
+ ) : (
+ ''
+ )}
+ </div>
+);
diff --git a/src/components/atoms/layout/index.ts b/src/components/atoms/layout/index.ts
index 3f2f8dc..c37ff02 100644
--- a/src/components/atoms/layout/index.ts
+++ b/src/components/atoms/layout/index.ts
@@ -6,3 +6,4 @@ export * from './header';
export * from './main';
export * from './nav';
export * from './section';
+export * from './time';
diff --git a/src/components/atoms/layout/time/index.ts b/src/components/atoms/layout/time/index.ts
new file mode 100644
index 0000000..47e4e1f
--- /dev/null
+++ b/src/components/atoms/layout/time/index.ts
@@ -0,0 +1 @@
+export * from './time';
diff --git a/src/components/atoms/layout/time/time.stories.tsx b/src/components/atoms/layout/time/time.stories.tsx
new file mode 100644
index 0000000..d534f14
--- /dev/null
+++ b/src/components/atoms/layout/time/time.stories.tsx
@@ -0,0 +1,32 @@
+import type { ComponentMeta, ComponentStory } from '@storybook/react';
+import { Time } from './time';
+
+/**
+ * Time - Storybook Meta
+ */
+export default {
+ title: 'Atoms/Layout/Time',
+ component: Time,
+ argTypes: {
+ date: {
+ control: {
+ type: 'text',
+ },
+ description: 'A valid date string.',
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ },
+} as ComponentMeta<typeof Time>;
+
+const Template: ComponentStory<typeof Time> = (args) => <Time {...args} />;
+
+/**
+ * Time Stories - Default
+ */
+export const Default = Template.bind({});
+Default.args = {
+ date: '2022-03-15 10:44:20',
+};
diff --git a/src/components/atoms/layout/time/time.test.tsx b/src/components/atoms/layout/time/time.test.tsx
new file mode 100644
index 0000000..910285d
--- /dev/null
+++ b/src/components/atoms/layout/time/time.test.tsx
@@ -0,0 +1,39 @@
+import { describe, expect, it } from '@jest/globals';
+import { render, screen as rtlScreen } from '../../../../../tests/utils';
+import { settings } from '../../../../utils/config';
+import { Time } from './time';
+
+describe('Time', () => {
+ it('renders a date wrapped in a time element', () => {
+ const date = '2022';
+
+ render(<Time date={date} />);
+
+ expect(rtlScreen.getByText(new RegExp(date))).toHaveAttribute(
+ 'datetime',
+ new Date(date).toISOString()
+ );
+ });
+
+ it('can show the time in addition to the date', () => {
+ const date = '2022';
+
+ render(<Time date={date} showTime />);
+
+ expect(rtlScreen.getByText(new RegExp(date))).toHaveTextContent(/\sat\s/);
+ });
+
+ it('can show the week day in front of the date', () => {
+ const date = new Date();
+
+ render(<Time date={date.toDateString()} showWeekDay />);
+
+ expect(
+ rtlScreen.getByText(new RegExp(`${date.getFullYear()}`))
+ ).toHaveTextContent(
+ new Intl.DateTimeFormat(settings.locales.defaultLocale, {
+ weekday: 'long',
+ }).format(date)
+ );
+ });
+});
diff --git a/src/components/atoms/layout/time/time.tsx b/src/components/atoms/layout/time/time.tsx
new file mode 100644
index 0000000..02b4763
--- /dev/null
+++ b/src/components/atoms/layout/time/time.tsx
@@ -0,0 +1,136 @@
+import {
+ type ForwardRefRenderFunction,
+ type TimeHTMLAttributes,
+ forwardRef,
+} from 'react';
+import { useIntl } from 'react-intl';
+import { settings } from '../../../../utils/config';
+
+type GetDateOptionsConfig = {
+ hasDay: boolean;
+ hasMonth: boolean;
+ hasWeekDay: boolean;
+ hasYear: boolean;
+};
+
+const getDateOptions = ({
+ hasDay,
+ hasMonth,
+ hasWeekDay,
+ hasYear,
+}: GetDateOptionsConfig): Intl.DateTimeFormatOptions => {
+ const day: Intl.DateTimeFormatOptions['day'] = 'numeric';
+ const month: Intl.DateTimeFormatOptions['month'] = 'long';
+ const weekDay: Intl.DateTimeFormatOptions['weekday'] = 'long';
+ const year: Intl.DateTimeFormatOptions['year'] = 'numeric';
+ const options: [
+ keyof Intl.DateTimeFormatOptions,
+ Intl.DateTimeFormatOptions[keyof Intl.DateTimeFormatOptions],
+ ][] = [];
+
+ if (hasDay) options.push(['day', day]);
+ if (hasMonth) options.push(['month', month]);
+ if (hasWeekDay) options.push(['weekday', weekDay]);
+ if (hasYear) options.push(['year', year]);
+
+ return Object.fromEntries(options);
+};
+
+export type TimeProps = Omit<
+ TimeHTMLAttributes<HTMLTimeElement>,
+ 'children' | 'dateTime'
+> & {
+ /**
+ * A valid date string.
+ */
+ date: string;
+ /**
+ * Should we hide the day number?
+ *
+ * @default false
+ */
+ hideDay?: boolean;
+ /**
+ * Should we hide the month?
+ *
+ * @default false
+ */
+ hideMonth?: boolean;
+ /**
+ * Should we hide the year?
+ *
+ * @default false
+ */
+ hideYear?: boolean;
+ /**
+ * The current locale.
+ *
+ * @default settings.locales.defaultLocale
+ */
+ locale?: string;
+ /**
+ * Should we display the time in addition to the date?
+ *
+ * @default false
+ */
+ showTime?: boolean;
+ /**
+ * Should we display the week day?
+ *
+ * @default false
+ */
+ showWeekDay?: boolean;
+};
+
+const TimeWithRef: ForwardRefRenderFunction<HTMLTimeElement, TimeProps> = (
+ {
+ date,
+ hideDay = false,
+ hideMonth = false,
+ hideYear = false,
+ locale = settings.locales.defaultLocale,
+ showTime = false,
+ showWeekDay = false,
+ ...props
+ },
+ ref
+) => {
+ const intl = useIntl();
+ const dateOptions = getDateOptions({
+ hasDay: !hideDay,
+ hasMonth: !hideMonth,
+ hasWeekDay: showWeekDay,
+ hasYear: !hideYear,
+ });
+ const fullDate = new Date(date);
+ const dateTime = fullDate.toISOString();
+ const readableDate = fullDate.toLocaleDateString(locale, dateOptions);
+ const formattedTime = fullDate.toLocaleTimeString(locale, {
+ hour: 'numeric',
+ minute: 'numeric',
+ });
+ const readableTime =
+ locale === 'fr' ? formattedTime.replace(':', 'h') : formattedTime;
+
+ return (
+ <time {...props} dateTime={dateTime} ref={ref}>
+ {showTime
+ ? intl.formatMessage(
+ {
+ defaultMessage: '{date} at {time}',
+ description: 'Time: readable date and time',
+ id: '8q5PXx',
+ },
+ { date: readableDate, time: readableTime }
+ )
+ : readableDate}
+ </time>
+ );
+};
+
+/**
+ * Time component.
+ *
+ * Render a date with an optional time in a `<time>` element.
+ */
+export const Time = forwardRef(TimeWithRef);
diff --git a/src/components/organisms/layout/comment.fixture.ts b/src/components/organisms/layout/comment.fixture.ts
index f626be9..bb18d22 100644
--- a/src/components/organisms/layout/comment.fixture.ts
+++ b/src/components/organisms/layout/comment.fixture.ts
@@ -1,4 +1,3 @@
-import { getFormattedDate, getFormattedTime } from '../../../utils/helpers';
import type { UserCommentProps } from './comment';
export const author = {
@@ -36,6 +35,3 @@ export const data: UserCommentProps = {
parentId: 0,
saveComment,
};
-
-export const formattedDate = getFormattedDate(date);
-export const formattedTime = getFormattedTime(date);
diff --git a/src/components/organisms/layout/comment.test.tsx b/src/components/organisms/layout/comment.test.tsx
index b64f84a..0e0ea3a 100644
--- a/src/components/organisms/layout/comment.test.tsx
+++ b/src/components/organisms/layout/comment.test.tsx
@@ -1,13 +1,7 @@
import { describe, expect, it } from '@jest/globals';
import { render, screen as rtlScreen } from '../../../../tests/utils';
import { UserComment } from './comment';
-import {
- author,
- data,
- formattedDate,
- formattedTime,
- id,
-} from './comment.fixture';
+import { author, data, id } from './comment.fixture';
describe('UserComment', () => {
it('renders an avatar', () => {
@@ -29,7 +23,7 @@ describe('UserComment', () => {
render(<UserComment canReply={true} {...data} />);
expect(
rtlScreen.getByRole('link', {
- name: `${formattedDate} at ${formattedTime}`,
+ name: /\sat\s/,
})
).toHaveAttribute('href', `#comment-${id}`);
});
diff --git a/src/components/organisms/layout/comment.tsx b/src/components/organisms/layout/comment.tsx
index e1ea6b5..cb2f16f 100644
--- a/src/components/organisms/layout/comment.tsx
+++ b/src/components/organisms/layout/comment.tsx
@@ -5,9 +5,8 @@ import { type FC, useCallback, useState } from 'react';
import { useIntl } from 'react-intl';
import type { Comment as CommentSchema, WithContext } from 'schema-dts';
import type { SingleComment } from '../../../types';
-import { getFormattedDate, getFormattedTime } from '../../../utils/helpers';
import { useSettings } from '../../../utils/hooks';
-import { Button, Link } from '../../atoms';
+import { Button, Link, Time } from '../../atoms';
import { MetaList } from '../../molecules';
import { CommentForm, type CommentFormProps } from '../forms';
import styles from './comment.module.scss';
@@ -61,21 +60,6 @@ export const UserComment: FC<UserCommentProps> = ({
}
const { author, date } = meta;
- const [publicationDate, publicationTime] = date.split(' ');
- const isoDateTime = new Date(
- `${publicationDate}T${publicationTime}`
- ).toISOString();
- const commentDate = intl.formatMessage(
- {
- defaultMessage: '{date} at {time}',
- description: 'Comment: publication date and time',
- id: 'Ld6yMP',
- },
- {
- date: getFormattedDate(publicationDate),
- time: getFormattedTime(`${publicationDate}T${publicationTime}`),
- }
- );
const buttonLabel = isReplying
? intl.formatMessage({
@@ -163,7 +147,7 @@ export const UserComment: FC<UserCommentProps> = ({
}),
value: (
<Link href={`#comment-${id}`}>
- <time dateTime={isoDateTime}>{commentDate}</time>
+ <Time date={date} showTime />
</Link>
),
},
diff --git a/src/components/organisms/layout/summary.tsx b/src/components/organisms/layout/summary.tsx
index f5c16cd..4fe7632 100644
--- a/src/components/organisms/layout/summary.tsx
+++ b/src/components/organisms/layout/summary.tsx
@@ -2,7 +2,6 @@ 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,6 +10,7 @@ import {
Icon,
Link,
Figure,
+ Time,
} from '../../atoms';
import { MetaList, type MetaItemData } from '../../molecules';
import styles from './summary.module.scss';
@@ -72,18 +72,6 @@ export const Summary: FC<SummaryProps> = ({
);
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 <time dateTime={isoDate}>{getFormattedDate(date)}</time>;
- };
-
const getMetaItems = (): MetaItemData[] => {
const summaryMeta: MetaItemData[] = [
{
@@ -93,7 +81,7 @@ export const Summary: FC<SummaryProps> = ({
description: 'Summary: publication date label',
id: 'TvQ2Ee',
}),
- value: getDate(meta.dates.publication),
+ value: <Time date={meta.dates.publication} />,
},
];
@@ -105,7 +93,7 @@ export const Summary: FC<SummaryProps> = ({
description: 'Summary: update date label',
id: 'f0Z/Po',
}),
- value: getDate(meta.dates.update),
+ value: <Time date={meta.dates.update} />,
});
summaryMeta.push({
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 92a0c45..9bfe248 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -155,6 +155,10 @@
"defaultMessage": "{website} picture",
"description": "Layout: photo alternative text"
},
+ "8q5PXx": {
+ "defaultMessage": "{date} at {time}",
+ "description": "Time: readable date and time"
+ },
"9DfuHk": {
"defaultMessage": "Updated on:",
"description": "TopicPage: update date label"
@@ -299,10 +303,6 @@
"defaultMessage": "Close search",
"description": "Search: Close label"
},
- "Ld6yMP": {
- "defaultMessage": "{date} at {time}",
- "description": "Comment: publication date and time"
- },
"LszkU6": {
"defaultMessage": "All posts in {thematicName}",
"description": "ThematicPage: posts list heading"
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index f602b20..a988729 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -155,6 +155,10 @@
"defaultMessage": "Photo d’{website}",
"description": "Layout: photo alternative text"
},
+ "8q5PXx": {
+ "defaultMessage": "{date} à {time}",
+ "description": "Time: readable date and time"
+ },
"9DfuHk": {
"defaultMessage": "Mis à jour le :",
"description": "TopicPage: update date label"
@@ -299,10 +303,6 @@
"defaultMessage": "Fermer la recherche",
"description": "Search: Close label"
},
- "Ld6yMP": {
- "defaultMessage": "{date} à {time}",
- "description": "Comment: publication date and time"
- },
"LszkU6": {
"defaultMessage": "Tous les articles dans {thematicName}",
"description": "ThematicPage: posts list heading"
diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
index bce493b..dea240f 100644
--- a/src/pages/article/[slug].tsx
+++ b/src/pages/article/[slug].tsx
@@ -15,6 +15,7 @@ import {
Sharing,
Spinner,
type MetaItemData,
+ Time,
} from '../../components';
import {
getAllArticlesSlugs,
@@ -26,7 +27,6 @@ import type { Article, NextPageWithLayout, SingleComment } from '../../types';
import { ROUTES } from '../../utils/constants';
import {
getBlogSchema,
- getFormattedDate,
getSchemaJson,
getSinglePageSchema,
getWebPageSchema,
@@ -83,18 +83,6 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({
const { content, id, intro, meta, title } = article;
const { author, commentsCount, cover, dates, seo, thematics, topics } = meta;
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
author
? {
@@ -114,7 +102,7 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({
description: 'ArticlePage: publication date label',
id: 'RecdwX',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update && dates.publication !== dates.update
? {
@@ -124,7 +112,7 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({
description: 'ArticlePage: update date label',
id: 'ZAqGZ6',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
{
diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx
index 652b913..d9f7031 100644
--- a/src/pages/cv.tsx
+++ b/src/pages/cv.tsx
@@ -20,13 +20,13 @@ import {
SocialMedia,
ListItem,
type MetaItemData,
+ Time,
} from '../components';
import CVContent, { data, meta } from '../content/pages/cv.mdx';
import styles from '../styles/pages/cv.module.scss';
import type { NextPageWithLayout } from '../types';
import { PERSONAL_LINKS, ROUTES } from '../utils/constants';
import {
- getFormattedDate,
getSchemaJson,
getSinglePageSchema,
getWebPageSchema,
@@ -153,18 +153,6 @@ const CVPage: NextPageWithLayout = () => {
id: '+Dre5J',
});
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
{
id: 'publication-date',
@@ -173,7 +161,7 @@ const CVPage: NextPageWithLayout = () => {
description: 'Page: publication date label',
id: '4QbTDq',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update
? {
@@ -183,7 +171,7 @@ const CVPage: NextPageWithLayout = () => {
description: 'Page: update date label',
id: 'Ez8Qim',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
];
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index cdc51c5..fb6ba9a 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -21,17 +21,14 @@ import {
type SectionProps,
Heading,
Figure,
+ Time,
} from '../components';
import HomePageContent from '../content/pages/homepage.mdx';
import { getArticlesCard } from '../services/graphql';
import styles from '../styles/pages/home.module.scss';
import type { ArticleCard, NextPageWithLayout } from '../types';
import { PERSONAL_LINKS, ROUTES } from '../utils/constants';
-import {
- getFormattedDate,
- getSchemaJson,
- getWebPageSchema,
-} from '../utils/helpers';
+import { getSchemaJson, getWebPageSchema } from '../utils/helpers';
import { loadTranslation, type Messages } from '../utils/helpers/server';
import { useBreadcrumb, useSettings } from '../utils/hooks';
@@ -301,8 +298,6 @@ const HomePage: NextPageWithLayout<HomeProps> = ({ recentPosts }) => {
*/
const getRecentPosts = (): JSX.Element => {
const posts: CardsListItem[] = recentPosts.map((post) => {
- const isoDate = new Date(`${post.dates.publication}`).toISOString();
-
return {
cover: post.cover,
id: post.slug,
@@ -310,11 +305,7 @@ const HomePage: NextPageWithLayout<HomeProps> = ({ recentPosts }) => {
{
id: 'publication-date',
label: publicationDate,
- value: (
- <time dateTime={isoDate}>
- {getFormattedDate(post.dates.publication)}
- </time>
- ),
+ value: <Time date={post.dates.publication} />,
},
],
title: post.title,
diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx
index 25c2dd9..4e14d90 100644
--- a/src/pages/mentions-legales.tsx
+++ b/src/pages/mentions-legales.tsx
@@ -12,12 +12,12 @@ import {
PageLayout,
Figure,
type MetaItemData,
+ Time,
} from '../components';
import LegalNoticeContent, { meta } from '../content/pages/legal-notice.mdx';
import type { NextPageWithLayout } from '../types';
import { ROUTES } from '../utils/constants';
import {
- getFormattedDate,
getSchemaJson,
getSinglePageSchema,
getWebPageSchema,
@@ -47,18 +47,6 @@ const LegalNoticePage: NextPageWithLayout = () => {
url: ROUTES.LEGAL_NOTICE,
});
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
{
id: 'publication-date',
@@ -67,7 +55,7 @@ const LegalNoticePage: NextPageWithLayout = () => {
description: 'Page: publication date label',
id: '4QbTDq',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update
? {
@@ -77,7 +65,7 @@ const LegalNoticePage: NextPageWithLayout = () => {
description: 'Page: update date label',
id: 'Ez8Qim',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
];
diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx
index 6ef3df5..3d3c57e 100644
--- a/src/pages/projets/[slug].tsx
+++ b/src/pages/projets/[slug].tsx
@@ -24,12 +24,12 @@ import {
Figure,
type MetaItemData,
type MetaValues,
+ Time,
} from '../../components';
import styles from '../../styles/pages/project.module.scss';
import type { NextPageWithLayout, ProjectPreview, Repos } from '../../types';
import { ROUTES } from '../../utils/constants';
import {
- getFormattedDate,
getSchemaJson,
getSinglePageSchema,
getWebPageSchema,
@@ -167,18 +167,6 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
url: `${website.url}${asPath}`,
};
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
{
id: 'publication-date',
@@ -187,7 +175,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
description: 'ProjectsPage: publication date label',
id: 'HxZvY4',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update && dates.update !== dates.publication
? {
@@ -197,7 +185,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
description: 'ProjectsPage: update date label',
id: 'wQrvgw',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
];
@@ -299,7 +287,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
description: 'ProjectsPage: creation date label',
id: 'wVFA4m',
}),
- value: getDate(data.created_at),
+ value: <Time date={data.created_at} />,
},
{
id: 'update-date',
@@ -308,7 +296,7 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
description: 'ProjectsPage: update date label',
id: 'wQrvgw',
}),
- value: getDate(data.updated_at),
+ value: <Time date={data.updated_at} />,
},
license
? {
diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx
index cacc972..87c3340 100644
--- a/src/pages/sujet/[slug].tsx
+++ b/src/pages/sujet/[slug].tsx
@@ -13,6 +13,7 @@ import {
type MetaItemData,
PageLayout,
PostsList,
+ Time,
} from '../../components';
import {
getAllTopicsSlugs,
@@ -24,7 +25,6 @@ import styles from '../../styles/pages/topic.module.scss';
import type { NextPageWithLayout, PageLink, Topic } from '../../types';
import { ROUTES } from '../../utils/constants';
import {
- getFormattedDate,
getLinksListItems,
getPageLinkFromRawData,
getPostsWithUrl,
@@ -60,18 +60,6 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
url: `${ROUTES.TOPICS}/${slug}`,
});
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
{
id: 'publication-date',
@@ -80,7 +68,7 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
description: 'TopicPage: publication date label',
id: 'KV+NMZ',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update
? {
@@ -90,7 +78,7 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
description: 'TopicPage: update date label',
id: '9DfuHk',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
officialWebsite
diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx
index a5badf3..8e21ff6 100644
--- a/src/pages/thematique/[slug].tsx
+++ b/src/pages/thematique/[slug].tsx
@@ -12,6 +12,7 @@ import {
type MetaItemData,
PageLayout,
PostsList,
+ Time,
} from '../../components';
import {
getAllThematicsSlugs,
@@ -22,7 +23,6 @@ import {
import type { NextPageWithLayout, PageLink, Thematic } from '../../types';
import { ROUTES } from '../../utils/constants';
import {
- getFormattedDate,
getLinksListItems,
getPageLinkFromRawData,
getPostsWithUrl,
@@ -51,18 +51,6 @@ const ThematicPage: NextPageWithLayout<ThematicPageProps> = ({
url: `${ROUTES.THEMATICS.INDEX}/${slug}`,
});
- /**
- * 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 headerMeta: (MetaItemData | undefined)[] = [
{
id: 'publication-date',
@@ -71,7 +59,7 @@ const ThematicPage: NextPageWithLayout<ThematicPageProps> = ({
description: 'ThematicPage: publication date label',
id: 'UTGhUU',
}),
- value: getDate(dates.publication),
+ value: <Time date={dates.publication} />,
},
dates.update
? {
@@ -81,7 +69,7 @@ const ThematicPage: NextPageWithLayout<ThematicPageProps> = ({
description: 'ThematicPage: update date label',
id: '24FIsG',
}),
- value: getDate(dates.update),
+ value: <Time date={dates.update} />,
}
: undefined,
articles
diff --git a/src/utils/helpers/dates.ts b/src/utils/helpers/dates.ts
deleted file mode 100644
index 82c14db..0000000
--- a/src/utils/helpers/dates.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { settings } from '../config';
-
-/**
- * Format a date based on a locale.
- *
- * @param {string} date - The date.
- * @param {string} [locale] - A locale.
- * @returns {string} The locale date string.
- */
-export const getFormattedDate = (
- date: string,
- locale: string = settings.locales.defaultLocale
-): string => {
- const dateOptions: Intl.DateTimeFormatOptions = {
- day: 'numeric',
- month: 'long',
- year: 'numeric',
- };
-
- return new Date(date).toLocaleDateString(locale, dateOptions);
-};
-
-/**
- * Format a time based on a locale.
- *
- * @param {string} time - The time.
- * @param {string} [locale] - A locale.
- * @returns {string} The locale time string.
- */
-export const getFormattedTime = (
- time: string,
- locale: string = settings.locales.defaultLocale
-): string => {
- const formattedTime = new Date(time).toLocaleTimeString(locale, {
- hour: 'numeric',
- minute: 'numeric',
- });
-
- return locale === 'fr' ? formattedTime.replace(':', 'h') : formattedTime;
-};
diff --git a/src/utils/helpers/index.ts b/src/utils/helpers/index.ts
index 1a35583..b2a4534 100644
--- a/src/utils/helpers/index.ts
+++ b/src/utils/helpers/index.ts
@@ -1,5 +1,4 @@
export * from './author';
-export * from './dates';
export * from './images';
export * from './pages';
export * from './rss';