@qite/tide-booking-component
Version:
React Booking wizard & Booking product component for Tide
154 lines (123 loc) • 5 kB
text/typescript
import {
PackagingEntryLine,
PackagingEntryPax,
BookingPackagePax,
PackagingEntry,
BookingPackageRequestRoom,
PackagingRoom,
PackagingTraveller
} from '@qite/tide-client';
import { range } from 'lodash';
export const GROUP_TOUR_SERVICE_TYPE = 1;
export const ACCOMMODATION_SERVICE_TYPE = 3;
export const EXCURSION_SERVICE_TYPE = 4;
export const FLIGHT_SERVICE_TYPE = 7;
export const toDateOnlyString = (value: string | Date): string => {
const date = value instanceof Date ? value : new Date(value);
return date.toISOString().split('T')[0];
};
const getAgeAtReferenceDate = (dateOfBirth: string | Date, referenceDate: string | Date): number => {
const dob = dateOfBirth instanceof Date ? dateOfBirth : new Date(dateOfBirth);
const ref = referenceDate instanceof Date ? referenceDate : new Date(referenceDate);
let age = ref.getFullYear() - dob.getFullYear();
const monthDiff = ref.getMonth() - dob.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && ref.getDate() < dob.getDate())) {
age--;
}
return age;
};
export const getPrimaryAccommodationLine = (lines: PackagingEntryLine[]): PackagingEntryLine | undefined => {
return [...lines]
.filter((line) => line.serviceType === ACCOMMODATION_SERVICE_TYPE)
.sort((a, b) => new Date(a.from).getTime() - new Date(b.from).getTime())[0];
};
const getFlightLines = (lines: PackagingEntryLine[]): PackagingEntryLine[] => {
return [...lines].filter((line) => line.serviceType === FLIGHT_SERVICE_TYPE).sort((a, b) => new Date(a.from).getTime() - new Date(b.from).getTime());
};
export const getDepartureAirportFromEntry = (lines: PackagingEntryLine[]): string | null => {
const firstFlight = getFlightLines(lines)[0];
const firstSegment = firstFlight?.flightInformation?.flightLines?.[0];
return firstSegment?.departureAirportCode ?? null;
};
export const getDestinationAirportFromEntry = (lines: PackagingEntryLine[]): string | null => {
const outboundFlight = getFlightLines(lines)[0];
const flightSegments = outboundFlight?.flightInformation?.flightLines;
if (!flightSegments?.length) return null;
return flightSegments[flightSegments.length - 1]?.arrivalAirportCode ?? null;
};
const mapPackagingPaxToBookingPax = (pax: PackagingEntryPax | undefined, fallbackId: number, referenceDate: string): BookingPackagePax => ({
id: pax?.id ?? fallbackId,
guid: pax?.id?.toString() ?? fallbackId.toString(),
firstName: pax?.firstName ?? '',
lastName: pax?.lastName ?? '',
dateOfBirth: pax?.dateOfBirth ?? undefined,
age: pax?.dateOfBirth ? getAgeAtReferenceDate(pax.dateOfBirth, referenceDate) : undefined,
isMainBooker: pax?.isMainBooker,
email: ''
});
export const getRequestRoomsFromPackagingEntry = (entry: PackagingEntry): BookingPackageRequestRoom[] => {
const accommodationLines = (entry.lines ?? []).filter((line) => line.serviceType === ACCOMMODATION_SERVICE_TYPE && line.pax?.length > 0);
const paxById = new Map((entry.pax ?? []).map((p) => [p.id, p]));
if (!accommodationLines.length) {
return [
{
index: 0,
pax: (entry.pax ?? []).map((p) => mapPackagingPaxToBookingPax(p, p.id, new Date().toISOString()))
}
];
}
const roomGroups: BookingPackagePax[][] = [];
accommodationLines.forEach((line) => {
const groupedByRoom = new Map<number, BookingPackagePax[]>();
line.pax.forEach((linePax) => {
const roomIndexWithinLine = Number(linePax.room ?? 0);
const paxId = Number(linePax.paxId);
const pax = mapPackagingPaxToBookingPax(paxById.get(paxId), paxId, line.from);
if (!groupedByRoom.has(roomIndexWithinLine)) {
groupedByRoom.set(roomIndexWithinLine, []);
}
groupedByRoom.get(roomIndexWithinLine)!.push(pax);
});
const sortedGroups = Array.from(groupedByRoom.entries())
.sort(([a], [b]) => a - b)
.map(([, pax]) => pax);
roomGroups.push(...sortedGroups);
});
if (!roomGroups.length) {
return [
{
index: 0,
pax: (entry.pax ?? []).map((p) => mapPackagingPaxToBookingPax(p, p.id, accommodationLines[0].from))
}
];
}
return roomGroups.map((pax, index) => ({
index,
pax
}));
};
export const parseHotelId = (line?: PackagingEntryLine): number | null => {
if (!line?.productCode) return null;
const parsed = Number(line.productCode);
return Number.isNaN(parsed) ? null : parsed;
};
export const getPackagingRequestRoomsFromBookingRooms = (rooms: BookingPackageRequestRoom[] | null) => {
if (!rooms?.length) {
const room = { index: 0, travellers: [] } as PackagingRoom;
range(0, 2).forEach(() => {
room.travellers.push({
age: 30
} as PackagingTraveller);
});
return [room];
}
return rooms.map((x, i) => {
const room = { index: x.index ?? i, travellers: [] } as PackagingRoom;
x.pax.forEach((p) => {
room.travellers.push({
age: p.age ?? 30
} as PackagingTraveller);
});
return room;
});
};