diff --git a/front_end/src/app/(main)/(leaderboards)/leaderboard/components/leaderboard_table/table_row.tsx b/front_end/src/app/(main)/(leaderboards)/leaderboard/components/leaderboard_table/table_row.tsx index d50e4d4918..288f593613 100644 --- a/front_end/src/app/(main)/(leaderboards)/leaderboard/components/leaderboard_table/table_row.tsx +++ b/front_end/src/app/(main)/(leaderboards)/leaderboard/components/leaderboard_table/table_row.tsx @@ -9,7 +9,7 @@ import { LeaderboardType, } from "@/types/scoring"; import cn from "@/utils/core/cn"; -import { abbreviatedNumber } from "@/utils/formatters/number"; +import { formatNumberBipm } from "@/utils/formatters/number"; import { formatUsername } from "@/utils/formatters/users"; import MedalIcon from "../../../components/medal_icon"; @@ -27,6 +27,17 @@ type Props = { isUserRow?: boolean; }; +const DEFAULT_SCORE_FORMAT_OPTIONS: Intl.NumberFormatOptions = { + minimumFractionDigits: 2, + maximumFractionDigits: 2, +}; +const SCORE_FORMAT_OPTIONS: Partial< + Record +> = { + baseline_global: { minimumFractionDigits: 0, maximumFractionDigits: 0 }, + peer_global: { minimumFractionDigits: 1, maximumFractionDigits: 1 }, +}; + const LeaderboardRow: FC = ({ rowEntry, scoreType, @@ -108,29 +119,35 @@ const LeaderboardRow: FC = ({ - + - {abbreviatedNumber(contribution_count, 3, false)} + {formatNumberBipm(contribution_count, { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + })} {scoreType == "peer_global" && ( - + - {abbreviatedNumber(coverage, 3, false)} + {formatNumberBipm(coverage, { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + })} )} @@ -139,7 +156,10 @@ const LeaderboardRow: FC = ({ className="flex items-center justify-end px-4 py-2.5 text-sm no-underline" prefetch={false} > - {abbreviatedNumber(score, 3, false)} + {formatNumberBipm( + score, + SCORE_FORMAT_OPTIONS[scoreType] ?? DEFAULT_SCORE_FORMAT_OPTIONS + )} diff --git a/front_end/src/utils/formatters/number.ts b/front_end/src/utils/formatters/number.ts index e9909b606b..f5caefdb21 100644 --- a/front_end/src/utils/formatters/number.ts +++ b/front_end/src/utils/formatters/number.ts @@ -120,3 +120,19 @@ export function formatNumberWithUnit( } return `${formattedNumber} ${unit}`; } + +/** + * Format a number using BIPM-style thousands separation with narrow non-breaking spaces (U+202F) + * and a dot as the decimal separator. + */ +export function formatNumberBipm( + val: number | string | null | undefined, + options?: Intl.NumberFormatOptions +): string { + let num = Number(val); + if (Number.isNaN(num)) { + num = 0; + } + + return num.toLocaleString("en-US", options).replace(/,/g, "\u202F"); +}