Skip to content

Commit bd6b8bd

Browse files
YoranSysUbuntudaveearley
authored
Feature: Enhance date formatting with user locale support (#782)
Co-authored-by: Ubuntu <[email protected]> Co-authored-by: Dave Earley <[email protected]>
1 parent 037afe2 commit bd6b8bd

File tree

13 files changed

+313
-74
lines changed

13 files changed

+313
-74
lines changed

frontend/src/components/common/EventCard/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {showError, showSuccess} from "../../../utilites/notifications.tsx";
2727
import {useUpdateEventStatus} from "../../../mutations/useUpdateEventStatus.ts";
2828
import {formatCurrency} from "../../../utilites/currency.ts";
2929
import {formatNumber} from "../../../utilites/helpers.ts";
30-
import {formatDate} from "../../../utilites/dates.ts";
30+
import {formatDateWithLocale} from "../../../utilites/dates.ts";
3131

3232
const placeholderEmojis = ['🎉', '🎪', '🎸', '🎨', '🌟', '🎭', '🎯', '🎮', '🎲', '🎳'];
3333

@@ -137,15 +137,15 @@ export function EventCard({event}: EventCardProps) {
137137
<div className={classes.dateTime}>
138138
<div className={classes.dateBox}>
139139
<span
140-
className={classes.month}>{formatDate(event.start_date, 'MMM', event.timezone)}</span>
141-
<span className={classes.day}>{formatDate(event.start_date, 'D', event.timezone)}</span>
140+
className={classes.month}>{formatDateWithLocale(event.start_date, 'monthShort', event.timezone)}</span>
141+
<span className={classes.day}>{formatDateWithLocale(event.start_date, 'dayOfMonth', event.timezone)}</span>
142142
</div>
143143
<div className={classes.timeInfo}>
144144
<span
145-
className={classes.time}>{formatDate(event.start_date, 'h:mm A', event.timezone)}</span>
145+
className={classes.time}>{formatDateWithLocale(event.start_date, 'timeOnly', event.timezone)}</span>
146146
{event.end_date && (
147147
<span
148-
className={classes.endTime}>- {formatDate(event.end_date, 'h:mm A', event.timezone)}</span>
148+
className={classes.endTime}>- {formatDateWithLocale(event.end_date, 'timeOnly', event.timezone)}</span>
149149
)}
150150
</div>
151151
</div>
Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
1-
import {Event} from "../../../types.ts";
2-
import {formatDate} from "../../../utilites/dates.ts";
1+
import { Event } from "../../../types.ts";
2+
import { formatDateWithLocale } from "../../../utilites/dates.ts";
33

44
interface EventDateRangeProps {
5-
event: Event
5+
event: Event;
66
}
77

8-
export const EventDateRange = ({event}: EventDateRangeProps) => {
9-
const startDateFormatted = formatDate(event.start_date, "ddd, MMM D, YYYY h:mm A", event.timezone);
10-
const endDateFormatted = event.end_date ? formatDate(event.end_date, "ddd, MMM D, YYYY h:mm A", event.timezone) : null;
11-
const sameDayFormatted = formatDate(event.start_date, "dddd, MMMM D", event.timezone);
12-
const startTimeFormatted = formatDate(event.start_date, "h:mm A", event.timezone);
13-
const endTimeFormatted = event.end_date ? formatDate(event.end_date, "h:mm A", event.timezone) : null;
14-
const timezone = formatDate(event.start_date, "z", event.timezone);
15-
8+
export const EventDateRange = ({ event }: EventDateRangeProps) => {
169
const isSameDay = event.end_date && event.start_date.substring(0, 10) === event.end_date.substring(0, 10);
10+
const timezone = formatDateWithLocale(event.start_date, "timezone", event.timezone);
11+
12+
if (isSameDay) {
13+
const dayFormatted = formatDateWithLocale(event.start_date, "dayName", event.timezone);
14+
const startTime = formatDateWithLocale(event.start_date, "timeOnly", event.timezone);
15+
const endTime = formatDateWithLocale(event.end_date!, "timeOnly", event.timezone);
16+
17+
return (
18+
<span>
19+
{dayFormatted} · {startTime} - {endTime} {timezone}
20+
</span>
21+
);
22+
}
23+
24+
const startDateFormatted = formatDateWithLocale(event.start_date, "fullDateTime", event.timezone);
25+
const endDateFormatted = event.end_date
26+
? formatDateWithLocale(event.end_date, "fullDateTime", event.timezone)
27+
: null;
1728

1829
return (
19-
<>
20-
{isSameDay ? (
21-
<span>
22-
{sameDayFormatted} · {startTimeFormatted} - {endTimeFormatted} {timezone}
23-
</span>
24-
) : (
25-
<span>
26-
{startDateFormatted}
27-
{endDateFormatted && ` - ${endDateFormatted}`} {timezone}
28-
</span>
29-
)}
30-
</>
30+
<span>
31+
{startDateFormatted}
32+
{endDateFormatted && ` - ${endDateFormatted}`} {timezone}
33+
</span>
3134
);
3235
}

frontend/src/components/layouts/OrganizerHomepage/EventCard/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import {Link} from "react-router";
33
import {Event} from "../../../../types.ts";
44
import classes from './EventCard.module.scss';
5-
import {formatDate} from "../../../../utilites/dates.ts";
5+
import {formatDateWithLocale} from "../../../../utilites/dates.ts";
66
import {t} from "@lingui/macro";
77
import {isLightColor} from "@mantine/core";
88
import {formatCurrency} from "../../../../utilites/currency.ts";
@@ -26,15 +26,15 @@ export const EventCard: React.FC<EventCardProps> = ({event, primaryColor = '#8b5
2626
const placeholderEmoji = placeholderEmojis[emojiIndex];
2727

2828
// Format dates using the event's timezone
29-
const startMonth = formatDate(event.start_date, "MMM", event.timezone);
30-
const startDay = formatDate(event.start_date, "D", event.timezone);
31-
const startTime = formatDate(event.start_date, "h:mm A", event.timezone);
32-
const endTime = event.end_date ? formatDate(event.end_date, "h:mm A", event.timezone) : null;
33-
const prettyTimezone = formatDate(event.start_date, "z", event.timezone);
29+
const startMonth = formatDateWithLocale(event.start_date, "monthShort", event.timezone);
30+
const startDay = formatDateWithLocale(event.start_date, "dayOfMonth", event.timezone);
31+
const startTime = formatDateWithLocale(event.start_date, "timeOnly", event.timezone);
32+
const endTime = event.end_date ? formatDateWithLocale(event.end_date, "timeOnly", event.timezone) : null;
33+
const prettyTimezone = formatDateWithLocale(event.start_date, "timezone", event.timezone);
3434

3535
const isSameDay = event.end_date && event.start_date.substring(0, 10) === event.end_date.substring(0, 10);
36-
const endMonth = event.end_date ? formatDate(event.end_date, "MMM", event.timezone) : null;
37-
const endDay = event.end_date ? formatDate(event.end_date, "D", event.timezone) : null;
36+
const endMonth = event.end_date ? formatDateWithLocale(event.end_date, "monthShort", event.timezone) : null;
37+
const endDay = event.end_date ? formatDateWithLocale(event.end_date, "dayOfMonth", event.timezone) : null;
3838

3939
const coverImage = event.images?.find(img => img.type === 'EVENT_COVER');
4040
const location = event?.settings?.location_details?.city || event?.settings?.location_details?.venue_name;

frontend/src/components/routes/event/EventDashboard/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {Card} from "../../../common/Card";
1010
import classes from "./EventDashboard.module.scss";
1111
import {useGetEventStats} from "../../../../queries/useGetEventStats.ts";
1212
import {formatCurrency} from "../../../../utilites/currency.ts";
13-
import {formatDate} from "../../../../utilites/dates.ts";
13+
import {formatDateWithLocale} from "../../../../utilites/dates.ts";
1414
import {Button, Skeleton} from "@mantine/core";
1515
import {useMediaQuery} from "@mantine/hooks";
1616
import {IconAlertCircle, IconX} from "@tabler/icons-react";
@@ -87,7 +87,7 @@ export const EventDashboard = () => {
8787
}
8888

8989
const dateRange = (eventStats && event)
90-
? `${formatDate(eventStats.start_date, 'MMM DD', event?.timezone)} - ${formatDate(eventStats.end_date, 'MMM DD', event?.timezone)}`
90+
? `${formatDateWithLocale(eventStats.start_date, 'chartDate', event?.timezone)} - ${formatDateWithLocale(eventStats.end_date, 'chartDate', event?.timezone)}`
9191
: '';
9292

9393
const shouldShowChecklist = (isChecklistVisible && event && accountIsFetched && account?.is_saas_mode_enabled) && (
@@ -255,7 +255,7 @@ export const EventDashboard = () => {
255255
<AreaChart
256256
h={300}
257257
data={eventStats?.daily_stats.map(stat => ({
258-
date: formatDate(stat.date, 'MMM DD', event.timezone),
258+
date: formatDateWithLocale(stat.date, 'chartDate', event.timezone),
259259
orders_created: stat.orders_created,
260260
products_sold: stat.products_sold,
261261
attendees_registered: stat.attendees_registered,
@@ -289,7 +289,7 @@ export const EventDashboard = () => {
289289
h={300}
290290
data={eventStats?.daily_stats.map(stat => {
291291
return ({
292-
date: formatDate(stat.date, 'MMM DD', event.timezone),
292+
date: formatDateWithLocale(stat.date, 'chartDate', event.timezone),
293293
total_fees: stat.total_fees,
294294
total_sales_gross: stat.total_sales_gross,
295295
total_tax: stat.total_tax,

frontend/src/components/routes/event/Reports/DailySalesReport/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {useParams} from "react-router";
22
import {useGetEvent} from "../../../../../queries/useGetEvent.ts";
33
import {formatCurrency} from "../../../../../utilites/currency.ts";
4-
import {formatDate} from "../../../../../utilites/dates.ts";
4+
import {formatDateWithLocale} from "../../../../../utilites/dates.ts";
55
import ReportTable from "../../../../common/ReportTable";
66

77
export const DailySalesReport = () => {
@@ -18,7 +18,7 @@ export const DailySalesReport = () => {
1818
key: 'date' as const,
1919
label: 'Date',
2020
sortable: true,
21-
render: (value: string) => formatDate(value, 'MMM D, YYYY', event?.timezone)
21+
render: (value: string) => formatDateWithLocale(value, 'shortDate', event?.timezone)
2222
},
2323
{
2424
key: 'sales_total_gross' as const,

frontend/src/components/routes/event/Reports/PromoCodesReport/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {useGetEvent} from "../../../../../queries/useGetEvent.ts";
33
import {formatCurrency} from "../../../../../utilites/currency.ts";
44
import ReportTable from "../../../../common/ReportTable";
55
import {t} from "@lingui/macro";
6-
import {formatDate} from "../../../../../utilites/dates.ts";
6+
import {formatDateWithLocale} from "../../../../../utilites/dates.ts";
77

88
const PromoCodesReport = () => {
99
const {eventId} = useParams();
@@ -63,13 +63,13 @@ const PromoCodesReport = () => {
6363
key: 'first_used_at' as const,
6464
label: t`First Used`,
6565
sortable: true,
66-
render: (value: string) => value ? formatDate(value, 'MMM D, YYYY', event.timezone) : '-'
66+
render: (value: string) => value ? formatDateWithLocale(value, 'shortDate', event.timezone) : '-'
6767
},
6868
{
6969
key: 'last_used_at' as const,
7070
label: t`Last Used`,
7171
sortable: true,
72-
render: (value: string) => value ? formatDate(value, 'MMM D, YYYY', event.timezone) : '-'
72+
render: (value: string) => value ? formatDateWithLocale(value, 'shortDate', event.timezone) : '-'
7373
},
7474
{
7575
key: 'max_allowed_usages' as const,

frontend/src/components/routes/organizer/Reports/CheckInSummaryReport/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Link, useParams} from "react-router";
22
import {useGetOrganizer} from "../../../../../queries/useGetOrganizer.ts";
3-
import {formatDate} from "../../../../../utilites/dates.ts";
3+
import {formatDateWithLocale} from "../../../../../utilites/dates.ts";
44
import OrganizerReportTable from "../../../../common/OrganizerReportTable";
55
import {t} from "@lingui/macro";
66

@@ -28,7 +28,7 @@ const CheckInSummaryReport = () => {
2828
key: 'start_date' as const,
2929
label: t`Event Date`,
3030
sortable: true,
31-
render: (value: string) => value ? formatDate(value, 'MMM D, YYYY', organizer?.timezone) : '-'
31+
render: (value: string) => value ? formatDateWithLocale(value, 'shortDate', organizer?.timezone || 'UTC') : '-'
3232
},
3333
{
3434
key: 'total_attendees' as const,

frontend/src/components/routes/organizer/Reports/EventsPerformanceReport/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Link, useParams} from "react-router";
22
import {useGetOrganizer} from "../../../../../queries/useGetOrganizer.ts";
33
import {useGetOrganizerStats} from "../../../../../queries/useGetOrganizerStats.ts";
44
import {formatCurrency} from "../../../../../utilites/currency.ts";
5-
import {formatDate} from "../../../../../utilites/dates.ts";
5+
import {formatDateWithLocale} from "../../../../../utilites/dates.ts";
66
import OrganizerReportTable from "../../../../common/OrganizerReportTable";
77
import {t} from "@lingui/macro";
88
import {Badge} from "@mantine/core";
@@ -55,7 +55,7 @@ const EventsPerformanceReport = () => {
5555
key: 'start_date' as const,
5656
label: t`Date`,
5757
sortable: true,
58-
render: (value: string) => value ? formatDate(value, 'MMM D, YYYY', organizer?.timezone) : '-'
58+
render: (value: string) => value ? formatDateWithLocale(value, 'shortDate', organizer?.timezone || 'UTC') : '-'
5959
},
6060
{
6161
key: 'event_state' as const,

frontend/src/components/routes/organizer/Reports/RevenueSummaryReport/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {useParams} from "react-router";
22
import {useGetOrganizer} from "../../../../../queries/useGetOrganizer.ts";
33
import {useGetOrganizerStats} from "../../../../../queries/useGetOrganizerStats.ts";
44
import {formatCurrency} from "../../../../../utilites/currency.ts";
5-
import {formatDate} from "../../../../../utilites/dates.ts";
5+
import {formatDateWithLocale} from "../../../../../utilites/dates.ts";
66
import OrganizerReportTable from "../../../../common/OrganizerReportTable";
77
import {t} from "@lingui/macro";
88

@@ -23,7 +23,7 @@ const RevenueSummaryReport = () => {
2323
key: 'date' as const,
2424
label: t`Date`,
2525
sortable: true,
26-
render: (value: string) => formatDate(value, 'MMM D, YYYY', organizer?.timezone)
26+
render: (value: string) => formatDateWithLocale(value, 'shortDate', organizer?.timezone || 'UTC')
2727
},
2828
{
2929
key: 'gross_sales' as const,

frontend/src/components/routes/profile/ManageProfile/index.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Card} from "../../../common/Card";
22
import {useForm, UseFormReturnType} from "@mantine/form";
33
import {useGetMe} from "../../../../queries/useGetMe.ts";
4-
import {Alert, Button, PasswordInput, Select, Tabs, TextInput} from "@mantine/core";
4+
import {Alert, Button, NativeSelect, PasswordInput, Select, Tabs, TextInput} from "@mantine/core";
55
import classes from "./ManageProfile.module.scss";
66
import {useEffect, useState} from "react";
77
import {IconInfoCircle, IconPassword, IconUser} from "@tabler/icons-react";
@@ -13,7 +13,12 @@ import {useCancelEmailChange} from "../../../../mutations/useCancelEmailChange.t
1313
import {useFormErrorResponseHandler} from "../../../../hooks/useFormErrorResponseHandler.tsx";
1414
import {t, Trans} from "@lingui/macro";
1515
import {useResendEmailConfirmation} from "../../../../mutations/useResendEmailConfirmation.ts";
16-
import {getLocaleName, localeToFlagEmojiMap, localeToNameMap, SupportedLocales} from "../../../../locales.ts";
16+
import {localeToFlagEmojiMap, localeToNameMap, SupportedLocales} from "../../../../locales.ts";
17+
18+
const localeSelectData = Object.keys(localeToNameMap).map(locale => ({
19+
value: locale,
20+
label: `${localeToFlagEmojiMap[locale as SupportedLocales]} ${localeToNameMap[locale as SupportedLocales]}`,
21+
}));
1722

1823
export const ManageProfile = () => {
1924
const {data: me, isFetching} = useGetMe();
@@ -162,15 +167,12 @@ export const ManageProfile = () => {
162167
placeholder={t`UTC`}
163168
/>
164169

165-
<Select
170+
<NativeSelect
166171
required
167-
data={Object.keys(localeToNameMap).map(locale => ({
168-
value: locale,
169-
label: localeToFlagEmojiMap[locale as SupportedLocales] + ' ' + getLocaleName(locale as SupportedLocales),
170-
}))}
171-
{...profileForm.getInputProps('locale')}
172+
data={localeSelectData}
173+
value={profileForm.values.locale || ''}
174+
onChange={(e) => profileForm.setFieldValue('locale', e.target.value)}
172175
label={t`Language`}
173-
placeholder={t`English`}
174176
/>
175177

176178
<Button fullWidth loading={mutation.isPending}

0 commit comments

Comments
 (0)