i18n datetime

This commit is contained in:
Minseo Lee 2024-08-28 14:42:30 +09:00
parent 338c2f3071
commit 4c3f3cbc71
9 changed files with 57 additions and 55 deletions

View file

@ -2,15 +2,15 @@ import { useContext } from 'react';
import classNames from 'classnames';
import { ReportContext } from '../[reportId]/Report';
import EmptyPlaceholder from 'components/common/EmptyPlaceholder';
import { useMessages, useLocale } from 'components/hooks';
import { formatDate } from 'lib/date';
import { useMessages } from 'components/hooks';
import styles from './RetentionTable.module.css';
import { useIntl } from 'react-intl';
const DAYS = [1, 2, 3, 4, 5, 6, 7, 14, 21, 28];
export function RetentionTable({ days = DAYS }) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const intl = useIntl();
const { report } = useContext(ReportContext);
const { data } = report || {};
@ -52,7 +52,7 @@ export function RetentionTable({ days = DAYS }) {
{rows.map(({ date, visitors, records }, rowIndex) => {
return (
<div key={rowIndex} className={styles.row}>
<div className={styles.date}>{formatDate(date, 'PP', locale)}</div>
<div className={styles.date}>{intl.formatDate(date, { dateStyle: 'medium' })}</div>
<div className={styles.visitors}>{visitors}</div>
{days.map(day => {
if (totalDays - rowIndex < day) {

View file

@ -6,6 +6,7 @@ import { renderDateLabels } from 'lib/charts';
import { formatLongNumber } from 'lib/format';
import { useContext, useMemo } from 'react';
import { ReportContext } from '../[reportId]/Report';
import { useIntl } from 'react-intl';
export interface PageviewsChartProps extends BarChartProps {
isLoading?: boolean;
@ -14,6 +15,7 @@ export interface PageviewsChartProps extends BarChartProps {
export function RevenueChart({ isLoading, ...props }: PageviewsChartProps) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const intl = useIntl();
const { report } = useContext(ReportContext);
const { data, parameters } = report || {};
@ -88,7 +90,7 @@ export function RevenueChart({ isLoading, ...props }: PageviewsChartProps) {
data={chartData}
unit={parameters?.dateRange.unit}
isLoading={isLoading}
renderXLabel={renderDateLabels(parameters?.dateRange.unit, locale)}
renderXLabel={renderDateLabels(intl, parameters?.dateRange.unit)}
/>
)}
</>

View file

@ -1,29 +1,34 @@
import { formatDate } from 'lib/date';
import { Flexbox, StatusLight } from 'react-basics';
import { formatLongNumber } from 'lib/format';
import { useLocale } from 'components/hooks';
import { useIntl } from 'react-intl';
const formats = {
millisecond: 'T',
second: 'pp',
minute: 'p',
hour: 'h:mm aaa - PP',
day: 'PPPP',
week: 'PPPP',
month: 'LLLL yyyy',
quarter: 'qqq',
year: 'yyyy',
millisecond: {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
fractionalSecondDigits: 3,
},
second: { timeStyle: 'medium' },
minute: { timeStyle: 'short' },
hour: { dateStyle: 'medium', timeStyle: 'short' },
day: { dateStyle: 'full' },
week: { dateStyle: 'full' },
month: { year: 'numeric', month: 'long' },
quarter: { year: 'numeric', month: 'long' },
year: { year: 'numeric' },
};
export default function BarChartTooltip({ tooltip, unit }) {
const { locale } = useLocale();
const intl = useIntl();
const { labelColors, dataPoints } = tooltip;
return (
<Flexbox direction="column" gap={10}>
<div>
{formatDate(new Date(dataPoints[0].raw.d || dataPoints[0].raw.x), formats[unit], locale)}
</div>
<div>{intl.formatDate(dataPoints[0].raw.d || dataPoints[0].raw.x, formats[unit])}</div>
<div>
<StatusLight color={labelColors?.[0]?.backgroundColor}>
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label}

View file

@ -2,11 +2,12 @@ import { useState } from 'react';
import { Icon, Modal, Dropdown, Item, Text, Flexbox } from 'react-basics';
import { endOfYear, isSameDay } from 'date-fns';
import DatePickerForm from 'components/metrics/DatePickerForm';
import { useLocale, useMessages } from 'components/hooks';
import { useMessages } from 'components/hooks';
import Icons from 'components/icons';
import { formatDate, parseDateValue } from 'lib/date';
import { parseDateValue } from 'lib/date';
import styles from './DateFilter.module.css';
import classNames from 'classnames';
import { useIntl } from 'react-intl';
export interface DateFilterProps {
value: string;
@ -31,7 +32,7 @@ export function DateFilter({
}: DateFilterProps) {
const { formatMessage, labels } = useMessages();
const [showPicker, setShowPicker] = useState(false);
const { locale } = useLocale();
const intl = useIntl();
const options = [
{ label: formatMessage(labels.today), value: '0day' },
@ -101,11 +102,11 @@ export function DateFilter({
const { unit } = parseDateValue(value) || {};
if (offset && unit === 'year') {
return formatDate(startDate, 'yyyy', locale);
return intl.formatDate(startDate, { year: 'numeric' });
}
if (offset && unit === 'month') {
return formatDate(startDate, 'MMMM yyyy', locale);
return intl.formatDate(startDate, { year: 'numeric', month: 'long' });
}
if (value.startsWith('range') || offset) {
@ -156,7 +157,7 @@ export function DateFilter({
}
const CustomRange = ({ startDate, endDate, unit, onClick }) => {
const { locale } = useLocale();
const intl = useIntl();
const monthFormat = unit === 'month';
@ -173,11 +174,12 @@ const CustomRange = ({ startDate, endDate, unit, onClick }) => {
</Icon>
<Text>
{monthFormat ? (
<>{formatDate(startDate, 'MMMM yyyy', locale)}</>
<>{intl.formatDate(startDate, { year: 'numeric', month: 'long' })}</>
) : (
<>
{formatDate(startDate, 'd LLL y', locale)}
{!isSameDay(startDate, endDate) && `${formatDate(endDate, 'd LLL y', locale)}`}
{intl.formatDate(startDate, { dateStyle: 'medium' })}
{!isSameDay(startDate, endDate) &&
`${intl.formatDate(endDate, { dateStyle: 'medium' })}`}
</>
)}
</Text>

View file

@ -11,13 +11,14 @@ import {
import { startOfMonth, endOfMonth } from 'date-fns';
import Icons from 'components/icons';
import { useLocale } from 'components/hooks';
import { formatDate } from 'lib/date';
import styles from './MonthSelect.module.css';
import { useIntl } from 'react-intl';
export function MonthSelect({ date = new Date(), onChange }) {
const { locale, dateLocale } = useLocale();
const month = formatDate(date, 'MMMM', locale);
const year = date.getFullYear();
const { dateLocale } = useLocale();
const intl = useIntl();
const month = intl.formatDate(date, { month: 'numeric' });
const year = intl.formatDate(date, { year: 'numeric' });
const ref = useRef();
const handleChange = (close: () => void, date: Date) => {

View file

@ -1,9 +1,10 @@
import { useMemo } from 'react';
import { colord } from 'colord';
import BarChart from 'components/charts/BarChart';
import { useLocale, useDateRange, useWebsiteEventsSeries } from 'components/hooks';
import { useDateRange, useWebsiteEventsSeries } from 'components/hooks';
import { CHART_COLORS } from 'lib/constants';
import { renderDateLabels } from 'lib/charts';
import { useIntl } from 'react-intl';
export interface EventsChartProps {
websiteId: string;
@ -14,8 +15,8 @@ export function EventsChart({ websiteId, className }: EventsChartProps) {
const {
dateRange: { startDate, endDate, unit },
} = useDateRange(websiteId);
const { locale } = useLocale();
const { data, isLoading } = useWebsiteEventsSeries(websiteId);
const intl = useIntl();
const chartData = useMemo(() => {
if (!data) return [];
@ -51,7 +52,7 @@ export function EventsChart({ websiteId, className }: EventsChartProps) {
data={chartData}
unit={unit}
stacked={true}
renderXLabel={renderDateLabels(unit, locale)}
renderXLabel={renderDateLabels(intl, unit)}
isLoading={isLoading}
/>
);

View file

@ -2,6 +2,7 @@ import { useMemo } from 'react';
import BarChart, { BarChartProps } from 'components/charts/BarChart';
import { useLocale, useTheme, useMessages } from 'components/hooks';
import { renderDateLabels } from 'lib/charts';
import { useIntl } from 'react-intl';
export interface PagepageviewsChartProps extends BarChartProps {
data: {
@ -20,6 +21,7 @@ export function PagepageviewsChart({ data, unit, isLoading, ...props }: Pagepage
const { formatMessage, labels } = useMessages();
const { colors } = useTheme();
const { locale } = useLocale();
const intl = useIntl();
const chartData = useMemo(() => {
if (!data) {
@ -74,7 +76,7 @@ export function PagepageviewsChart({ data, unit, isLoading, ...props }: Pagepage
data={chartData}
unit={unit}
isLoading={isLoading}
renderXLabel={renderDateLabels(unit, locale)}
renderXLabel={renderDateLabels(intl, unit)}
/>
);
}

View file

@ -1,25 +1,25 @@
import { formatDate } from 'lib/date';
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(unit: string, locale: string) {
export function renderDateLabels(intl: IntlShape, unit: string) {
return (label: string, index: number, values: any[]) => {
const d = new Date(values[index].value);
switch (unit) {
case 'minute':
return formatDate(d, 'h:mm', locale);
return intl.formatDate(d, { timeStyle: 'short' });
case 'hour':
return formatDate(d, 'p', locale);
return intl.formatDate(d, { timeStyle: 'short' });
case 'day':
return formatDate(d, 'MMM d', locale);
return intl.formatDate(d, { month: 'short', day: 'numeric' });
case 'month':
return formatDate(d, 'MMM', locale);
return intl.formatDate(d, { month: 'short' });
case 'year':
return formatDate(d, 'YYY', locale);
return intl.formatDate(d, { year: 'numeric' });
default:
return label;
}

View file

@ -27,7 +27,6 @@ import {
differenceInCalendarWeeks,
differenceInCalendarMonths,
differenceInCalendarYears,
format,
max,
min,
isDate,
@ -288,16 +287,6 @@ export function getDateArray(data: any[], startDate: Date, endDate: Date, unit:
return arr;
}
export function formatDate(date: string | number | Date, str: string, locale = 'en-US') {
return format(
typeof date === 'string' ? new Date(date) : date,
CUSTOM_FORMATS?.[locale]?.[str] || str,
{
locale: getDateLocale(locale),
},
);
}
export function maxDate(...args: Date[]) {
return max(args.filter(n => isDate(n)));
}