Files
goumrah-api/src/modules/package/package.mapper.ts
2025-12-01 12:54:45 +07:00

185 lines
5.8 KiB
TypeScript

import type { FlightSchedule } from "@/database/entities/flight-schedule.entity";
import type { PackageDetail } from "@/database/entities/package-detail.entity";
import type { PackageItineraryDay } from "@/database/entities/package-itinerary-day.entity";
import type {
PackageItineraryWidget,
PackageItineraryWidgetHotel,
PackageItineraryWidgetInformation,
PackageItineraryWidgetTransport,
} from "@/database/entities/package-itinerary-widget.entity";
import type { PackageItinerary } from "@/database/entities/package-itinerary.entity";
import type { Package } from "@/database/entities/package.entity";
import { PackageItineraryWidgetType } from "@/database/enums/package-itinerary-widget-type.enum";
import type { FlightMapper } from "@/modules/flight/flight.mapper";
import type { FlightClassResponse } from "@/modules/flight/flight.types";
import type { HotelMapper } from "@/modules/hotel/hotel.mapper";
import type {
PackageDetailResponse,
PackageItineraryDayResponse,
PackageItineraryResponse,
PackageItineraryWidgetResponse,
PackageResponse,
} from "@/modules/package/package.types";
import type { PartnerMapper } from "@/modules/partner/partner.mapper";
import type { TransportationMapper } from "@/modules/transportation/transportation.mapper";
import * as dateFns from "date-fns";
export class PackageMapper {
public constructor(
private readonly partnerMapper: PartnerMapper,
private readonly flightMapper: FlightMapper,
private readonly hotelMapper: HotelMapper,
private readonly transportationMapper: TransportationMapper,
) {}
public mapEntityToResponse(package_: Package): PackageResponse {
return {
id: package_.id,
slug: package_.slug,
name: package_.name,
type: package_.type,
class: package_.class,
thumbnail: package_.thumbnail,
use_fast_train: package_.useFastTrain,
partner: this.partnerMapper.mapEntityToResponse(package_.partner),
created_at: package_.createdAt,
updated_at: package_.updatedAt,
};
}
private mapFlightSchedule(
flightSchedule: FlightSchedule,
): FlightClassResponse[] {
const flightClassResponses: FlightClassResponse[] = [];
let currentFlightSchedule: FlightSchedule | null = flightSchedule;
while (currentFlightSchedule !== null) {
flightClassResponses.push(
this.flightMapper.mapClassEntityToResponse(
currentFlightSchedule.flight,
),
);
currentFlightSchedule = currentFlightSchedule.next;
}
return flightClassResponses;
}
private mapItineraryWidget(
packageItineraryWidget: PackageItineraryWidget,
): PackageItineraryWidgetResponse {
switch (packageItineraryWidget.type) {
case PackageItineraryWidgetType.transport:
const transportWidget =
packageItineraryWidget as PackageItineraryWidgetTransport;
return {
type: "transport",
transportation: transportWidget.transportation,
from: transportWidget.from,
to: transportWidget.to,
};
case PackageItineraryWidgetType.hotel:
const hotelWidget =
packageItineraryWidget as PackageItineraryWidgetHotel;
return {
type: "hotel",
hotel: this.hotelMapper.mapEntityToResponse(hotelWidget.hotel),
};
case PackageItineraryWidgetType.information:
const informationWidget =
packageItineraryWidget as PackageItineraryWidgetInformation;
return {
type: "information",
description: informationWidget.description,
};
}
}
private mapItineraryDay(
packageItineraryDay: PackageItineraryDay,
nth: number,
): PackageItineraryDayResponse {
return {
nth,
title: packageItineraryDay.title,
description: packageItineraryDay.description,
widgets: packageItineraryDay.widgets
.getItems()
.map((widget) => this.mapItineraryWidget(widget)),
};
}
private mapItinerary(
packageItinerary: PackageItinerary,
nthDay: number = 1,
): PackageItineraryResponse {
const days: PackageItineraryDayResponse[] = [];
for (
let currentItineraryDay: PackageItineraryDay | null =
packageItinerary.day,
index = 0;
currentItineraryDay !== null;
currentItineraryDay = currentItineraryDay.next, index++
) {
days.push(this.mapItineraryDay(currentItineraryDay, nthDay + index));
}
return {
location: packageItinerary.location,
images: packageItinerary.images
.getItems()
.map((packageItineraryImage) => packageItineraryImage.src),
days,
};
}
public mapDetailEntityToResponse(
packageDetail: PackageDetail,
): PackageDetailResponse {
const itineraries: PackageItineraryResponse[] = [];
for (
let currentItinerary: PackageItinerary | null = packageDetail.itinerary,
nthDay = 1;
currentItinerary !== null;
currentItinerary = currentItinerary.next
) {
const itineraryResponse = this.mapItinerary(currentItinerary, nthDay);
itineraries.push(itineraryResponse);
nthDay += itineraryResponse.days.length;
}
return {
id: packageDetail.id,
package: this.mapEntityToResponse(packageDetail.package),
departure_date: dateFns.format(packageDetail.departureDate, "yyyy-MM-dd"),
tour_flights: packageDetail.tourFlight
? this.mapFlightSchedule(packageDetail.tourFlight)
: null,
outbound_flights: this.mapFlightSchedule(packageDetail.outboundFlight),
inbound_flights: this.mapFlightSchedule(packageDetail.inboundFlight),
tour_hotels: packageDetail.tourHotels.map(
this.hotelMapper.mapEntityToResponse,
),
makkah_hotel: this.hotelMapper.mapEntityToResponse(
packageDetail.makkahHotel,
),
madinah_hotel: this.hotelMapper.mapEntityToResponse(
packageDetail.madinahHotel,
),
transportation: this.transportationMapper.mapClassEntityToResponse(
packageDetail.transportation,
),
quad_price: packageDetail.quadPrice,
triple_price: packageDetail.triplePrice,
double_price: packageDetail.doublePrice,
infant_price: packageDetail.infantPrice,
itineraries,
created_at: packageDetail.createdAt,
updated_at: packageDetail.updatedAt,
};
}
}