date formatter in a single file
This commit is contained in:
parent
5e0c2ae643
commit
4bc24f5395
@ -1,10 +1,6 @@
|
|||||||
const formatter = Intl.DateTimeFormat("en-US", {
|
import { formatDate } from "../../core/helpers/date-formatter";
|
||||||
day: "2-digit",
|
|
||||||
month: "short",
|
|
||||||
year: "numeric",
|
|
||||||
});
|
|
||||||
|
|
||||||
export default function DateComponent({ dateString }: any) {
|
export default function DateComponent({ dateString }: any) {
|
||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
return <time dateTime={dateString}>{formatter.format(date)}</time>;
|
return <time dateTime={dateString}>{formatDate(date)}</time>;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
import { Link, Routes } from "blitz";
|
import { Link, Routes } from "blitz";
|
||||||
import PostPreview from "./post-preview";
|
|
||||||
import type { Post } from "../../../integrations/datocms";
|
import type { Post } from "../../../integrations/datocms";
|
||||||
|
import { formatDate } from "../../core/helpers/date-formatter";
|
||||||
|
|
||||||
|
import PostPreview from "./post-preview";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
posts: Post[];
|
posts: Post[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatter = Intl.DateTimeFormat("en-US", {
|
|
||||||
day: "2-digit",
|
|
||||||
month: "short",
|
|
||||||
year: "numeric",
|
|
||||||
});
|
|
||||||
|
|
||||||
export default function MoreStories({ posts }: Props) {
|
export default function MoreStories({ posts }: Props) {
|
||||||
return (
|
return (
|
||||||
<aside>
|
<aside>
|
||||||
@ -46,9 +43,7 @@ export default function MoreStories({ posts }: Props) {
|
|||||||
</h3>
|
</h3>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="text-sm opacity-80">
|
<div className="text-sm opacity-80">{formatDate(new Date(post.date))}</div>
|
||||||
{formatter.format(new Date(post.date))}
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
<footer>
|
<footer>
|
||||||
{/* Author meta */}
|
{/* Author meta */}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import type { BlitzPage, GetStaticPaths, GetStaticProps } from "blitz";
|
import type { BlitzPage, GetStaticPaths, GetStaticProps } from "blitz";
|
||||||
import { Head, useRouter } from "blitz";
|
import { useRouter } from "blitz";
|
||||||
import ErrorPage from "next/error";
|
import ErrorPage from "next/error";
|
||||||
|
|
||||||
import type { Post } from "integrations/datocms";
|
import type { Post } from "integrations/datocms";
|
||||||
import { getAllPostsWithSlug, getPostAndMorePosts, markdownToHtml } from "integrations/datocms";
|
import { getAllPostsWithSlug, getPostAndMorePosts, markdownToHtml } from "integrations/datocms";
|
||||||
|
import { formatDate } from "../../../core/helpers/date-formatter";
|
||||||
|
|
||||||
import Header from "../../../public-area/components/header";
|
import Header from "../../../public-area/components/header";
|
||||||
import PostBody from "../../components/post-body";
|
import PostBody from "../../components/post-body";
|
||||||
import SectionSeparator from "../../components/section-separator";
|
import SectionSeparator from "../../components/section-separator";
|
||||||
@ -15,12 +17,6 @@ type Props = {
|
|||||||
preview: boolean;
|
preview: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatter = Intl.DateTimeFormat("en-US", {
|
|
||||||
day: "2-digit",
|
|
||||||
month: "short",
|
|
||||||
year: "numeric",
|
|
||||||
});
|
|
||||||
|
|
||||||
const PostPage: BlitzPage<Props> = ({ post, morePosts, preview }) => {
|
const PostPage: BlitzPage<Props> = ({ post, morePosts, preview }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
if (!router.isFallback && !post?.slug) {
|
if (!router.isFallback && !post?.slug) {
|
||||||
@ -81,7 +77,7 @@ const PostPage: BlitzPage<Props> = ({ post, morePosts, preview }) => {
|
|||||||
</a>
|
</a>
|
||||||
<span className="text-gray-600 dark:text-gray-400">
|
<span className="text-gray-600 dark:text-gray-400">
|
||||||
{" "}
|
{" "}
|
||||||
· {formatter.format(new Date(post.date))}
|
· {formatDate(new Date(post.date))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
48
app/core/helpers/date-formatter.ts
Normal file
48
app/core/helpers/date-formatter.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
|
export function formatDate(date: Date, config?: Intl.DateTimeFormatOptions): string {
|
||||||
|
const dateFormatter = Intl.DateTimeFormat(
|
||||||
|
"en-US",
|
||||||
|
config ?? {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "short",
|
||||||
|
year: "numeric",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return dateFormatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatTime(date: Date, config?: Intl.DateTimeFormatOptions): string {
|
||||||
|
const timeFormatter = Intl.DateTimeFormat(
|
||||||
|
"en-US",
|
||||||
|
config ?? {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return timeFormatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatRelativeDate(date: Date): string {
|
||||||
|
const dateTime = DateTime.fromJSDate(date);
|
||||||
|
const diff = dateTime.diffNow("days");
|
||||||
|
|
||||||
|
const isToday = diff.days >= -1;
|
||||||
|
if (isToday) {
|
||||||
|
return dateTime.toFormat("HH:mm", { locale: "en-US" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const isYesterday = diff.days >= -2;
|
||||||
|
if (isYesterday) {
|
||||||
|
return "Yesterday";
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDuringLastWeek = diff.days >= -7;
|
||||||
|
if (isDuringLastWeek) {
|
||||||
|
return dateTime.weekdayLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateTime.toFormat("dd/MM/yyyy", { locale: "en-US" });
|
||||||
|
}
|
@ -5,6 +5,7 @@ import clsx from "clsx";
|
|||||||
import { Direction } from "../../../db";
|
import { Direction } from "../../../db";
|
||||||
import useConversation from "../hooks/use-conversation";
|
import useConversation from "../hooks/use-conversation";
|
||||||
import NewMessageArea from "./new-message-area";
|
import NewMessageArea from "./new-message-area";
|
||||||
|
import { formatDate, formatTime } from "../../core/helpers/date-formatter";
|
||||||
|
|
||||||
export default function Conversation() {
|
export default function Conversation() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -42,18 +43,13 @@ export default function Conversation() {
|
|||||||
{(!isPreviousMessageFromSameSender || !shouldGroupMessages) && (
|
{(!isPreviousMessageFromSameSender || !shouldGroupMessages) && (
|
||||||
<div className="flex py-2 space-x-1 text-xs justify-center">
|
<div className="flex py-2 space-x-1 text-xs justify-center">
|
||||||
<strong>
|
<strong>
|
||||||
{new Date(message.sentAt).toLocaleDateString("en-US", {
|
{formatDate(new Date(message.sentAt), {
|
||||||
weekday: "long",
|
weekday: "long",
|
||||||
day: "2-digit",
|
day: "2-digit",
|
||||||
month: "short",
|
month: "short",
|
||||||
})}
|
})}
|
||||||
</strong>
|
</strong>
|
||||||
<span>
|
<span>{formatTime(new Date(message.sentAt))}</span>
|
||||||
{new Date(message.sentAt).toLocaleTimeString("en-US", {
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Link, useQuery, Routes } from "blitz";
|
import { Link, useQuery, Routes } from "blitz";
|
||||||
import { DateTime } from "luxon";
|
|
||||||
import { faChevronRight } from "@fortawesome/pro-regular-svg-icons";
|
import { faChevronRight } from "@fortawesome/pro-regular-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import getConversationsQuery from "../queries/get-conversations";
|
import getConversationsQuery from "../queries/get-conversations";
|
||||||
|
import { formatRelativeDate } from "../../core/helpers/date-formatter";
|
||||||
|
|
||||||
export default function ConversationsList() {
|
export default function ConversationsList() {
|
||||||
const conversations = useQuery(getConversationsQuery, {})[0];
|
const conversations = useQuery(getConversationsQuery, {})[0];
|
||||||
@ -23,7 +23,7 @@ export default function ConversationsList() {
|
|||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
<strong>{formattedPhoneNumber}</strong>
|
<strong>{formattedPhoneNumber}</strong>
|
||||||
<div className="text-gray-700 flex flex-row gap-x-1">
|
<div className="text-gray-700 flex flex-row gap-x-1">
|
||||||
{formatMessageDate(lastMessage.sentAt)}
|
{formatRelativeDate(lastMessage.sentAt)}
|
||||||
<FontAwesomeIcon className="w-4 h-4 my-auto" icon={faChevronRight} />
|
<FontAwesomeIcon className="w-4 h-4 my-auto" icon={faChevronRight} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,20 +36,3 @@ export default function ConversationsList() {
|
|||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatMessageDate(date: Date): string {
|
|
||||||
const messageDate = DateTime.fromJSDate(date);
|
|
||||||
const diff = messageDate.diffNow("days");
|
|
||||||
|
|
||||||
const isToday = diff.days > -1;
|
|
||||||
if (isToday) {
|
|
||||||
return messageDate.toFormat("HH:mm", { locale: "en-US" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const isDuringLastWeek = diff.days > -8;
|
|
||||||
if (isDuringLastWeek) {
|
|
||||||
return messageDate.weekdayLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
return messageDate.toFormat("dd/MM/yyyy", { locale: "en-US" });
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import type { BlitzPage } from "blitz";
|
import type { BlitzPage } from "blitz";
|
||||||
import { Head } from "blitz";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { CheckIcon, XIcon, TerminalIcon } from "@heroicons/react/solid";
|
import { CheckIcon, XIcon, TerminalIcon } from "@heroicons/react/solid";
|
||||||
|
|
||||||
import Header from "../components/header";
|
import { formatDate } from "../../core/helpers/date-formatter";
|
||||||
import Footer from "../components/footer";
|
|
||||||
import Layout from "../components/layout";
|
import Layout from "../components/layout";
|
||||||
|
|
||||||
const Roadmap: BlitzPage = () => {
|
const Roadmap: BlitzPage = () => {
|
||||||
@ -45,7 +44,7 @@ const Roadmap: BlitzPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
{isDone ? (
|
{isDone ? (
|
||||||
<div className="text-right self-start text-md xl:text-lg whitespace-nowrap text-gray-500">
|
<div className="text-right self-start text-md xl:text-lg whitespace-nowrap text-gray-500">
|
||||||
<time>{formatter.format(feature.doneDate)}</time>
|
<time>{formatDate(feature.doneDate)}</time>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
@ -131,12 +130,6 @@ const roadmap: RoadmapItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const formatter = Intl.DateTimeFormat("en-US", {
|
|
||||||
day: "2-digit",
|
|
||||||
month: "short",
|
|
||||||
year: "numeric",
|
|
||||||
});
|
|
||||||
|
|
||||||
Roadmap.getLayout = (page) => <Layout title="(Rough) Roadmap">{page}</Layout>;
|
Roadmap.getLayout = (page) => <Layout title="(Rough) Roadmap">{page}</Layout>;
|
||||||
Roadmap.suppressFirstRenderFlicker = true;
|
Roadmap.suppressFirstRenderFlicker = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user