{ "version": 3, "sources": ["src/generated/openapi/model/leadRequestCreatePolymorphicTypes.ts", "src/generated/openapi/model/publicDeparture.ts", "src/app/shared/form-dynamic-with-config/form-dynamic-with-config.component.ts", "src/app/shared/form-dynamic-with-config/form-dynamic-with-config.component.html", "src/app/shared/enquire-form-additional-info-modal/enquire-form-additional-info-modal.component.ts", "src/app/shared/enquire-form-additional-info-modal/enquire-form-additional-info-modal.component.html", "src/app/shared/enquire-form-modal/enquire-form-modal.component.ts", "src/app/shared/enquire-form-modal/enquire-form-modal.component.html", "src/app/features/trips/components/trips-trip-self-booking-departure-detail/trips-trip-self-booking-departure-detail.component.ts", "src/app/features/trips/components/trips-trip-self-booking-departure-detail/trips-trip-self-booking-departure-detail.component.html", "src/app/features/trips/components/trips-trip-self-booking/trips-trip-self-booking.component.ts", "src/app/features/trips/components/trips-trip-self-booking/trips-trip-self-booking.component.html"], "sourcesContent": ["/**\n *\n * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)\n *\n * The version of the OpenAPI document: 1.0.0\n *\n *\n * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).\n * https://openapi-generator.tech\n * Do not edit the class manually.\n */\n\nexport type LeadRequestCreatePolymorphicTypes =\n | 'DepartureLeadRequest'\n | 'CustomDepartureLeadRequest';\n\nexport const LeadRequestCreatePolymorphicTypes = {\n DepartureLeadRequest:\n 'DepartureLeadRequest' as LeadRequestCreatePolymorphicTypes,\n CustomDepartureLeadRequest:\n 'CustomDepartureLeadRequest' as LeadRequestCreatePolymorphicTypes,\n};\n", "/**\n *\n * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)\n *\n * The version of the OpenAPI document: 1.0.0\n *\n *\n * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).\n * https://openapi-generator.tech\n * Do not edit the class manually.\n */\nimport { PublicDeparturePolymorphicTypes } from './publicDeparturePolymorphicTypes';\n\nexport interface PublicDeparture {\n readonly id?: string;\n readonly code?: string;\n title: string;\n additional_text?: string | null;\n start_date: string;\n end_date: string;\n readonly price?: string;\n readonly price_currency?: string;\n readonly deposit?: string;\n readonly single_supplement?: string;\n status?: PublicDeparture.StatusEnum;\n readonly available_spots?: number;\n readonly itinerary?: string;\n readonly itinerary_id?: string;\n readonly self_booking_enabled?: boolean;\n readonly trip_id?: string;\n readonly display_status?: PublicDeparture.DisplayStatusEnum;\n resourcetype?: PublicDeparturePolymorphicTypes;\n}\nexport namespace PublicDeparture {\n export type StatusEnum =\n | 'SCHEDULED'\n | 'GUARANTEED'\n | 'SOLD_OUT'\n | 'CANCELLED'\n | 'RUNNING'\n | 'COMPLETED';\n export const StatusEnum = {\n Scheduled: 'SCHEDULED' as StatusEnum,\n Guaranteed: 'GUARANTEED' as StatusEnum,\n SoldOut: 'SOLD_OUT' as StatusEnum,\n Cancelled: 'CANCELLED' as StatusEnum,\n Running: 'RUNNING' as StatusEnum,\n Completed: 'COMPLETED' as StatusEnum,\n };\n export type DisplayStatusEnum = 'OPEN' | 'FEW_SPOTS' | 'SOLD_OUT';\n export const DisplayStatusEnum = {\n Open: 'OPEN' as DisplayStatusEnum,\n FewSpots: 'FEW_SPOTS' as DisplayStatusEnum,\n SoldOut: 'SOLD_OUT' as DisplayStatusEnum,\n };\n}\n", "import { CommonModule } from '@angular/common';\nimport {\n Component,\n computed,\n EventEmitter,\n inject,\n input,\n Output,\n} from '@angular/core';\nimport {\n FormBuilder,\n FormControl,\n ReactiveFormsModule,\n ValidatorFn,\n} from '@angular/forms';\nimport { CustomDropdownComponent } from '@shared/custom-dropdown/custom-dropdown.component';\nimport { CustomInputComponent } from '@shared/custom-input/custom-input.component';\nimport { Ng2TelInputDirective } from '@shared/ng2-tel-input/directives/ng2-tel-input.directive';\nimport { SaveButtonComponent } from '@shared/save-button/save-button.component';\n\nexport interface DynamicFormSchemaField {\n label: string;\n type: string;\n name: string;\n validators: ValidatorFn[];\n options?: {\n label: string;\n value: number | string;\n }[];\n testId?: string;\n placeholder?: string;\n}\n\n@Component({\n selector: 'app-form-dynamic-with-config',\n standalone: true,\n imports: [\n CommonModule,\n ReactiveFormsModule,\n CustomInputComponent,\n CustomDropdownComponent,\n SaveButtonComponent,\n Ng2TelInputDirective,\n ],\n templateUrl: './form-dynamic-with-config.component.html',\n styles: ``,\n})\nexport class FormDynamicWithConfigComponent {\n private formBuilder = inject(FormBuilder);\n @Output() onSubmit = new EventEmitter();\n formSchema = input.required();\n form = computed(() =>\n this.formBuilder.group(\n this.formSchema().reduce((acc, curr) => {\n return {\n ...acc,\n [curr.name]: new FormControl('', [...curr.validators]),\n };\n }, {})\n )\n );\n\n submitForm(): void {\n this.form().markAllAsTouched();\n if (this.form().valid) {\n this.onSubmit.emit(this.form().value);\n console.log('Form Submitted', this.form().value);\n // Handle form submission logic here\n } else {\n console.log('Form is invalid');\n }\n }\n}\n", "
\n @if (form()) {\n @for (formField of formSchema(); track formField.name) {\n @if (formField.type === 'dropdown') {\n \n \n } @else if (\n formField.type === 'text' || formField.type === 'email'\n ) {\n \n \n } @else if (formField.type === 'phone') {\n \n
\n
\n \n
\n @if (\n form().controls[formField.name].invalid &&\n form().controls[formField.name].dirty\n ) {\n

\n Phone number is invalid\n

\n }\n
\n } @else if (formField.type === 'textbox') {\n \n }\n }\n }\n\n \n Go\n \n\n", "import { Component, OnDestroy, OnInit, signal } from '@angular/core';\nimport { DjangoService, Routes } from '@core/services/django.service';\nimport { EventTrackerService } from '@core/services/event-tracker.service';\nimport { AnalyticsEventName } from '@core/utils/AnalyticsEvents';\nimport {\n Configurations,\n LazyPictureComponent,\n Stops,\n} from '@features/lazy-image/components/lazy-picture/lazy-picture.component';\nimport { ModalService } from '@features/modal/services/modal.service';\nimport { Itinerary, Trip } from '@generated/graphql';\nimport { LeadRequestAdditionalData } from '@generated/openapi/model/leadRequestAdditionalData';\nimport { LeadRequestCreatePolymorphicTypes as LeadRequestType } from '@generated/openapi/model/leadRequestCreatePolymorphicTypes';\nimport { PublicDeparture } from '@generated/openapi/model/publicDeparture';\nimport {\n DynamicFormSchemaField,\n FormDynamicWithConfigComponent,\n} from '@shared/form-dynamic-with-config/form-dynamic-with-config.component';\nimport { CtaButtonComponent } from '../cta-button/cta-button.component';\n\n@Component({\n selector: 'app-enquire-form-additional-info-modal',\n standalone: true,\n imports: [\n FormDynamicWithConfigComponent,\n CtaButtonComponent,\n LazyPictureComponent,\n ],\n templateUrl: './enquire-form-additional-info-modal.component.html',\n styles: ``,\n})\nexport class EnquireFormAdditionalInfoModalComponent\n implements OnInit, OnDestroy\n{\n modalData: {\n createdLeadId: string;\n trip: Trip;\n departure?: PublicDeparture;\n typeOfEnquiry: LeadRequestType;\n itinerary?: Itinerary;\n analyticsEventCompleted: AnalyticsEventName;\n analyticsEventAbandoned: AnalyticsEventName;\n analyticsEventData: {\n trip: string;\n departure?: string;\n itinerary?: string;\n };\n };\n isAdditionalInfoSubmitted = signal(false);\n readonly modalContainerstyles = [\n '!w-full !h-full !max-h-screen !rounded-none',\n ];\n readonly isModalFullscreen = true;\n featuredImageConfiguration: Configurations;\n\n formSchema: DynamicFormSchemaField[] = [\n {\n label: 'Any questions?',\n type: 'textbox',\n name: 'questions',\n validators: [],\n },\n {\n label: 'Would you like a callback?',\n name: 'phonenumber',\n type: 'phone',\n validators: [],\n },\n ];\n\n constructor(\n private djangoService: DjangoService,\n private modalService: ModalService,\n private eventTrackerService: EventTrackerService\n ) {}\n\n ngOnInit(): void {\n const trip = this.modalData.trip;\n const mobileCoverImage =\n trip?.enquireFormHorizontalImage || trip?.secondaryFeaturedImage;\n const desktopCoverImage =\n trip?.enquireFormVerticalImage || trip?.featuredImage;\n this.featuredImageConfiguration = {\n [Stops.FALLBACK]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 1,\n width: 600,\n width2x: 800,\n },\n [Stops.BASE]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 3,\n width: 600,\n width2x: 800,\n },\n [Stops.SM]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 3,\n width: 640,\n width2x: 1000,\n },\n [Stops.MD]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.LG]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.XL]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.XXL]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n };\n }\n\n submitAdditionalInfo(values) {\n this.addDetailsToLead(this.modalData.createdLeadId, {\n comment: values.questions,\n phone_number: values.phonenumber,\n }).subscribe(() => {\n this.isAdditionalInfoSubmitted.set(true);\n this.eventTrackerService.trackEvent(\n this.modalData.analyticsEventCompleted,\n this.modalData.analyticsEventData\n );\n setTimeout(() => {\n this.closeModal();\n }, 5000);\n });\n }\n\n ngOnDestroy(): void {\n if (!this.isAdditionalInfoSubmitted()) {\n this.abandonLead(this.modalData.createdLeadId).subscribe();\n }\n }\n\n closeModal() {\n this.modalService.hide();\n }\n\n addDetailsToLead(id, { comment, phone_number }) {\n const route = Routes.leads;\n const resource = `${id}/add_details`;\n return this.djangoService.drfUpdate(\n route,\n resource,\n {\n comment,\n phone_number,\n }\n );\n }\n\n abandonLead(id) {\n const route = Routes.leads;\n const resource = `${id}/abandon`;\n this.eventTrackerService.trackEvent(\n this.modalData.analyticsEventAbandoned,\n this.modalData.analyticsEventData\n );\n return this.djangoService.drfCreate(route, {}, resource);\n }\n}\n", "\n \n \n \n
\n
\n @if (isAdditionalInfoSubmitted()) {\n
\n

Enquiry sent

\n \n Thanks!\n
We will be in touch shortly\n \n Go back\n \n
\n } @else {\n
\n

Enquiry received

\n \n
\n

Any further questions?

\n \n }\n
\n
\n\n", "import { CommonModule } from '@angular/common';\nimport { Component, OnInit } from '@angular/core';\nimport { ReactiveFormsModule, Validators } from '@angular/forms';\nimport { DjangoService, Routes } from '@core/services/django.service';\nimport { EventTrackerService } from '@core/services/event-tracker.service';\nimport { AnalyticsEventName } from '@core/utils/AnalyticsEvents';\nimport {\n Configurations,\n LazyPictureComponent,\n Stops,\n} from '@features/lazy-image/components/lazy-picture/lazy-picture.component';\nimport { ModalService } from '@features/modal/services/modal.service';\nimport { Itinerary, Trip } from '@generated/graphql';\nimport { CustomDepartureLeadCreateRequest } from '@generated/openapi/model/customDepartureLeadCreateRequest';\nimport { DepartureLeadCreateRequest } from '@generated/openapi/model/departureLeadCreateRequest';\nimport { LeadRequestAdditionalData } from '@generated/openapi/model/leadRequestAdditionalData';\nimport { LeadRequestCreatePolymorphicTypes as LeadRequestType } from '@generated/openapi/model/leadRequestCreatePolymorphicTypes';\nimport { PublicDeparture } from '@generated/openapi/model/publicDeparture';\nimport { EnquireFormAdditionalInfoModalComponent } from '@shared/enquire-form-additional-info-modal/enquire-form-additional-info-modal.component';\nimport { FormDynamicWithConfigComponent } from '@shared/form-dynamic-with-config/form-dynamic-with-config.component';\n\nconst groupSizeStrings = [\n 'Solo traveller',\n 'Couple / 2 friends',\n 'Small group (up to 8)',\n 'Large group (8+)',\n];\nconst GROUP_SIZE_OPTIONS = [\n ...groupSizeStrings.map(value => ({\n value: value.toLowerCase(),\n label: value,\n })),\n];\n\n@Component({\n selector: 'app-enquire-form-modal',\n standalone: true,\n imports: [\n CommonModule,\n ReactiveFormsModule,\n FormDynamicWithConfigComponent,\n LazyPictureComponent,\n ],\n templateUrl: './enquire-form-modal.component.html',\n styles: ``,\n})\nexport class EnquireFormModalComponent implements OnInit {\n modalData: {\n trip: Trip;\n departure?: PublicDeparture;\n typeOfEnquiry: LeadRequestType;\n itinerary?: Itinerary;\n analyticsEventSent: AnalyticsEventName;\n analyticsEventCompleted: AnalyticsEventName;\n analyticsEventAbandoned: AnalyticsEventName;\n analyticsEventData: {\n trip: string;\n departure?: string;\n itinerary?: string;\n };\n };\n featuredImageConfiguration: Configurations;\n readonly modalContainerstyles = [\n '!w-full !h-full !max-h-screen !rounded-none',\n ];\n readonly isModalFullscreen = true;\n\n monthNames = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n ];\n years = [\n new Date().getUTCFullYear(),\n new Date().getUTCFullYear() + 1,\n new Date().getUTCFullYear() + 2,\n new Date().getUTCFullYear() + 3,\n ];\n\n formSchema = [\n {\n label: 'Your Name',\n type: 'text',\n name: 'name',\n validators: [Validators.required, Validators.minLength(3)],\n },\n {\n label: 'Your Email',\n type: 'email',\n name: 'email',\n validators: [Validators.required, Validators.email],\n },\n {\n label: 'No. of Travellers',\n name: 'travel',\n type: 'dropdown',\n testId: 'groupSize',\n placeholder: 'Select number',\n validators: [Validators.required],\n options: GROUP_SIZE_OPTIONS,\n },\n ];\n\n constructor(\n private modalService: ModalService,\n private djangoService: DjangoService,\n private eventTrackerService: EventTrackerService\n ) {}\n\n ngOnInit() {\n const trip = this.modalData.trip;\n const mobileCoverImage =\n trip?.enquireFormHorizontalImage || trip?.secondaryFeaturedImage;\n const desktopCoverImage =\n trip?.enquireFormVerticalImage || trip?.featuredImage;\n\n const currentMonth = new Date().getUTCMonth();\n const currentYear = new Date().getUTCFullYear();\n\n const dateOptions = this.years.flatMap(year => {\n return this.monthNames\n .map((month, index) => {\n if (year === currentYear && index < currentMonth) {\n return null;\n }\n return {\n value: `${month} ${year}`,\n label: `${month} ${year}`,\n };\n })\n .filter(option => option !== null);\n });\n\n if (\n this.modalData.typeOfEnquiry ===\n LeadRequestType.CustomDepartureLeadRequest\n ) {\n this.formSchema.push({\n label: 'When do you want to travel?',\n name: 'departure_date',\n type: 'dropdown',\n testId: 'departureDate',\n placeholder: 'Select number',\n validators: [Validators.required],\n options: dateOptions,\n });\n }\n\n this.featuredImageConfiguration = {\n [Stops.FALLBACK]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 1,\n width: 600,\n width2x: 800,\n },\n [Stops.BASE]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 3,\n width: 600,\n width2x: 800,\n },\n [Stops.SM]: {\n image: mobileCoverImage,\n ratioHeight: 1,\n ratioWidth: 3,\n width: 640,\n width2x: 1000,\n },\n [Stops.MD]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.LG]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.XL]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n [Stops.XXL]: {\n image: desktopCoverImage,\n ratioHeight: 4,\n ratioWidth: 1,\n width: 500,\n width2x: 500,\n },\n };\n }\n\n proceedToNextPage(leadId: string) {\n this.modalService.show(EnquireFormAdditionalInfoModalComponent, {\n createdLeadId: leadId,\n ...this.modalData,\n });\n }\n\n submitPrimaryForm(values) {\n this.createLead({\n resourcetype: this.modalData.typeOfEnquiry,\n email: values.email,\n first_name: values.name,\n group_size: values.travel,\n trip: this.modalData?.trip?.linkedVirtualOfficeTrip || null,\n itinerary:\n this.modalData?.itinerary?.linkedVirtualOfficeItinerary || null,\n departure: this.modalData?.departure?.id || null,\n departure_date: values.departure_date,\n }).subscribe(response => {\n this.eventTrackerService.trackEvent(\n this.modalData.analyticsEventSent,\n this.modalData.analyticsEventData,\n values.email\n );\n this.proceedToNextPage(response.id);\n });\n }\n\n createLead(\n data: DepartureLeadCreateRequest | CustomDepartureLeadCreateRequest\n ) {\n const route = Routes.leads;\n\n return this.djangoService.drfCreate<\n DepartureLeadCreateRequest | CustomDepartureLeadCreateRequest\n >(route, data);\n }\n\n addDetailsToLead(id, { comment, phone_number }) {\n const route = Routes.leads;\n const resource = `${id}/add_details`;\n return this.djangoService.drfUpdate(\n route,\n resource,\n {\n comment,\n phone_number,\n }\n );\n }\n}\n", "\n \n \n \n \n
\n

