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, }; } }