diff --git a/routes/pricing.tsx b/routes/pricing.tsx index da43acb41..a55e3c439 100644 --- a/routes/pricing.tsx +++ b/routes/pricing.tsx @@ -8,7 +8,7 @@ import { stripe, StripProductWithPrice, } from "@/utils/stripe.ts"; -import { formatAmountForDisplay } from "@/utils/display.ts"; +import { formatCurrency } from "@/utils/display.ts"; import Stripe from "stripe"; import IconCheckCircle from "tabler_icons_tsx/circle-check.tsx"; import Head from "@/components/Head.tsx"; @@ -83,7 +83,7 @@ function PremiumPlanCard(

- {formatAmountForDisplay( + {formatCurrency( defaultPrice.unit_amount! / 100, defaultPrice?.currency, )} diff --git a/utils/display.ts b/utils/display.ts index 252fbb015..fc2b62c86 100644 --- a/utils/display.ts +++ b/utils/display.ts @@ -10,7 +10,6 @@ import { difference } from "std/datetime/difference.ts"; * * pluralize(0, "meow"); // Returns "0 meows" * pluralize(1, "meow"); // Returns "1 meow" - * pluralize(2, "meow"); // Returns "2 meows" * ``` */ export function pluralize(amount: number, unit: string) { @@ -26,7 +25,6 @@ export function pluralize(amount: number, unit: string) { * import { SECOND, MINUTE, HOUR } from "std/datetime/constants.ts"; * * timeAgo(new Date()); // Returns "just now" - * timeAgo(new Date(Date.now() - MINUTE)); // Returns "2 minutes ago" * timeAgo(new Date(Date.now() - 3 * HOUR)); // Returns "3 hours ago" * ``` */ @@ -55,11 +53,24 @@ export function timeAgo(date: Date) { return pluralize(amount, unit.slice(0, -1)) + " ago"; } -export function formatAmountForDisplay( +/** + * Returns a formatted string based on the given amount of currency and the + * machine's preferred language. + * + * @see {@linkcode Intl.NumberFormat} + * + * @example + * ```ts + * import { formatCurrency } from "@/utils/display.ts"; + * + * formatCurrency(4, "USD"); // Returns "$5" + * ``` + */ +export function formatCurrency( amount: number, currency: string, ): string { - const numberFormat = new Intl.NumberFormat( + return new Intl.NumberFormat( navigator.language, { style: "currency", @@ -67,6 +78,8 @@ export function formatAmountForDisplay( currencyDisplay: "symbol", maximumFractionDigits: 0, }, - ); - return numberFormat.format(amount); + ).format(amount) + // Issue: https://stackoverflow.com/questions/44533919/space-after-symbol-with-js-intl + .replace(/^(\D+)/, "$1") + .replace(/\s+/, ""); } diff --git a/utils/display_test.ts b/utils/display_test.ts index 55978c700..ec6cda684 100644 --- a/utils/display_test.ts +++ b/utils/display_test.ts @@ -1,7 +1,7 @@ // Copyright 2023 the Deno authors. All rights reserved. MIT license. -import { pluralize, timeAgo } from "./display.ts"; +import { formatCurrency, pluralize, timeAgo } from "./display.ts"; import { DAY, HOUR, MINUTE, SECOND } from "std/datetime/constants.ts"; -import { assertEquals } from "std/assert/mod.ts"; +import { assertEquals, assertThrows } from "std/assert/mod.ts"; Deno.test("[display] pluralize()", () => { assertEquals(pluralize(0, "item"), "0 items"); @@ -24,4 +24,13 @@ Deno.test("[display] timeAgo()", () => { assertEquals(timeAgo(new Date(Date.now() - DAY)), "1 day ago"); assertEquals(timeAgo(new Date(Date.now() - DAY - HOUR * 12)), "1 day ago"); assertEquals(timeAgo(new Date(Date.now() - DAY * 5)), "5 days ago"); + assertThrows( + () => timeAgo(new Date(Date.now() + 1)), + Error, + "Timestamp must be in the past", + ); +}); + +Deno.test("[display] formatCurrency()", () => { + assertEquals(formatCurrency(5, "USD"), "$5"); });