Replace formatLongNumber with intl.formatNumber

This commit is contained in:
Minseo Lee 2024-08-30 09:59:43 +09:00
parent 5636bd9617
commit 16f86c7715
12 changed files with 44 additions and 48 deletions

View file

@ -39,7 +39,7 @@ export function FunnelChart({ className }: FunnelChartProps) {
{formatMessage(labels.visitors)} {formatMessage(labels.visitors)}
</div> </div>
<div className={styles.percent}> <div className={styles.percent}>
{intl.formatNumber(+remaining, { style: 'percent', maximumFractionDigits: 1 })} {intl.formatNumber(remaining, { style: 'percent', maximumFractionDigits: 1 })}
</div> </div>
</div> </div>
<div className={styles.track}> <div className={styles.track}>
@ -49,7 +49,7 @@ export function FunnelChart({ className }: FunnelChartProps) {
<div className={styles.info}> <div className={styles.info}>
<b>{intl.formatNumber(dropped, formatLongNumberOptions(dropped))}</b>{' '} <b>{intl.formatNumber(dropped, formatLongNumberOptions(dropped))}</b>{' '}
{formatMessage(labels.visitorsDroppedOff)} ( {formatMessage(labels.visitorsDroppedOff)} (
{intl.formatNumber(+dropoff, { style: 'percent', maximumFractionDigits: 1 })}) {intl.formatNumber(dropoff, { style: 'percent', maximumFractionDigits: 1 })})
</div> </div>
)} )}
</div> </div>

View file

@ -2,12 +2,14 @@ import { useContext } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useMessages } from 'components/hooks'; import { useMessages } from 'components/hooks';
import { ReportContext } from '../[reportId]/Report'; 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'; import styles from './GoalsChart.module.css';
export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) { export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) {
const { report } = useContext(ReportContext); const { report } = useContext(ReportContext);
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const intl = useIntl();
const { data } = report || {}; const { data } = report || {};
@ -58,10 +60,15 @@ export function GoalsChart({ className }: { className?: string; isLoading?: bool
</div> </div>
<div className={styles.metric}> <div className={styles.metric}>
<div className={styles.value}> <div className={styles.value}>
{formatLongNumber(result)} {intl.formatNumber(result, formatLongNumberOptions(result))}
<span className={styles.total}> / {formatLongNumber(goal)}</span> <span className={styles.total}>
{' '}
/ {intl.formatNumber(goal, formatLongNumberOptions(goal))}
</span>
</div>
<div className={styles.percent}>
{intl.formatNumber(result / goal, { style: 'percent', maximumFractionDigits: 1 })}
</div> </div>
<div className={styles.percent}>{((result / goal) * 100).toFixed(2)}%</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -3,7 +3,7 @@ import { useLocale, useMessages } from 'components/hooks';
import MetricCard from 'components/metrics/MetricCard'; import MetricCard from 'components/metrics/MetricCard';
import MetricsBar from 'components/metrics/MetricsBar'; import MetricsBar from 'components/metrics/MetricsBar';
import { renderDateLabels } from 'lib/charts'; import { renderDateLabels } from 'lib/charts';
import { formatLongNumber } from 'lib/format'; import { formatLongNumberOptions } from 'lib/format';
import { useContext, useMemo } from 'react'; import { useContext, useMemo } from 'react';
import { ReportContext } from '../[reportId]/Report'; import { ReportContext } from '../[reportId]/Report';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
@ -57,22 +57,22 @@ export function RevenueChart({ isLoading, ...props }: PageviewsChartProps) {
{ {
value: sum, value: sum,
label: formatMessage(labels.total), label: formatMessage(labels.total),
formatValue: formatLongNumber, formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)),
}, },
{ {
value: avg, value: avg,
label: formatMessage(labels.average), label: formatMessage(labels.average),
formatValue: formatLongNumber, formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)),
}, },
{ {
value: count, value: count,
label: formatMessage(labels.transactions), label: formatMessage(labels.transactions),
formatValue: formatLongNumber, formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)),
}, },
{ {
value: uniqueCount, value: uniqueCount,
label: formatMessage(labels.uniqueCustomers), label: formatMessage(labels.uniqueCustomers),
formatValue: formatLongNumber, formatValue: (n: number) => intl.formatNumber(n, formatLongNumberOptions(n)),
}, },
] as any; ] as any;
}, [data, locale]); }, [data, locale]);

View file

