diff --git a/src/app/(main)/reports/funnel/FunnelChart.tsx b/src/app/(main)/reports/funnel/FunnelChart.tsx index 61fe268da..8fb60c9ff 100644 --- a/src/app/(main)/reports/funnel/FunnelChart.tsx +++ b/src/app/(main)/reports/funnel/FunnelChart.tsx @@ -39,7 +39,7 @@ export function FunnelChart({ className }: FunnelChartProps) { {formatMessage(labels.visitors)}
- {intl.formatNumber(+remaining, { style: 'percent', maximumFractionDigits: 1 })} + {intl.formatNumber(remaining, { style: 'percent', maximumFractionDigits: 1 })}
@@ -49,7 +49,7 @@ export function FunnelChart({ className }: FunnelChartProps) {
{intl.formatNumber(dropped, formatLongNumberOptions(dropped))}{' '} {formatMessage(labels.visitorsDroppedOff)} ( - {intl.formatNumber(+dropoff, { style: 'percent', maximumFractionDigits: 1 })}) + {intl.formatNumber(dropoff, { style: 'percent', maximumFractionDigits: 1 })})
)}
diff --git a/src/app/(main)/reports/goals/GoalsChart.tsx b/src/app/(main)/reports/goals/GoalsChart.tsx index dedbd07cb..a3ee3120b 100644 --- a/src/app/(main)/reports/goals/GoalsChart.tsx +++ b/src/app/(main)/reports/goals/GoalsChart.tsx @@ -2,12 +2,14 @@ import { useContext } from 'react'; import classNames from 'classnames'; import { useMessages } from 'components/hooks'; import { ReportContext } from '../[reportId]/Report'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; +import { useIntl } from 'react-intl'; import styles from './GoalsChart.module.css'; export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) { const { report } = useContext(ReportContext); const { formatMessage, labels } = useMessages(); + const intl = useIntl(); const { data } = report || {}; @@ -58,10 +60,15 @@ export function GoalsChart({ className }: { className?: string; isLoading?: bool
- {formatLongNumber(result)} - / {formatLongNumber(goal)} + {intl.formatNumber(result, formatLongNumberOptions(result))} + + {' '} + / {intl.formatNumber(goal, formatLongNumberOptions(goal))} + +
+
+ {intl.formatNumber(result / goal, { style: 'percent', maximumFractionDigits: 1 })}
-
{((result / goal) * 100).toFixed(2)}%
diff --git a/src/app/(main)/reports/revenue/RevenueChart.tsx b/src/app/(main)/reports/revenue/RevenueChart.tsx index aee6df6c4..c0c416ea0 100644 --- a/src/app/(main)/reports/revenue/RevenueChart.tsx +++ b/src/app/(main)/reports/revenue/RevenueChart.tsx @@ -3,7 +3,7 @@ import { useLocale, useMessages } from 'components/hooks'; import MetricCard from 'components/metrics/MetricCard'; import MetricsBar from 'components/metrics/MetricsBar'; import { renderDateLabels } from 'lib/charts'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; import { useContext, useMemo } from 'react'; import { ReportContext } from '../[reportId]/Report'; import { useIntl } from 'react-intl'; @@ -57,22 +57,22 @@ export function RevenueChart({ isLoading, ...props }: PageviewsChartProps) { { value: sum, label: formatMessage(labels.total), - formatValue: formatLongNumber, + formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)), }, { value: avg, label: formatMessage(labels.average), - formatValue: formatLongNumber, + formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)), }, { value: count, label: formatMessage(labels.transactions), - formatValue: formatLongNumber, + formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)), }, { value: uniqueCount, label: formatMessage(labels.uniqueCustomers), - formatValue: formatLongNumber, + formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)), }, ] as any; }, [data, locale]); diff --git a/src/components/charts/BarChart.tsx b/src/components/charts/BarChart.tsx index 7624ba1c4..935cb7daa 100644 --- a/src/components/charts/BarChart.tsx +++ b/src/components/charts/BarChart.tsx @@ -1,7 +1,8 @@ import BarChartTooltip from 'components/charts/BarChartTooltip'; import Chart, { ChartProps } from 'components/charts/Chart'; import { useTheme } from 'components/hooks'; -import { renderNumberLabels } from 'lib/charts'; +import { formatLongNumberOptions } from 'lib/format'; +import { useIntl } from 'react-intl'; import { useMemo, useState } from 'react'; export interface BarChartProps extends ChartProps { @@ -18,6 +19,7 @@ export interface BarChartProps extends ChartProps { export function BarChart(props: BarChartProps) { const [tooltip, setTooltip] = useState(null); const { colors } = useTheme(); + const intl = useIntl(); const { renderXLabel, renderYLabel, @@ -66,7 +68,8 @@ export function BarChart(props: BarChartProps) { }, ticks: { color: colors.chart.text, - callback: renderYLabel || renderNumberLabels, + callback: (n: number) => + renderYLabel || intl.formatNumber(n, formatLongNumberOptions(n)), }, }, }, diff --git a/src/components/charts/BarChartTooltip.tsx b/src/components/charts/BarChartTooltip.tsx index f9ce49757..4e0c4cb99 100644 --- a/src/components/charts/BarChartTooltip.tsx +++ b/src/components/charts/BarChartTooltip.tsx @@ -1,5 +1,5 @@ import { Flexbox, StatusLight } from 'react-basics'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; import { useIntl } from 'react-intl'; const formats = { @@ -31,7 +31,8 @@ export default function BarChartTooltip({ tooltip, unit }) {
{intl.formatDate(dataPoints[0].raw.d || dataPoints[0].raw.x, formats[unit])}
- {formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label} + {intl.formatNumber(dataPoints[0].raw.y, formatLongNumberOptions(dataPoints[0].raw.y))}{' '} + {dataPoints[0].dataset.label}
diff --git a/src/components/charts/BubbleChart.tsx b/src/components/charts/BubbleChart.tsx index 956e260cb..cf74823b9 100644 --- a/src/components/charts/BubbleChart.tsx +++ b/src/components/charts/BubbleChart.tsx @@ -1,7 +1,8 @@ import { Chart, ChartProps } from 'components/charts/Chart'; import { useState } from 'react'; import { StatusLight } from 'react-basics'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; +import { useIntl } from 'react-intl'; export interface BubbleChartProps extends ChartProps { type?: 'bubble'; @@ -10,6 +11,7 @@ export interface BubbleChartProps extends ChartProps { export default function BubbleChart(props: BubbleChartProps) { const [tooltip, setTooltip] = useState(null); const { type = 'bubble' } = props; + const intl = useIntl(); const handleTooltip = ({ tooltip }) => { const { labelColors, dataPoints } = tooltip; @@ -17,7 +19,8 @@ export default function BubbleChart(props: BubbleChartProps) { setTooltip( tooltip.opacity ? ( - {formatLongNumber(dataPoints?.[0]?.raw)} {dataPoints?.[0]?.label} + {intl.formatNumber(dataPoints?.[0]?.raw, formatLongNumberOptions(dataPoints?.[0]?.raw))}{' '} + {dataPoints?.[0]?.label} ) : null, ); diff --git a/src/components/charts/PieChart.tsx b/src/components/charts/PieChart.tsx index 57d676cae..de425ff13 100644 --- a/src/components/charts/PieChart.tsx +++ b/src/components/charts/PieChart.tsx @@ -1,7 +1,8 @@ import { Chart, ChartProps } from 'components/charts/Chart'; import { useState } from 'react'; import { StatusLight } from 'react-basics'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; +import { useIntl } from 'react-intl'; export interface PieChartProps extends ChartProps { type?: 'doughnut' | 'pie'; @@ -10,6 +11,7 @@ export interface PieChartProps extends ChartProps { export default function PieChart(props: PieChartProps) { const [tooltip, setTooltip] = useState(null); const { type = 'pie' } = props; + const intl = useIntl(); const handleTooltip = ({ tooltip }) => { const { labelColors, dataPoints } = tooltip; @@ -17,7 +19,8 @@ export default function PieChart(props: PieChartProps) { setTooltip( tooltip.opacity ? ( - {formatLongNumber(dataPoints?.[0]?.raw)} {dataPoints?.[0]?.label} + {intl.formatNumber(dataPoints?.[0]?.raw, formatLongNumberOptions(dataPoints?.[0]?.raw))}{' '} + {dataPoints?.[0]?.label} ) : null, ); diff --git a/src/components/metrics/ListTable.tsx b/src/components/metrics/ListTable.tsx index fba44d218..f578735ae 100644 --- a/src/components/metrics/ListTable.tsx +++ b/src/components/metrics/ListTable.tsx @@ -104,7 +104,7 @@ const AnimatedRow = ({ label, value = 0, percent, change, animate, showPercentag
`${n}%`) }} /> - {props.width.to(n => intl.formatNumber(+n / 100, { style: 'percent' }))} + {props.width.to(n => intl.formatNumber(n / 100, { style: 'percent' }))}
)} diff --git a/src/components/metrics/MetricsBar.tsx b/src/components/metrics/MetricsBar.tsx index 60a217067..01a6035ce 100644 --- a/src/components/metrics/MetricsBar.tsx +++ b/src/components/metrics/MetricsBar.tsx @@ -1,7 +1,8 @@ import { ReactNode } from 'react'; import { Loading, cloneChildren } from 'react-basics'; import ErrorMessage from 'components/common/ErrorMessage'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; +import { useIntl } from 'react-intl'; import styles from './MetricsBar.module.css'; export interface MetricsBarProps { @@ -12,7 +13,8 @@ export interface MetricsBarProps { } export function MetricsBar({ children, isLoading, isFetched, error }: MetricsBarProps) { - const formatFunc = n => (n >= 0 ? formatLongNumber(n) : `-${formatLongNumber(Math.abs(n))}`); + const intl = useIntl(); + const formatFunc = (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)); return (
diff --git a/src/components/metrics/WorldMap.tsx b/src/components/metrics/WorldMap.tsx index bbd769709..89c84009b 100644 --- a/src/components/metrics/WorldMap.tsx +++ b/src/components/metrics/WorldMap.tsx @@ -8,7 +8,7 @@ import { useDateRange, useTheme, useWebsiteMetrics } from 'components/hooks'; import { useIntl } from 'react-intl'; import { useLocale } from 'components/hooks'; import { useMessages } from 'components/hooks'; -import { formatLongNumber } from 'lib/format'; +import { formatLongNumberOptions } from 'lib/format'; import { percentFilter } from 'lib/filters'; import styles from './WorldMap.module.css'; @@ -62,8 +62,9 @@ export function WorldMap({ if (code === 'AQ') return; const country = metrics?.find(({ x }) => x === code); setTooltipPopup( - `${intl.formatDisplayName(code, { type: 'region' })}: ${formatLongNumber( + `${intl.formatDisplayName(code, { type: 'region' })}: ${intl.formatNumber( country?.y || 0, + formatLongNumberOptions(country?.y || 0), )} ${visitorsLabel}` as any, ); }; diff --git a/src/lib/charts.ts b/src/lib/charts.ts index 75037d11c..332a22e7b 100644 --- a/src/lib/charts.ts +++ b/src/lib/charts.ts @@ -1,10 +1,5 @@ -import { formatLongNumber } from 'lib/format'; import { type IntlShape } from 'react-intl'; -export function renderNumberLabels(label: string) { - return +label > 1000 ? formatLongNumber(+label) : label; -} - export function renderDateLabels(intl: IntlShape, unit: string) { return (label: string, index: number, values: any[]) => { const d = new Date(values[index].value); diff --git a/src/lib/format.ts b/src/lib/format.ts index 83c67067f..836040628 100644 --- a/src/lib/format.ts +++ b/src/lib/format.ts @@ -46,25 +46,6 @@ export function formatNumber(n: string | number) { return Number(n).toFixed(0); } -export function formatLongNumber(value: number) { - const n = Number(value); - - if (n >= 1000000) { - return `${(n / 1000000).toFixed(1)}m`; - } - if (n >= 100000) { - return `${(n / 1000).toFixed(0)}k`; - } - if (n >= 10000) { - return `${(n / 1000).toFixed(1)}k`; - } - if (n >= 1000) { - return `${(n / 1000).toFixed(2)}k`; - } - - return formatNumber(n); -} - export function formatLongNumberOptions(value: number): FormatNumberOptions { return value < 100 ? {