diff --git a/app/components/NextEventInfo/NextEventInfo.tsx b/app/components/NextEventInfo/NextEventInfo.tsx index 2b77e35..ca1c486 100644 --- a/app/components/NextEventInfo/NextEventInfo.tsx +++ b/app/components/NextEventInfo/NextEventInfo.tsx @@ -1,5 +1,5 @@ import type { MeetupEvent } from "~/models/meetup.parsing"; -import { isEmptyString } from "~/utils"; +import { formatDateTime, isEmptyString } from "~/utils"; import MeetupLink from "~/components/MeetupLink"; import type { SerializeFrom } from "@remix-run/server-runtime"; @@ -12,16 +12,6 @@ const DEFAULT_VENUE: Venue = { state: "TX", }; -const EVENT_TIME_FORMAT = new Intl.DateTimeFormat("en-US", { - weekday: "short", - month: "short", - day: "numeric", - hour: "numeric", - minute: "2-digit", - timeZoneName: "short", - timeZone: "America/Chicago", -}); - function isValidVenue(venue: MeetupEvent["venue"]): venue is Venue { return ( venue !== null && @@ -48,9 +38,7 @@ export default function NextEventInfo({
{event.title}
- +
{venue.name}
diff --git a/app/utils.test.ts b/app/utils.test.ts index 761ec5b..c039ae1 100644 --- a/app/utils.test.ts +++ b/app/utils.test.ts @@ -3,6 +3,7 @@ import { safeRedirect, getRedirectUrlIfWww, isEmptyString, + formatDateTime, } from "./utils"; describe("utils", () => { @@ -123,10 +124,11 @@ describe("utils", () => { }); }); - // TODO - // describe("useMatchesData", () => { - // it("safeRedirect", () => { - // expect(validateEmail("kody@example.com")).toBe(true); - // }); - // }); + describe("formatDateTime", () => { + it("Correctly formats a date string", () => { + const dateTime = "2023-03-08T15:06:39.096Z"; + const formattedDateTime = formatDateTime(dateTime); + expect(formattedDateTime).toBe("Wed, Mar 8, 9:06 AM CST"); + }); + }); }); diff --git a/app/utils.ts b/app/utils.ts index 27cf63b..1ee6f56 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -74,3 +74,29 @@ export function isEmptyString(val: unknown): boolean { export type PropsWithRequiredChildren
= P & { children: ReactNode; }; + +const eventTimeFormat = new Intl.DateTimeFormat("en-US", { + weekday: "short", + month: "short", + day: "numeric", + hour: "numeric", + minute: "2-digit", + timeZoneName: "short", + timeZone: "America/Chicago", +}); + +const NARROW_NON_BREAK_SPACE = String.fromCharCode(8239); + +// Note: if we have more date formatting needs we can seperate this function and others +// into a dedicated utils file + +/** + * Formats an date string into a more human readable format + * For example: "2023-03-08T15:06:39.096Z" -> "Wed, Mar 8, 9:06 AM CST" + */ +export function formatDateTime(dateTime: string) { + // Discrepency between server and client, see https://github.com/remix-austin/remixaustin-com/issues/83#issuecomment-1450654389 + return eventTimeFormat + .format(new Date(dateTime)) + .replaceAll(NARROW_NON_BREAK_SPACE, " "); +} diff --git a/tsconfig.json b/tsconfig.json index 2a705a6..f3ffd93 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "exclude": ["./e2e"], "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], "compilerOptions": { - "lib": ["DOM", "DOM.Iterable", "ES2019"], + "lib": ["DOM", "DOM.Iterable", "ES2021"], "types": ["vitest/globals"], "isolatedModules": true, "esModuleInterop": true, @@ -10,7 +10,7 @@ "module": "CommonJS", "moduleResolution": "node", "resolveJsonModule": true, - "target": "ES2019", + "target": "ES2021", "strict": true, "allowJs": true, "forceConsistentCasingInFileNames": true,