Skip to content

Commit

Permalink
bugfix: [234] Format dates on FrontEnd to fix timezone issues (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
radulescuandrew authored Jul 15, 2024
1 parent 140bcf5 commit 2bd731d
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export class MobileEventListItemPresenter {

this.location = event.location;
this.eventInterval = formatEventDate(event.startDate, event.endDate);

this.startDate = event.startDate;
this.endDate = event.endDate;

this.organizationLogo = event.organizationLogo;

this.poster = event.poster;
Expand Down Expand Up @@ -43,6 +47,19 @@ export class MobileEventListItemPresenter {
})
location: string;

@Expose()
@ApiProperty({
description: 'Start date of the event',
})
startDate: Date;

@Expose()
@ApiProperty({
description: 'End date of the event',
})
endDate: Date;

// TODO: Deprecate this, remove in the next version. Because of the BE timezone the dates are parsed wrong in the backend we do it in FE.
@Expose()
@ApiProperty({
description:
Expand Down
16 changes: 16 additions & 0 deletions backend/src/api/_mobile/event/presenters/mobile-event.presenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export class MobileEventPresenter {
this.isPublic = event.isPublic;

this.location = event.location;

this.eventInterval = formatEventDate(event.startDate, event.endDate);
this.startDate = event.startDate;
this.endDate = event.endDate;

this.organizationLogo = event.organization.logo;

this.targets = event.targets?.map(
Expand Down Expand Up @@ -64,6 +68,18 @@ export class MobileEventPresenter {
})
eventInterval: string;

@Expose()
@ApiProperty({
description: 'Start date of the event',
})
startDate: Date;

@Expose()
@ApiProperty({
description: 'End date of the event',
})
endDate: Date;

@Expose()
@ApiProperty({ description: 'The image of the Event' })
poster: string;
Expand Down
4 changes: 3 additions & 1 deletion mobile/src/common/interfaces/event-list-item.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export interface IEventListItem {
poster: string;
location: string;
isPublic: boolean;
eventInterval: string;
startDate: string;
endDate: string;
eventInterval: string; // TODO: remove after deprecation
organizationLogo?: string;
targets?: IOrganizationListItem[];
}
48 changes: 48 additions & 0 deletions mobile/src/common/utils/event.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { format, isSameDay } from 'date-fns';

/**
* Formats the start and end date of an event into a human-readable string.
*
* @param {string} startDate - The start date of the event in ISO string format.
* @param {string} [endDate] - The optional end date of the event in ISO string format.
* @returns {string} - A formatted string representing the event's date and time.
*
* @example
* const formattedDate = formatEventDate("2024-07-15T07:45:00Z");
* 👀 Returns: "15 Jul 2024, 07:45" (considering the user is in Timezone +0, if RO there will be +2/3)
*
* @example
* const formattedDateWithEnd = formatEventDate("2024-07-15T07:45:00Z", "2024-07-15T09:45:00Z");
* 👀 Returns: "15 Jul 2024, 07:45 - 09:45"
*
* @example
* const formattedDateDifferentDays = formatEventDate("2024-07-15T07:45:00Z", "2024-07-16T09:45:00Z");
* 👀 Returns: "15 Jul 2024, 07:45 - 16 Jul 2024, 09:45"
*/
export const formatEventDate = (startDate: string, endDate?: string): string => {
if (!startDate && !endDate) {
return '-';
}
// HERE
let eventDate = '';
if (!endDate) {
eventDate = `${formatDate(startDate)}, ${getHoursAndMinutes(startDate)}`;
} else {
if (isSameDay(new Date(startDate), new Date(endDate))) {
eventDate = `${formatDate(startDate)}, ${getHoursAndMinutes(
startDate,
)} - ${getHoursAndMinutes(endDate)}`;
} else {
eventDate = `${formatDate(startDate)}, ${getHoursAndMinutes(
startDate,
)} - ${formatDate(endDate)}, ${getHoursAndMinutes(endDate)}`;
}
}

return eventDate;
};

const formatDate = (value?: Date | string | null): string =>
value ? format(new Date(value), 'dd MMM yyyy') : '-';

const getHoursAndMinutes = (value: Date | string): string => format(new Date(value), 'HH:mm');
5 changes: 4 additions & 1 deletion mobile/src/components/EventItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PressableContainer from './PressableContainer';
import { mapEventType } from '../common/utils/helpers';
import ImageWithPreload from './ImageWithPreload';
import { ALLOW_FONT_SCALLING } from '../common/constants/constants';
import { formatEventDate } from '../common/utils/event.helper';

interface EventItemProps {
event: IEventListItem;
Expand Down Expand Up @@ -65,7 +66,9 @@ const EventItem = ({ event, onPress }: EventItemProps) => {
<Text allowFontScaling={ALLOW_FONT_SCALLING} style={styles.title} category="p2">
{event.name}
</Text>
<EventContentRow icon="clock">{event.eventInterval}</EventContentRow>
<EventContentRow icon="clock">
{formatEventDate(event.startDate, event.endDate)}
</EventContentRow>
<EventContentRow icon="map-pin">{event.location}</EventContentRow>
<EventContentRow icon="users">{mapEventType(event)}</EventContentRow>
</View>
Expand Down
6 changes: 5 additions & 1 deletion mobile/src/screens/Event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { AttendanceType } from '../common/enums/attendance-type.enum';
import EventSkeleton from '../components/skeleton/event-skeleton';
import ImageWithPreload from '../components/ImageWithPreload';
import { ALLOW_FONT_SCALLING } from '../common/constants/constants';
import { formatEventDate } from '../common/utils/event.helper';

const Event = ({ navigation, route }: any) => {
const { t } = useTranslation('event');
Expand Down Expand Up @@ -148,7 +149,10 @@ const Event = ({ navigation, route }: any) => {
uri={event.organizationLogo || ''}
name={event.organizationName || ''}
/>
<ReadOnlyElement label={t('date')} value={event.eventInterval} />
<ReadOnlyElement
label={t('date')}
value={formatEventDate(event.startDate, event.endDate)}
/>
<ReadOnlyElement label={t('name')} value={event.name} />
<ReadOnlyElement label={t('target')} value={mapEventType(event)} />
<ReadOnlyElement label={t('location')} value={event.location} />
Expand Down

0 comments on commit 2bd731d

Please sign in to comment.