\n @if (modalData.trip.enquireFormHeading) {\n {{ modalData.trip.enquireFormHeading }}\n } @else {\n Ready for Your Next Adventure?\n }\n

\n

\n @if (modalData.trip.enquireFormDescription) {\n {{ modalData.trip.enquireFormDescription }}\n } @else {\n We'll send you a personalised itinerary and connect you with\n one of our travel experts!\n }\n

\n \n
\n \n\n", "import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, Input, OnInit } from '@angular/core';\nimport { EventTrackerService } from '@core/services/event-tracker.service';\nimport {\n FeatureFlagService,\n FeatureFlags,\n} from '@core/services/feature-flag.service';\nimport { ANALYTICS_EVENTS } from '@core/utils/AnalyticsEvents';\nimport { ModalService } from '@features/modal/services/modal.service';\nimport { FontAwesomeModule } from '@fortawesome/angular-fontawesome';\nimport { faArrowRight } from '@fortawesome/free-solid-svg-icons';\nimport { Trip } from '@generated/graphql';\nimport { LeadRequestCreatePolymorphicTypes as LeadRequestType } from '@generated/openapi/model/leadRequestCreatePolymorphicTypes';\nimport { PublicDeparture } from '@generated/openapi/model/publicDeparture';\nimport { CtaButtonComponent } from '@shared/cta-button/cta-button.component';\nimport { EnquireFormModalComponent } from '@shared/enquire-form-modal/enquire-form-modal.component';\nimport { DepartureWithDates } from '../trips-trip-self-booking/trips-trip-self-booking.component';\n@Component({\n selector: 'app-trips-trip-self-booking-departure-detail',\n standalone: true,\n imports: [CommonModule, FontAwesomeModule, CtaButtonComponent],\n templateUrl: './trips-trip-self-booking-departure-detail.component.html',\n})\nexport class TripsTripSelfBookingDepartureDetailComponent implements OnInit {\n open: boolean;\n openTooltip: boolean = false;\n isGuaranteed: boolean = false;\n isSoldOut: boolean = false;\n faArrowRight = faArrowRight;\n selfBookingFeatureFlagSignal = this.featureFlagService.getFeatureFlag(\n FeatureFlags.SELF_BOOKING\n );\n @Input() departure: DepartureWithDates;\n @Input() trip: Trip;\n @Input() isItineraryPage: boolean = false;\n toggleOpen() {\n this.open = !this.open;\n }\n\n public get DisplayStatusEnum() {\n return PublicDeparture.DisplayStatusEnum;\n }\n\n constructor(\n private modalService: ModalService,\n private eventTrackerService: EventTrackerService,\n public elRef: ElementRef,\n private featureFlagService: FeatureFlagService\n ) {}\n\n ngOnInit(): void {\n this.isGuaranteed = this.departure.status === 'GUARANTEED';\n this.isSoldOut = this.departure.status === 'SOLD_OUT';\n }\n\n toggleOpenTooltip() {\n this.openTooltip = !this.openTooltip;\n }\n\n join(departure: PublicDeparture) {\n if (this.isItineraryPage) {\n this.eventTrackerService.trackEvent(\n ANALYTICS_EVENTS.ITINERARY_ENQUIRE,\n {\n trip: this.trip.title,\n itinerary: this.departure.itinerary,\n departure: departure.title,\n }\n );\n } else {\n this.eventTrackerService.trackEvent(ANALYTICS_EVENTS.TRIP_ENQUIRE, {\n trip: this.trip.title,\n departure: departure.title,\n });\n }\n this.modalService.show(\n EnquireFormModalComponent,\n {\n departure: departure,\n trip: this.trip,\n typeOfEnquiry: LeadRequestType.DepartureLeadRequest,\n analyticsEventSent: ANALYTICS_EVENTS.TRIP_ENQUIRY_SENT,\n analyticsEventCompleted:\n ANALYTICS_EVENTS.TRIP_ENQUIRY_COMPLETED,\n analyticsEventAbandoned:\n ANALYTICS_EVENTS.TRIP_ENQUIRY_ABANDONED,\n analyticsEventData: {\n trip: this.trip.title,\n departure: departure.title,\n },\n },\n false\n );\n }\n}\n", "\n
\n

