@qite/tide-booking-component
Version:
React Booking wizard & Booking product component for Tide
302 lines (266 loc) • 8.32 kB
text/typescript
import { arSA, da, de, enGB, es, fr, is, it, nl, nb, pl, pt, sv, ja } from 'date-fns/locale';
import { format as formatDateFns } from 'date-fns';
export const languages = [
'ar-SA',
'da-DK',
'de-DE',
'en-GB',
'es-ES',
'fr-BE',
'fr-FR',
'is-IS',
'it-IT',
'nl-BE',
'nl-NL',
'no-NO',
'pl-PL',
'pt-PT',
'sv-SE',
'ja-JP'
];
export const defaultLanguage = 'nl-BE';
export const formatPrice = (price: number, currencyCode: string, locale: string = 'nl-BE') => {
const priceFormat = Intl.NumberFormat(locale, {
style: 'currency',
currency: currencyCode ? currencyCode : 'EUR',
minimumFractionDigits: 2,
useGrouping: true
});
return priceFormat.format(price);
};
import arJson from '../translations/ar-SA.json';
import daJson from '../translations/da-DK.json';
import deJson from '../translations/de-DE.json';
import enJson from '../translations/en-GB.json';
import esJson from '../translations/es-ES.json';
import frBeJson from '../translations/fr-BE.json';
import frFrJson from '../translations/fr-FR.json';
import isJson from '../translations/is-IS.json';
import itJson from '../translations/it-IT.json';
import nlBeJson from '../translations/nl-BE.json';
import nlNlJson from '../translations/nl-NL.json';
import noJson from '../translations/no-NO.json';
import plJson from '../translations/pl-PL.json';
import ptJson from '../translations/pt-PT.json';
import svJson from '../translations/sv-SE.json';
import jaJson from '../translations/ja-JP.json';
import { DateStruct } from '@qite/tide-client';
import { DepartureRange } from '../types';
import { SortByType } from '../../search-results/types';
export const getTranslations = (language: string) => {
switch (language) {
case 'ar-SA':
return arJson;
case 'da-DK':
return daJson;
case 'de-DE':
return deJson;
case 'en-GB':
return enJson;
case 'es-ES':
return esJson;
case 'fr-BE':
return frBeJson;
case 'fr-FR':
return frFrJson;
case 'is-IS':
return isJson;
case 'it-IT':
return itJson;
case 'nl-BE':
return nlBeJson;
case 'nl-NL':
return nlNlJson;
case 'no-NO':
return noJson;
case 'pl-PL':
return plJson;
case 'pt-PT':
return ptJson;
case 'sv-SE':
return svJson;
case 'ja-JP':
return jaJson;
default:
throw new Error(`The language '${language}' is not yet supported.`);
}
};
export const locales = {
'ar-SA': arSA,
'da-DK': da,
'de-DE': de,
'en-GB': enGB,
'es-ES': es,
'fr-BE': fr,
'fr-FR': fr,
'is-IS': is,
'it-IT': it,
'nl-BE': nl,
'nl-NL': nl,
'no-NO': nb,
'pl-PL': pl,
'pt-PT': pt,
'sv-SE': sv,
'ja-JP': ja
};
export function getLocale(code: string) {
switch (code) {
case 'ar-SA':
return locales[code];
case 'da-DK':
return locales[code];
case 'de-DE':
return locales[code];
case 'en-GB':
return locales[code];
case 'es-ES':
return locales[code];
case 'fr-BE':
return locales[code];
case 'fr-FR':
return locales[code];
case 'is-IS':
return locales[code];
case 'it-IT':
return locales[code];
case 'nl-BE':
return locales[code];
case 'nl-NL':
return locales[code];
case 'no-NO':
return locales[code];
case 'pl-PL':
return locales[code];
case 'pt-PT':
return locales[code];
case 'sv-SE':
return locales[code];
case 'ja-JP':
return locales[code];
default:
return locales['nl-BE'];
}
}
export const getPriceDifferenceText = (price: number, currencyCode: string) => {
return price > 0 ? `+ ${formatPrice(Math.abs(price), currencyCode)}` : `- ${formatPrice(Math.abs(price), currencyCode)}`;
};
export function format(text: string, args: any[]) {
return text.replace(/{([0-9]+)}/g, function (match, index) {
return typeof args[index] == 'undefined' ? match : args[index];
});
}
export const formatTime = (date: Date) =>
new Intl.DateTimeFormat('nl-BE', {
hour: '2-digit',
minute: '2-digit',
hour12: false
}).format(new Date(date));
export const formatDate = (date: Date) =>
new Intl.DateTimeFormat('nl-BE', {
weekday: 'short',
day: '2-digit',
month: 'short',
year: '2-digit'
}).format(new Date(date));
export const dateToDateStruct = (date: Date | undefined): DateStruct => {
if (date === undefined) {
return { year: 0, month: 0, day: 0 };
}
return {
year: date.getFullYear(),
month: date.getMonth() + 1, // Months are 0-based in JS
day: date.getDate()
};
};
export const timeFromDateTime = (dateTime: Date | undefined): string => {
if (!dateTime) {
return '';
}
const value = dateTime as Date | string;
if (typeof value === 'string') {
return value.match(/T(\d{2}:\d{2})/)?.[1] ?? '';
}
return `${value.getHours().toString().padStart(2, '0')}:${value.getMinutes().toString().padStart(2, '0')}`;
};
export const longFormatDate = (dateTime: Date | undefined, language: string): string => {
if (!dateTime) {
return '';
}
const locale = getLocale(language);
const formattedDate = formatDateFns(new Date(dateTime), 'eee dd MMM yy', { locale });
return formattedDate;
};
export const durationTicksInHoursString = (durationInTicks: number): string => {
const totalMinutes = Math.floor(durationInTicks / 10_000 / 1000 / 60);
return minutesToHoursString(totalMinutes);
};
export const durationInTicksInMinutes = (durationInTicks: number): number => {
const totalMinutes = Math.floor(durationInTicks / 10_000 / 1000 / 60);
return totalMinutes;
};
export const minutesToHoursString = (totalMinutes: number): string => {
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
const paddedMinutes = minutes.toString().padStart(2, '0');
return `${hours.toString()} h ${paddedMinutes}`;
};
export const rangeFromDateTimeInMinutes = (dateTime: Date | undefined): DepartureRange => {
if (!dateTime) {
return DepartureRange.Morning;
}
const date = new Date(dateTime);
const hours = date.getHours();
const minutes = hours * 60 + date.getMinutes();
switch (true) {
case minutes >= 300 && minutes < 720:
return DepartureRange.Morning;
case minutes >= 720 && minutes < 1080:
return DepartureRange.Afternoon;
case minutes >= 1080 && minutes < 1440:
return DepartureRange.Evening;
default:
return DepartureRange.Night;
}
};
export const calculateNights = (fromDate: Date, toDate: Date): number => {
const from = new Date(fromDate);
const to = new Date(toDate);
// Normalize to midnight to avoid time issues
from.setHours(0, 0, 0, 0);
to.setHours(0, 0, 0, 0);
const diffTime = to.getTime() - from.getTime();
return Math.round(diffTime / (1000 * 60 * 60 * 24));
};
export const calculateDays = (fromDate: Date, toDate: Date): number => {
return calculateNights(fromDate, toDate) + 1;
};
export const getSortingName = (translations: any, sortByType: SortByType): string => {
switch (sortByType.label) {
case 'price':
return sortByType.direction === 'asc' ? translations.SRP.PRICE_ASC : translations.SRP.PRICE_DESC;
case 'departureTime':
return sortByType.direction === 'asc' ? translations.SRP.DEPARTURE_TIME_ASC : translations.SRP.DEPARTURE_TIME_DESC;
case 'durationInTicks':
return sortByType.direction === 'asc' ? translations.SRP.DURATION_ASC : translations.SRP.DURATION_DESC;
default:
return sortByType.label;
}
};
export const findSortByType = (sortByTypes: SortByType[], sortKey: string, direction: string) => {
return sortByTypes.find((s) => s.label === sortKey && s.direction === direction) || sortByTypes[0];
};
export const getDatesBetween = (fromDate: string, toDate: string): Date[] => {
const dates: Date[] = [];
const current = new Date(fromDate);
const end = new Date(toDate);
while (current < end) {
dates.push(new Date(current));
current.setUTCDate(current.getUTCDate() + 1);
}
return dates;
};
export const getDateOnlyTime = (date?: string | Date | null) => {
if (!date) return 0;
const parsedDate = new Date(date);
return new Date(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()).getTime();
};