@ -1,7 +1,8 @@
import BarChartTooltip from 'components/charts/BarChartTooltip'; import BarChartTooltip from 'components/charts/BarChartTooltip';
import Chart, { ChartProps } from 'components/charts/Chart'; import Chart, { ChartProps } from 'components/charts/Chart';
import { useTheme } from 'components/hooks'; 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'; import { useMemo, useState } from 'react';
export interface BarChartProps extends ChartProps { export interface BarChartProps extends ChartProps {
@ -18,6 +19,7 @@ export interface BarChartProps extends ChartProps {
export function BarChart(props: BarChartProps) { export function BarChart(props: BarChartProps) {
const [tooltip, setTooltip] = useState(null); const [tooltip, setTooltip] = useState(null);
const { colors } = useTheme(); const { colors } = useTheme();
const intl = useIntl();
const { const {
renderXLabel, renderXLabel,
renderYLabel, renderYLabel,
@ -66,7 +68,8 @@ export function BarChart(props: BarChartProps) {
}, },
ticks: { ticks: {
color: colors.chart.text, color: colors.chart.text,
callback: renderYLabel || renderNumberLabels, callback: (n: number) =>
renderYLabel || intl.formatNumber(n, formatLongNumberOptions(n)),
}, },
}, },
}, },

View file

@ -1,5 +1,5 @@
import { Flexbox, StatusLight } from 'react-basics'; import { Flexbox, StatusLight } from 'react-basics';
import { formatLongNumber } from 'lib/format'; import { formatLongNumberOptions } from 'lib/format';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
const formats = { const formats = {
@ -31,7 +31,8 @@ export default function BarChartTooltip({ tooltip, unit }) {
<div>{intl.formatDate(dataPoints[0].raw.d || dataPoints[0].raw.x, formats[unit])}</div> <div>{intl.formatDate(dataPoints[0].raw.d || dataPoints[0].raw.x, formats[unit])}</div>
<div> <div>
<StatusLight color={labelColors?.[0]?.backgroundColor}> <StatusLight color={labelColors?.[0]?.backgroundColor}>
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label} {intl.formatNumber(dataPoints[0].raw.y, formatLongNumberOptions(dataPoints[0].raw.y))}{' '}
{dataPoints[0].dataset.label}
</StatusLight> </StatusLight>
</div> </div>
</Flexbox> </Flexbox>

View file

@ -1,7 +1,8 @@
import { Chart, ChartProps } from 'components/charts/Chart'; import { Chart, ChartProps } from 'components/charts/Chart';
import { useState } from 'react'; import { useState } from 'react';
import { StatusLight } from 'react-basics'; 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 { export interface BubbleChartProps extends ChartProps {
type?: 'bubble'; type?: 'bubble';
@ -10,6 +11,7 @@ export interface BubbleChartProps extends ChartProps {
export default function BubbleChart(props: BubbleChartProps) { export default function BubbleChart(props: BubbleChartProps) {
const [tooltip, setTooltip] = useState(null); const [tooltip, setTooltip] = useState(null);
const { type = 'bubble' } = props; const { type = 'bubble' } = props;
const intl = useIntl();
const handleTooltip = ({ tooltip }) => { const handleTooltip = ({ tooltip }) => {
const { labelColors, dataPoints } = tooltip; const { labelColors, dataPoints } = tooltip;
@ -17,7 +19,8 @@ export default function BubbleChart(props: BubbleChartProps) {
setTooltip( setTooltip(
tooltip.opacity ? ( tooltip.opacity ? (
<StatusLight color={labelColors?.[0]?.backgroundColor}> <StatusLight color={labelColors?.[0]?.backgroundColor}>
{formatLongNumber(dataPoints?.[0]?.raw)} {dataPoints?.[0]?.label} {intl.formatNumber(dataPoints?.[0]?.raw, formatLongNumberOptions(dataPoints?.[0]?.raw))}{' '}
{dataPoints?.[0]?.label}
</StatusLight> </StatusLight>
) : null, ) : null,
); );

View file

@ -1,7 +1,8 @@
import { Chart, ChartProps } from 'components/charts/Chart'; import { Chart, ChartProps } from 'components/charts/Chart';
import { useState } from 'react'; import { useState } from 'react';
import { StatusLight } from 'react-basics'; 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 { export interface PieChartProps extends ChartProps {
type?: 'doughnut' | 'pie'; type?: 'doughnut' | 'pie';
@ -10,6 +11,7 @@ export interface PieChartProps extends ChartProps {
export default function PieChart(props: PieChartProps) { export default function PieChart(props: PieChartProps) {
const [tooltip, setTooltip] = useState(null); const [tooltip, setTooltip] = useState(null);
const { type = 'pie' } = props; const { type = 'pie' } = props;
const intl = useIntl();
const handleTooltip = ({ tooltip }) => { const handleTooltip = ({ tooltip }) => {
const { labelColors, dataPoints } = tooltip; const { labelColors, dataPoints } = tooltip;
@ -17,7 +19,8 @@ export default function PieChart(props: PieChartProps) {
setTooltip( setTooltip(
tooltip.opacity ? ( tooltip.opacity ? (
<StatusLight color={labelColors?.[0]?.backgroundColor}> <StatusLight color={labelColors?.[0]?.backgroundColor}>
{formatLongNumber(dataPoints?.[0]?.raw)} {dataPoints?.[0]?.label} {intl.formatNumber(dataPoints?.[0]?.raw, formatLongNumberOptions(dataPoints?.[0]?.raw))}{' '}
{dataPoints?.[0]?.label}
</StatusLight> </StatusLight>
) : null, ) : null,
); );

View file

@ -104,7 +104,7 @@ const AnimatedRow = ({ label, value = 0, percent, change, animate, showPercentag
<div className={styles.percent}> <div className={styles.percent}>
<animated.div className={styles.bar} style={{ width: props.width.to(n => `${n}%`) }} /> <animated.div className={styles.bar} style={{ width: props.width.to(n => `${n}%`) }} />
<animated.span> <animated.span>
{props.width.to(n => intl.formatNumber(+n / 100, { style: 'percent' }))} {props.width.to(n => intl.formatNumber(n / 100, { style: 'percent' }))}
</animated.span> </animated.span>
</div> </div>
)} )}

View file

@ -1,7 +1,8 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Loading, cloneChildren } from 'react-basics'; import { Loading, cloneChildren } from 'react-basics';
import ErrorMessage from 'components/common/ErrorMessage'; 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'; import styles from './MetricsBar.module.css';
export interface MetricsBarProps { export interface MetricsBarProps {
@ -12,7 +13,8 @@ export interface MetricsBarProps {
} }
export function MetricsBar({ children, isLoading, isFetched, error }: 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 ( return (
<div className={styles.bar}> <div className={styles.bar}>

View file

@ -8,7 +8,7 @@ import { useDateRange, useTheme, useWebsiteMetrics } from 'components/hooks';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useLocale } from 'components/hooks'; import { useLocale } from 'components/hooks';
import { useMessages } from 'components/hooks'; import { useMessages } from 'components/hooks';
import { formatLongNumber } from 'lib/format'; import { formatLongNumberOptions } from 'lib/format';
import { percentFilter } from 'lib/filters'; import { percentFilter } from 'lib/filters';
import styles from './WorldMap.module.css'; import styles from './WorldMap.module.css';
@ -62,8 +62,9 @@ export function WorldMap({
if (code === 'AQ') return; if (code === 'AQ') return;
const country = metrics?.find(({ x }) => x === code); const country = metrics?.find(({ x }) => x === code);
setTooltipPopup( setTooltipPopup(
`${intl.formatDisplayName(code, { type: 'region' })}: ${formatLongNumber( `${intl.formatDisplayName(code, { type: 'region' })}: ${intl.formatNumber(
country?.y || 0, country?.y || 0,
formatLongNumberOptions(country?.y || 0),
)} ${visitorsLabel}` as any, )} ${visitorsLabel}` as any,
); );
}; };

View file

@ -1,10 +1,5 @@
import { formatLongNumber } from 'lib/format';
import { type IntlShape } from 'react-intl'; import { type IntlShape } from 'react-intl';
export function renderNumberLabels(label: string) {
return +label > 1000 ? formatLongNumber(+label) : label;
}
export function renderDateLabels(intl: IntlShape, unit: string) { export function renderDateLabels(intl: IntlShape, unit: string) {
return (label: string, index: number, values: any[]) => { return (label: string, index: number, values: any[]) => {
const d = new Date(values[index].value); const d = new Date(values[index].value);

View file

@ -46,25 +46,6 @@ export function formatNumber(n: string | number) {
return Number(n).toFixed(0); 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 { export function formatLongNumberOptions(value: number): FormatNumberOptions {
return value < 100 return value < 100
? { ? {