\n {{ departure.title }}\n

\n\n \n \n \n \n
\n \n
\n \n
\n
\n \n

\n {{ departure.date | date: 'mediumDate' }}\n

\n
\n
\n @switch (departure.display_status) {\n @case (DisplayStatusEnum.Open) {\n

\n Open for bookings\n

\n }\n @case (DisplayStatusEnum.FewSpots) {\n

\n Few spaces left\n

\n }\n @case (DisplayStatusEnum.SoldOut) {\n

\n Sold out\n

\n }\n }\n
\n
\n\n
\n from{{\n departure.price | currency: 'USD' : 'code' : '1.0-0'\n }}\n
\n Deposit{{\n departure.deposit | currency: 'USD' : 'code' : '1.0-0'\n }}\n
\n
\n @if (open) {\n \n
\n \n

\n {{ departure.end_date | date: 'mediumDate' }}\n

\n
\n

\n {{ departure.additional_text }}*\n

\n \n \n
\n

\n +${{ departure.single_supplement }}\n

\n

own room

\n
\n
\n \n @if (openTooltip) {\n
\n }\n @if (openTooltip) {\n \n \n \n \n \n \n

\n Upgrade to your own room by paying a charge\n of ${{ departure.single_supplement }}.\n Otherwise you will share a room with another\n traveller!\n

\n \n }\n \n \n \n }\n
\n @if (!isSoldOut) {\n \n Enquire\n \n }\n\n @if (\n selfBookingFeatureFlagSignal() &&\n departure.self_booking_enabled &&\n !isSoldOut\n ) {\n \n Book\n \n }\n\n \n \n \n \n
\n \n \n\n @if (open) {\n