{"version":3,"file":"product-details-B4a2ll0k.js","sources":["../../../scripts/components/products/details/cruise-benefit.vue","../../../scripts/services/helpers/truncation.ts","../../../scripts/components/products/details/product-itinerary.vue","../../../scripts/components/products/details/track-sailing.vue","../../../scripts/components/advisor/recommended-advisors.vue","../../../scripts/components/products/details/cruise-details.vue","../../../scripts/components/products/details/hotel-features.vue","../../../scripts/components/products/details/hotel-guest-rooms.vue","../../../scripts/components/products/details/hotel-details.vue","../../../scripts/components/products/details/tour-experiences.vue","../../../scripts/components/products/details/tour-details.vue","../../../scripts/services/layout/sticky-subhead.ts","../../../scripts/components/advisor/advisor-details.vue","../../../scripts/components/products/details/product-details.vue","../../../scripts/entry-points/product-details.ts"],"sourcesContent":["<template>\r\n    <div :id=\"'benefit-' + benefit.id\" ref=\"benefit\" :class=\"['-item', (isCarousel) ? 'slide slide-flex' : '']\">\r\n        <div v-if=\"isHostedBenefit\" class=\"-benefit-number-label d-md-none\" v-html=\"hostedBenefitNumberLabel\"></div>\r\n        <div class=\"-overview\">\r\n            <img v-if=\"benefit.thumbnailImageUrl\" :src=\"benefit.thumbnailImageUrl\" width=\"230\" class=\"d-none d-md-block\" :title=\"benefit.name\" :alt=\"benefit.name\" />\r\n            <div v-if=\"benefit.isEvent\" :class=\"['mt-1 text--small -details', (collapseMobileFields) ? 'mobile-benefit-collapsed' : '']\">\r\n                <div v-if=\"benefit.meals\">Meals: <b v-html=\"benefit.meals\"></b></div>\r\n                <div v-if=\"benefit.ageAppropriateness\">Recommended&nbsp;Ages: <b v-html=\"benefit.ageAppropriateness\"></b></div>\r\n                <div v-if=\"benefit.activityLevel\">Activity&nbsp;Level: <b v-html=\"benefit.activityLevel\"></b></div>\r\n                <div v-if=\"benefit.experiences\">Experience(s): <b v-html=\"benefit.experiences\"></b></div>\r\n            </div>\r\n        </div>\r\n        <div class=\"-description\">\r\n            <h3 v-html=\"benefit.name\"></h3>\r\n            <div v-if=\"benefit.location || benefit.duration\" class=\"mt-1\">\r\n                <span v-if=\"benefit.location\" v-html=\"benefit.location\"></span>\r\n                <span v-if=\"benefit.duration\" v-html=\"benefit.duration\"></span>\r\n            </div>\r\n            <div v-if=\"benefit.notice\" class=\"-notice mt-1\" v-html=\"benefit.notice\"></div>\r\n            <div v-if=\"collapseMobileFields\" class=\"d-md-none mobile-benefit-expand-button mt-1 text-center\"><button class=\"btn btn-xs btn-primary-emphasis\" @click=\"expandHostedBenefits\">Show all details</button></div>\r\n            <div :class=\"['mt-1', (collapseMobileFields) ? 'mobile-benefit-collapsed' : '']\" v-html=\"benefit.description\"></div>\r\n            <div v-if=\"benefit.isEvent\" :class=\"['mt-1', (collapseMobileFields) ? 'mobile-benefit-collapsed' : '']\">\r\n                <div><b v-html=\"benefit.availability\"></b> of {{ benefit.capacity }} spaces remaining {{ benefit.waitlist }}</div>\r\n            </div>\r\n        </div>\r\n        <div v-if=\"isHostedBenefit\" class=\"-benefit-number-label d-none d-md-block\" v-html=\"hostedBenefitNumberLabel\"></div>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { CruiseBenefit } from \"interfaces/cruise\";\r\n    import { getPlural } from \"virtuoso-shared-web-ui\";\r\n    import { PropType, ref, useTemplateRef } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        benefit: {\r\n            type: Object as PropType<CruiseBenefit>,\r\n            default: undefined\r\n        },\r\n        hostedBenefitIndex: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        isCarousel: {\r\n            type: Boolean\r\n        },\r\n        isHostedBenefit: {\r\n            type: Boolean\r\n        },\r\n        totalHostedBenefits: {\r\n            type: Number,\r\n            default: undefined\r\n        }\r\n    });\r\n\r\n    const collapseMobileFields = ref((props.isHostedBenefit && !props.benefit.isForAllGuests));\r\n    const hostedBenefitNumberLabel = ref(`${props.hostedBenefitIndex + 1} of ${props.totalHostedBenefits} possible benefit${getPlural(props.totalHostedBenefits)}`);\r\n    const benefitRef = useTemplateRef(\"benefit\");\r\n\r\n    function expandHostedBenefits(): void {\r\n        collapseMobileFields.value = false;\r\n\r\n        // Need the carousel to recalculate the height        \r\n        const splideElement = benefitRef.value.closest(`.splide__track`);\r\n        if (splideElement) {\r\n            const evt = new CustomEvent(\"resize\", { bubbles: true, cancelable: false, composed: true });\r\n            splideElement.dispatchEvent(evt);\r\n        }\r\n    }   \r\n</script>\r\n","/**\r\n * applyVerticalTruncation - Sets truncation with a gradient and \"View more\" link on the bottom\r\n *   The whole element is clickable to expand.\r\n *   Height of the truncated content is based off of the max-height of .truncate-vertical.-initialized,\r\n        which defaults to the values in .truncate-5\r\n *   Use the @truncate-lines mixin to set different heights.\r\n *   Optionally add a data-view-more-text element to specify link text other than \"View more\".\r\n * @param containerElement - The block element(s) to be vertically truncated, defaults to document.querySelectorAll(\".truncate-vertical\")\r\n */\r\nexport function applyVerticalTruncation(truncateElements: NodeList = document.querySelectorAll<HTMLElement>(\".truncate-vertical\")): void {\r\n    truncateElements.forEach((element: HTMLElement) => {\r\n\r\n        if (!element.classList.contains(\"-initialized\")) {\r\n\r\n            const viewMoreText: string = element.dataset.viewMoreText || \"View more\";\r\n            const viewLessText: string = element.dataset.viewLessText || \"View less\";\r\n\r\n            element.classList.add(\"-initialized\");\r\n\r\n            const initialHeight: number = element.offsetHeight;\r\n            const copyHeight = element.scrollHeight;\r\n\r\n            // Check to see if the text is long enough to even worry with this mess\r\n            if (copyHeight <= initialHeight) {\r\n                element.classList.add(\"-not-needed\");\r\n            } else {\r\n\r\n                // Add the inner div\r\n                const innerWrap = document.createElement(\"div\");\r\n                innerWrap.classList.add(\"-inner\");\r\n                innerWrap.innerHTML = element.innerHTML;\r\n\r\n                // Add the 'View less\" button now so it takes up space when expanding\r\n                innerWrap.insertAdjacentHTML(\"beforeend\", `<div><button class=\"btn-link -toggle -view-less\">${viewLessText} <i class=\"icon-angle-up\"></i></button></div>`);\r\n                element.innerHTML = innerWrap.outerHTML;\r\n                const maxHeight = element.scrollHeight;\r\n\r\n                // Add the gradient overlay\r\n                element.insertAdjacentHTML(\"beforeend\", `<div class=\"-gradient\"><button class=\"btn-link -toggle\">${viewMoreText} <i class=\"icon-angle-down\"></i></button></div>`);\r\n\r\n                // // Allow re-collapsing\r\n                element.querySelector(\".-view-less\").addEventListener(\"click\", () => {\r\n                    element.style.maxHeight = maxHeight + \"px\"; // Explicitly reset the current full height from 'none'\r\n                    setTimeout(() => { // Let the max-height percolate so the transition transitions\r\n                        element.style.maxHeight = initialHeight + \"px\"; // Then back down to collapsed\r\n                    }, 1);\r\n\r\n                    // Re-enable \"View more\"\r\n                    setTimeout(() => { // Prevent immediate re-execution\r\n                        applyTruncationHandlers(element, maxHeight);\r\n                        element.classList.remove(\"-reveal\");\r\n                    }, 100);\r\n                });\r\n\r\n                applyTruncationHandlers(element, maxHeight);\r\n            }\r\n        }\r\n    });\r\n\r\n}\r\n\r\nfunction applyTruncationHandlers(el: HTMLElement, maxHeight: number): void {\r\n    el.addEventListener(\"click\", () => {\r\n        el.style.maxHeight = maxHeight + \"px\";\r\n\r\n        function handleTransitionEnd(e: Event) {\r\n            if (e.target === e.currentTarget) {\r\n                // To keep multiple events from being fired (child elements with transitions)\r\n                el.style.maxHeight = \"none\"; // Set the max-height to none after the transition so page resizing works\r\n                el.removeEventListener(\"transitionend\", handleTransitionEnd);\r\n            }\r\n        }\r\n\r\n        el.addEventListener(\"transitionend\", handleTransitionEnd);\r\n\r\n        el.classList.add(\"-reveal\");\r\n    }, { once: true });\r\n}\r\n","<template>\r\n    <ol class=\"list-unstyled itinerary-container\">\r\n        <li v-for=\"(day, dayIndex) in itinerary\" :key=\"dayIndex\" :class=\"'itinerary-row' + ' -' + productType\">\r\n            <div class=\"-day context-dark\">\r\n                <div>Day {{ day.itineraryDay }}</div>\r\n                <div v-if=\"day.dateFormatted\" class=\"-date\" v-html=\"day.dateFormatted\"></div>\r\n            </div>\r\n            <div class=\"-content\">\r\n                <div class=\"-overview\">\r\n                    <div class=\"-stops\">\r\n                        <div class=\"-label\">Location(s)</div>\r\n                        <ol class=\"list-unstyled\">\r\n                            <li v-for=\"(stop, stopIndex) in day.stops\" :key=\"stopIndex\" class=\"text-emphasis\">\r\n                                <i v-if=\"isCruiseTour\" :class=\"['me-1', (stop.isOnLand) ? 'icon-shuttle' : 'icon-Cruises']\"></i>\r\n                                {{ stop.location }}\r\n                                <span v-if=\"isCruise && (stop.timeArrive || stop.timeDepart)\" class=\"-times\">\r\n                                    <span v-if=\"stop.timeArrive\">Arrive: {{ stop.timeArrive }}</span>\r\n                                    <span v-if=\"stop.timeDepart\">Depart: {{ stop.timeDepart }}</span>\r\n                                </span>\r\n                            </li>\r\n                        </ol>\r\n                    </div>\r\n                    <div v-if=\"isTour\" class=\"-lodging\">\r\n                        <div class=\"-label\">Hotel</div>\r\n                        <div v-if=\"day.hotelName\" class=\"text-emphasis\" v-html=\"day.hotelName\"></div>\r\n                        <div v-else class=\"text-emphasis\">None</div>\r\n                    </div>\r\n                    <div v-if=\"isTour\" class=\"-meals\">\r\n                        <div class=\"-label\">Meals</div>\r\n                        <div v-if=\"day.meals\" class=\"text-emphasis\" v-html=\"day.meals\"></div>\r\n                        <div v-else class=\"text-emphasis\">None</div>\r\n                    </div>\r\n                </div>\r\n                <div v-if=\"day.description\" class=\"-description truncate-vertical truncate-3\" data-view-more-text=\"More details\" data-view-less-text=\"Fewer details\" v-html=\"day.description\"></div>\r\n            </div>\r\n        </li>\r\n    </ol>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { ItineraryDay } from \"interfaces/date\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { applyVerticalTruncation } from \"services/helpers/truncation\";\r\n    import { nextTick, PropType } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        productType: {\r\n            type: String as PropType<ProductType>,\r\n            default: undefined\r\n        },\r\n        isCruiseTour: {\r\n            type: Boolean\r\n        },\r\n        itinerary: {\r\n            type: Array as PropType<ItineraryDay[]>,\r\n            default: undefined\r\n        }\r\n    });\r\n\r\n    const isCruise = (props.productType === ProductType.CRUISES);\r\n    const isTour = (props.productType === ProductType.TOURS);\r\n\r\n    nextTick(() => {\r\n        applyVerticalTruncation(document.querySelectorAll(\".itinerary-container .truncate-vertical\"));\r\n    });\r\n    \r\n</script>\r\n","<template>\r\n    <div v-if=\"canViewComponent\" id=\"track-sailing-component\" class=\"mt-2\">\r\n        <button v-show=\"!showTrackCruiseForm\" class=\"btn btn-primary-regular btn-sm w-100\" @click=\"toggleTrackSailingForm()\">Track Sailing</button>\r\n        <div v-show=\"showTrackCruiseForm\" class=\"-wrapper\">\r\n            <h3>Track this Sailing</h3>\r\n            <div class=\"mt-1 text--small\">Client Name(s)</div>\r\n            <div class=\"mt-half input-group\">\r\n                <input id=\"track-sailing-client\" v-model=\"clientNamesValue\" type=\"text\" maxlength=\"50\" class=\"form-control\" :disabled=\"isLoading\" @keyup.enter=\"doTrackCruise\" />\r\n            </div>\r\n            <div v-if=\"validationText\" class=\"text-danger text--small mt-1\">{{ validationText }}</div>\r\n            <div class=\"mt-1\">\r\n                <button :class=\"['btn btn-primary-emphasis btn-sm', isLoading ? 'disabled' : '']\" :disabled=\"isLoading\" @click=\"doTrackCruise\">Save</button>\r\n                <button :class=\"['btn btn-tertiary btn-sm ms-2', isLoading ? 'disabled' : '']\" :disabled=\"isLoading\" @click=\"toggleTrackSailingForm(true)\">Cancel</button>\r\n            </div>\r\n        </div>\r\n        <div class=\"text--small mt-2 mx-auto d-none d-lg-block\"><a :href=\"cobrandLink('/cruisealerts')\">Learn more about Virtuoso Cruise Alerts</a></div>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { AddCruiseAlertResponse } from \"interfaces/responses/product-detail-responses\";\r\n    import { saveTrackSailing } from \"services/api/user\";\r\n    import { isAdvisor, isVStaff } from \"services/auth/user-info\";\r\n    import { toastError, toastSuccess } from \"services/helpers/toasts\";\r\n    import { isEmbeddedMode } from \"services/layout/environment\";\r\n    import { cobrandLink } from \"virtuoso-shared-web-ui\";\r\n    import { ref } from \"vue\";\r\n\r\n    const props = defineProps({\r\n        sailingId: {\r\n            type: Number,\r\n            default: undefined\r\n        }\r\n    });\r\n\r\n    const clientNamesValue = defineModel<string>();\r\n    const canViewComponent = (isAdvisor() || isVStaff()) && !isEmbeddedMode();\r\n    const showTrackCruiseForm = ref(false);\r\n    const validationText = ref(\"\");\r\n    const isLoading = ref(false);\r\n\r\n        \r\n    function doTrackCruise(): void {\r\n        if (!clientNamesValue.value || clientNamesValue.value.length < 3 || clientNamesValue.value.length > 50) {\r\n            validationText.value = \"Client name(s) must be between 3 and 50 characters.\";\r\n            return;\r\n        }\r\n\r\n        isLoading.value = true;\r\n        validationText.value = \"\";\r\n\r\n        saveTrackSailing(props.sailingId, clientNamesValue.value).then((resultJSON: AddCruiseAlertResponse) => {\r\n                    if (resultJSON && resultJSON.success) {\r\n                        toastSuccess(\"Sailing tracked successfully!\");\r\n                        toggleTrackSailingForm();\r\n                        clientNamesValue.value = \"\";\r\n                        isLoading.value = false;\r\n                    } else {\r\n                        toastError(\"Error tracking this sailing, please try again.\");\r\n                        isLoading.value = false;\r\n                    }\r\n                }, () => {\r\n                    toastError(\"Error tracking this sailing, please try again.\");\r\n                    isLoading.value = false;\r\n                });\r\n    }\r\n\r\n    function toggleTrackSailingForm(clearValue = false): void {\r\n        validationText.value = \"\";\r\n        if (clearValue) {\r\n            clientNamesValue.value = \"\";\r\n        }\r\n\r\n        showTrackCruiseForm.value = !showTrackCruiseForm.value;\r\n    }\r\n</script>\r\n","<template>\r\n    <div v-if=\"canViewComponent && !isLoading\" class=\"recommended-advisors mt-3\">\r\n        <div v-if=\"hasAdvisors && !isCobranded()\" class=\"slab p-2\">\r\n            <h4>Connect with a Virtuoso Travel Advisor</h4>\r\n            <ul class=\"list-unstyled\">\r\n                <li v-for=\"(advisor, index) in recommendedAdvisors\" :key=\"index\" class=\"mt-2 d-flex d-md-block d-lg-flex\">\r\n                    <div v-if=\"advisor.advisorImageUrl\" class=\"-headshot mb-2\"><a :href=\"advisor.advisorUrl\" @click=\"trackRecommendedAdvisorClick(advisor, index)\"><img :src=\"advisor.advisorImageUrl\" :alt=\"advisor.advisorName\" class=\"rounded-circle d-block mx-auto\" width=\"120\" loading=\"lazy\" /></a></div>\r\n                    <div v-track-element-view=\"getRecommendedAdvisorTrackingData(advisor, index)\" class=\"-contact-info\">\r\n                        <div><a :href=\"advisor.advisorUrl\" class=\"-name\" @click=\"trackRecommendedAdvisorClick(advisor, index)\" v-html=\"advisor.advisorName\"></a></div>\r\n                        <div v-if=\"advisor.recommendedLabel\" class=\"text--xsmall\" v-html=\"advisor.recommendedLabel\"></div>\r\n                        <div class=\"mt-1\">\r\n                            <div v-if=\"advisor.advisorSpecialtyLabel\" class=\"fw-bold text--small\" v-html=\"advisor.advisorSpecialtyLabel\"></div>\r\n                            <div class=\"text--xsmall\" v-html=\"advisor.agencyLocation\"></div>\r\n                            <div class=\"text--xsmall\" v-html=\"advisor.agencyName\"></div>\r\n                            <advisor-contact-button-component :advisor=\"advisorContactButtonInfo(advisor)\" :event-name=\"gaCategory\" button-style=\"down-arrow\" class=\"mt-1-half\"></advisor-contact-button-component>\r\n                        </div>\r\n                    </div>\r\n                </li>\r\n            </ul>\r\n            <div class=\"mt-2\"><a :href=\"advisorCatalogLinkFiltered\">Or, find a different advisor</a></div>\r\n        </div>\r\n        <a v-else-if=\"!isNetworkUser() && !isCobranded()\" class=\"btn btn-primary-emphasis btn-sm d-block\" :href=\"cobrandLink('/travel/advisors/search#')\">Find a Travel Advisor</a>\r\n        <a v-else-if=\"!isNetworkUser() && isCobranded() && !hideCobrandedButton\" class=\"btn btn-primary-emphasis btn-sm d-block\" :href=\"cobrandLink('/travel/advisors/search#')\">Contact Advisor to Book</a>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import AdvisorContactButtonComponent from \"components/advisor/advisor-contact-button.vue\";\r\n    import { AdvisorContactButton, RecommendedAdvisor, RecommendedAdvisorQuery } from \"interfaces/advisor\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { getRecommendedAdvisors } from \"services/api/advisors\";\r\n    import { isNetworkUser } from \"services/auth/user-info\";\r\n    import { extractCountryFromLocationString } from \"services/helpers/destinations\";\r\n    import { generateMediaServerImageUrl } from \"services/helpers/images\";\r\n    import { isEmbeddedMode } from \"services/layout/environment\";\r\n    import { translateB2BFacetToConsumer } from \"services/search/product-search\";\r\n    import { parseAdvisorMeidFromUrlString, translateToConsumerUrl } from \"services/transformers/products\";\r\n    import { getRecommendedAdvisorTrackingData, trackRecommendedAdvisorClick } from \"services/analytics\";\r\n    import { cobrandLink, getPlural, isCobranded } from \"virtuoso-shared-web-ui\";\r\n    import { computed, PropType, provide, ref } from \"vue\";\r\n  \r\n    const props = defineProps({\r\n        advisorQuery: {\r\n            type: Object as PropType<RecommendedAdvisorQuery>,\r\n            default: () => ({})\r\n        },\r\n        hideCobrandedButton: {\r\n            type: Boolean,\r\n            default: false\r\n        },\r\n        setRecommendedAdvisorIds: {\r\n            type: Function,\r\n            default: (): void => { /* if setRecommendedAdvisorsIds() is passed as undefined */ }\r\n        }\r\n    });\r\n\r\n    // Data provided to advisor contact form\r\n    provide(\"searchFilters\", computed(() => ({\r\n                    destinationSpecialties: advisorSearchquery.value.ProductLocationCountry,\r\n                    specialties: advisorSearchquery.value.InterestType}))\r\n    );\r\n\r\n    const advisorCatalogLinkFiltered = ref(cobrandLink(\"/travel/advisors/search#\"));\r\n    const canViewComponent = ref((!isEmbeddedMode() && !isNetworkUser()));\r\n    const gaCategory = ref((props.advisorQuery.ProductTypeName === \"Cruise\") ? \"Sailing Detail\" : `${props.advisorQuery.ProductTypeName} Detail`);\r\n    const hasAdvisors = ref(false);\r\n    const isLoading = ref(true);\r\n    const recommendedAdvisors = ref([] as RecommendedAdvisor[]);\r\n    const advisorSearchquery = ref(props.advisorQuery);\r\n\r\n    if (canViewComponent.value) {\r\n        // Special handling for US destination specialties, no \"magic sub region\" mapping (for now?)\r\n        if (advisorSearchquery.value.ProductLocationCountry === \"United States\") {\r\n            advisorSearchquery.value.ProductLocationCountry = \"United States - All\";\r\n        }\r\n\r\n        // Translation from ship cruise type to advisor interest type\r\n        if (advisorSearchquery.value.ProductTypeName === \"Cruise\" && advisorSearchquery.value.InterestType) {\r\n            advisorSearchquery.value.InterestType = `${advisorSearchquery.value.InterestType} Cruising`;\r\n        }\r\n\r\n        if (advisorSearchquery.value.ProductLocationCountry) {\r\n            advisorCatalogLinkFiltered.value += `${translateB2BFacetToConsumer(\"advisor_specilty_destination_for_facet\")}=${encodeURIComponent(advisorSearchquery.value.ProductLocationCountry)}`;\r\n        } else if (advisorSearchquery.value.InterestType) {\r\n            advisorCatalogLinkFiltered.value += `${translateB2BFacetToConsumer(\"advisor_interest_types\")}=${encodeURIComponent(advisorSearchquery.value.InterestType)}`;\r\n        }\r\n\r\n        getAdvisors();\r\n    }\r\n\r\n    function advisorContactButtonInfo(advisor: RecommendedAdvisor): AdvisorContactButton {\r\n        return {\r\n            company: advisor.agencyName,\r\n            companyId: advisor.companyId,\r\n            country: advisor.country,\r\n            email: advisor.advisorEmail,\r\n            id: parseAdvisorMeidFromUrlString(advisor.advisorUrl),\r\n            name: advisor.advisorName,\r\n            phone: advisor.advisorPhone,\r\n            productType: ProductType.ADVISORS\r\n        };\r\n    }\r\n\r\n    function getAdvisors(): void {\r\n\r\n        let firstRecommendedAdvisor: number = null;\r\n        let lastRecommendedAdvisor: number = null;\r\n\r\n        if (!isCobranded()) { // If it's cobranded, we only ever show either a static button or nothing\r\n\r\n            getRecommendedAdvisors(advisorSearchquery.value)\r\n                .then((advisorsJSON) => {\r\n\r\n                    // Test data for local testing, comment out the getRecommendedAdvisors().then() lines & the reject below\r\n                    // const advisorsJSON = advisorsTestData;\r\n\r\n                    if (advisorsJSON && advisorsJSON.length > 0) {\r\n                        const validAdvisors: RecommendedAdvisor[] = [];\r\n\r\n                        advisorsJSON.forEach((advisor) => {\r\n                            if (advisor.AdvisorName && advisor.ProfilePageUrl && advisor.EmailAddress && advisor.PhoneNumber && advisor.AgencyLocation && advisor.AgencyName) {\r\n                                validAdvisors.push({\r\n                                    advisorEmail: advisor.EmailAddress,\r\n                                    advisorImageUrl: (advisor.ImageUrl) ? generateMediaServerImageUrl(advisor.ImageUrl, { height: 140, width: 140 }) : \"\",\r\n                                    advisorName: advisor.AdvisorName,\r\n                                    advisorPhone: advisor.PhoneNumber,\r\n                                    advisorSpecialtyLabel: advisor.AdvisorSpecialityLabel,\r\n                                    advisorUrl: translateToConsumerUrl(advisor.ProfilePageUrl),\r\n                                    agencyLocation: advisor.AgencyLocation,\r\n                                    agencyName: advisor.AgencyName,\r\n                                    companyId: advisor.CompanyId,\r\n                                    country: extractCountryFromLocationString(advisor.AgencyLocation),\r\n                                    recommendedLabel: (advisor.TotalReviews && advisor.TotalReviews > 0) ? `${advisor.TotalRecommendedPercent}% Recommended (${advisor.TotalReviews} Review${getPlural(advisor.TotalReviews)})` : \"\",\r\n                                    totalReviews: advisor.TotalReviews\r\n                                });\r\n                            }\r\n                        });\r\n\r\n                        if (validAdvisors.length) {\r\n                            if (validAdvisors.length > 2) {\r\n                                validAdvisors.length = 2; // If, for some reason, it returns more than 2 advisors, trim it down to 2\r\n                            }\r\n                            recommendedAdvisors.value = validAdvisors;\r\n                            hasAdvisors.value = true;\r\n                            // there are at max 2 advisors\r\n                            if (recommendedAdvisors.value[0]) {\r\n                                firstRecommendedAdvisor = parseAdvisorMeidFromUrlString(recommendedAdvisors.value[0].advisorUrl);\r\n                            }\r\n                            if (recommendedAdvisors.value[1]) {\r\n                                lastRecommendedAdvisor = parseAdvisorMeidFromUrlString(recommendedAdvisors.value[1].advisorUrl);\r\n                            }\r\n                        }\r\n\r\n                    } else {\r\n                        console.log(\"No recommended advisors available.\");\r\n                    }\r\n                    isLoading.value = false;\r\n                },\r\n                    (err: Error) => {\r\n                        console.log(\"Error retrieving recommended advisors\", err);\r\n                        isLoading.value = false;\r\n                    })\r\n                .finally(() => {\r\n                    props.setRecommendedAdvisorIds(firstRecommendedAdvisor, lastRecommendedAdvisor);\r\n                });\r\n        } else {\r\n            if (props.hideCobrandedButton) {\r\n                canViewComponent.value = false;\r\n            }\r\n            isLoading.value = false;\r\n        }\r\n    }\r\n</script>\r\n","<template>\r\n    <div v-if=\"isOverviewReady\" ref=\"product-detail\" class=\"product-detail\">\r\n        <top-splash-component :top-splash-data=\"topSplashData\" @promo-click=\"showTab('promotions', false, true)\"></top-splash-component>\r\n        <div v-if=\"isReady\">\r\n            <div class=\"container mt-4\">\r\n                <div class=\"product-detail-overview mb-6\">\r\n                    <div>\r\n                        <h1 v-html=\"sailing.cruiseName\"></h1>\r\n                        <div v-if=\"sailing.isCruiseTour\" class=\"mt-1\"><b>CRUISETOUR</b></div>\r\n                        <div v-if=\"sailing.sailings.length > 1\" class=\"mt-2\">\r\n                            Travel Dates<br />\r\n                            <template v-if=\"isEmbeddedMode()\">\r\n                                Ask your advisor about available travel dates\r\n                            </template>\r\n                            <label v-else class=\"select--styled\">\r\n                                <select id=\"itinerary-nav\" class=\"w-100\" aria-label=\"Select Travel Dates\" @change=\"goToSailing()\">\r\n                                    <option v-for=\"(item, index) in sailing.sailings\" :key=\"index\" :value=\"item.id\" :selected=\"item.id === sailing.id\" :data-url=\"item.url\" v-html=\"item.travelDates\"></option>\r\n                                </select>\r\n                            </label>\r\n                        </div>\r\n                        <div class=\"mt-3 -description\">\r\n                            <b v-if=\"sailing.sailings.length <= 1\">{{ sailing.travelDates }}<br /></b>\r\n                            <b v-html=\"sailing.cruisePorts\"></b><br />\r\n                            <b v-if=\"isEmbeddedMode()\" class=\"weglot-exclude\" v-html=\"sailing.companyName\"></b>\r\n                            <a v-else class=\"weglot-exclude\" :href=\"sailing.brandUrl\"><b v-html=\"sailing.companyName\"></b></a>\r\n                            <br />\r\n                            Ship: <b v-if=\"isEmbeddedMode()\" class=\"weglot-exclude\" v-html=\"sailing.shipName\"></b>\r\n                            <b v-else class=\"weglot-exclude\"><a :href=\"sailing.shipUrl\" v-html=\"sailing.shipName\"></a></b>\r\n                        </div>\r\n\r\n                        <div v-if=\"isNetworkUser() && sailing.cruiseDepartureCode\" class=\"mt-2\">Sailing ID: {{ sailing.cruiseDepartureCode }}</div>\r\n\r\n                        <h2 class=\"text--serif mt-3\">At a Glance</h2>\r\n\r\n                        <img :src=\"sailing.cruiseMapUrl\" width=\"500\" :alt=\"'Cruise Itinerary Map for ' + sailing.cruiseName\" :title=\"'Cruise Itinerary Map for ' + sailing.cruiseName\" class=\"mt-2\" loading=\"lazy\" />\r\n\r\n                        <div v-if=\"sailing.whatIsIncluded\" class=\"mt-2\">\r\n                            <div class=\"mb-1\"><b>Included</b></div>\r\n                            <div v-html=\"sailing.whatIsIncluded\"></div>\r\n                        </div>\r\n\r\n                        <div v-if=\"sailing.whatIsNotIncluded\" class=\"mt-2\">\r\n                            <div class=\"mb-1\"><b>Not Included</b></div>\r\n                            <div v-html=\"sailing.whatIsNotIncluded\"></div>\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"-gallery mt-5 mt-md-0 mb-6\">\r\n                        <image-gallery-component v-if=\"sailing.galleryImages && sailing.galleryImages.length\"\r\n                                                 :gallery-data=\"sailing.galleryImages\"\r\n                                                 :product-id=\"sailing.id.toString()\"\r\n                                                 :product-name=\"sailing.cruiseName\"\r\n                                                 :product-type=\"ProductType.CRUISES\"></image-gallery-component>\r\n                        <recommended-advisors-component v-if=\"!suppressRecommendedAdvisors\" :advisor-query=\"recommendedAdvisorQuery\" :product-type=\"ProductType.CRUISES\" :set-recommended-advisor-ids=\"setRecommendedAdvisorIds\"></recommended-advisors-component>\r\n                        <a v-if=\"isNetworkUser() && !isEmbeddedMode()\" id=\"b2blink-legacy-link-label\" class=\"btn btn-primary-emphasis btn-sm d-block mt-3\" :href=\"legacyLink\" @click=\"handleLegacyLinkClick\">{{ legacyLinkLabel }}</a>\r\n                        <track-sailing-component :sailing-id=\"productId\"></track-sailing-component>\r\n                        <button class=\"wl-heartable -save-this mt-3\" data-wl-type=\"cruise\" :data-wl-id=\"heartableUrl\" :data-wl-title=\"cruiseTitle\"></button>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n            <div id=\"detail-tabs\"></div>\r\n            <div class=\"container d-none d-md-block\">\r\n                <ul ref=\"tab-nav-container\" class=\"tab-nav-container\">\r\n                    <li id=\"tab-itinerary\"><button @click=\"showTab('itinerary')\">Itinerary</button></li>\r\n                    <li v-if=\"hasBenefits\" id=\"tab-benefits\"><button @click=\"showTab('benefits')\">Virtuoso Benefits</button></li>\r\n                    <li v-if=\"sailing.promotions.length\" id=\"tab-promotions\"><button @click=\"showTab('promotions')\">Promotions</button></li>\r\n                    <li v-if=\"sailing.addOnDayTours.length || sailing.postPackages.length || sailing.prePackages.length\" id=\"tab-add-ons\"><button @click=\"showTab('add-ons')\">Add-ons</button></li>\r\n                </ul>\r\n            </div>\r\n            <div class=\"slab -tab-slab\">\r\n                <div class=\"container\">\r\n                    <ul class=\"tab-content\">\r\n                        <li id=\"tc-itinerary\">\r\n                            <button class=\"tab-nav\" @click=\"showTab('itinerary')\">Itinerary</button>\r\n                            <div class=\"-container\">\r\n                                <h4 class=\"tab-title\">Itinerary</h4>\r\n                                <div v-if=\"sailing.isCruiseTour\" class=\"my-1 cruisetour-key\"><span class=\"text-nowrap me-3\"><i class=\"icon-shuttle\"></i> Tour Segment</span> <span class=\"text-nowrap\"><i class=\"icon-Cruises\"></i> Cruise Segment</span></div>\r\n                                <product-itinerary-component :itinerary=\"sailing.itinerary\" :product-type=\"ProductType.CRUISES\" :is-cruise-tour=\"sailing.isCruiseTour\"></product-itinerary-component>\r\n                            </div>\r\n                        </li>\r\n                        <li v-if=\"hasBenefits\" id=\"tc-benefits\">\r\n                            <button class=\"tab-nav\" @click=\"showTab('benefits')\">Virtuoso Benefits</button>\r\n                            <div class=\"-container\">\r\n                                <h4 class=\"tab-title\">Virtuoso Benefits</h4>\r\n                                <div v-if=\"sailing.benefitsHostedGroups.length > 0\" class=\"mb-4 mt-2\">\r\n                                    <h2 class=\"text--serif mt-2\">Hosted Benefits</h2>\r\n                                    <div v-for=\"(hbg, hbgIndex) in sailing.benefitsHostedGroups\" :key=\"hbgIndex\" class=\"benefits-box mt-2\">\r\n                                        <div class=\"-title-row\">\r\n                                            <div class=\"-dates\" v-html=\"hbg.dates\"></div>\r\n                                            <div class=\"-hosts\" v-html=\"hbg.hosts\"></div>\r\n                                        </div>\r\n                                        <div v-if=\"hbg.hostedBenefits.length > 0\" class=\"benefits-container\">\r\n                                            <div class=\"text--small\">Guests may select one of the following benefits. Please consult your Virtuoso travel advisor for restrictions and fees that apply to 3rd and 4th passengers in the cabin.</div>\r\n                                            <CarouselSliderComponent v-if=\"hbg.hostedBenefits.length > 1 && isBenefitsCarouselInitialized\" slide-class=\"-slide\" :slides=\"hbg.hostedBenefits\" :carousel-config=\"carouselConfig\">\r\n                                                <template #slides=\"{slide, index}\">\r\n                                                    <cruise-benefit-component :benefit=\"slide\"\r\n                                                                              :is-hosted-benefit=\"true\"\r\n                                                                              :is-carousel=\"true\"\r\n                                                                              :hosted-benefit-index=\"index\"\r\n                                                                              :total-hosted-benefits=\"hbg.hostedBenefits.length\"></cruise-benefit-component>\r\n                                                </template>\r\n                                            </CarouselSliderComponent>\r\n                                            <cruise-benefit-component v-else-if=\"hbg.hostedBenefits.length === 1\"\r\n                                                                      :benefit=\"hbg.hostedBenefits[0]\"\r\n                                                                      :is-hosted-benefit=\"true\"\r\n                                                                      :is-carousel=\"false\"\r\n                                                                      :hosted-benefit-index=\"0\"\r\n                                                                      :total-hosted-benefits=\"1\"></cruise-benefit-component>\r\n                                        </div>\r\n                                        <div v-if=\"hbg.forAllBenefits.length > 0\" class=\"container mt-2\">\r\n                                            <div><b>Guests may also enjoy these benefits.</b> Restrictions may apply.</div>\r\n                                            <cruise-benefit-component v-for=\"(ben, benIndex) in hbg.forAllBenefits\" :key=\"benIndex\" :benefit=\"ben\" :is-hosted-benefit=\"false\"></cruise-benefit-component>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n                                <div v-if=\"sailing.benefitsExclusive.length > 0\" class=\"mt-2 mb-4\">\r\n                                    <h2 class=\"text--serif\">Exclusive Benefits</h2>\r\n                                    <div class=\"benefits-box mt-2\">\r\n                                        <div class=\"benefits-container\">\r\n                                            <div>Guests may also be entitled to the following complimentary benefits. Please consult your Virtuoso travel advisor for restrictions that may apply.</div>\r\n                                            <cruise-benefit-component v-for=\"(ben, benIndex) in sailing.benefitsExclusive\" :key=\"benIndex\" :benefit=\"ben\" :is-hosted-benefit=\"false\"></cruise-benefit-component>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n                                <div v-if=\"sailing.benefitsHQGroups.length > 0\" class=\"mt-2\">\r\n                                    <h2 class=\"text--serif\">HQ Group Benefits</h2>\r\n                                    <div class=\"benefits-box mt-2\">\r\n                                        <div class=\"benefits-container\">\r\n                                            <div>Benefits may be recalled by the cruise line at any time. Please contact the cruise line to verify availability before offering them to your clients. Combinability restrictions may also apply, please see the Booking Instructions for information.</div>\r\n                                            <div v-for=\"(hqGroup, index) in sailing.benefitsHQGroups\" :key=\"index\">\r\n                                                <template v-if=\"hqGroup.benefits.length > 0\">\r\n                                                    <div v-if=\"hqGroup.visibilityCountries && isVStaff()\" class=\"text-danger mt-2\">Visible Only to {{ hqGroup.visibilityCountries }}</div>\r\n                                                    <cruise-benefit-component v-for=\"(ben, benIndex) in hqGroup.benefits\" :key=\"benIndex\" :benefit=\"ben\" :is-hosted-benefit=\"false\"></cruise-benefit-component>\r\n                                                </template>\r\n                                            </div>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n                            </div>\r\n                        </li>\r\n                        <li v-if=\"sailing.promotions.length\" id=\"tc-promotions\">\r\n                            <button class=\"tab-nav\" @click=\"showTab('promotions')\">Promotions</button>\r\n                            <div class=\"-container\">\r\n                                <h4 class=\"tab-title\">Promotions</h4>\r\n                                <promotions-component :product-type=\"ProductType.CRUISES\" :promotions=\"sailing.promotions\"></promotions-component>\r\n                            </div>\r\n                        </li>\r\n                        <li v-if=\"sailing.addOnDayTours.length || sailing.postPackages.length || sailing.prePackages.length\" id=\"tc-add-ons\">\r\n                            <button class=\"tab-nav\" @click=\"showTab('add-ons')\">Add-ons</button>\r\n                            <div class=\"-container\">\r\n                                <h4 class=\"tab-title\">Add-ons</h4>\r\n\r\n                                <div v-if=\"sailing.prePackages.length > 0\" class=\"mb-4\">\r\n                                    <h2 class=\"text--serif\">Pre-Packages</h2>\r\n                                    <div class=\"add-ons-box mt-2\">\r\n                                        <div class=\"-title-row\">\r\n                                            <div class=\"-location\" v-html=\"sailing.prePackages[0].location\"></div>\r\n                                            <div class=\"-toggle\"><button aria-label=\"Toggle Pre-Packages\" @click.prevent.stop=\"toggleAddOn('prepackages')\"><i id=\"add-on-toggle-prepackages\" class=\"icon-plus-circle-ut\"></i></button></div>\r\n                                        </div>\r\n                                        <div id=\"add-on-container-prepackages\" class=\"add-on-container\">\r\n                                            <add-on-tours-component v-for=\"(pkg, pkgIndex) in sailing.prePackages\" :key=\"pkgIndex\" :add-on=\"pkg\"></add-on-tours-component>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n\r\n                                <div v-if=\"sailing.addOnDayTours.length > 0\" class=\"mb-4\">\r\n                                    <h2 class=\"text--serif\">Shore Excursions</h2>\r\n                                    <div v-for=\"(segment, segmentIndex) in sailing.addOnDayTours\" :key=\"segmentIndex\" class=\"add-ons-box mt-2\">\r\n                                        <div class=\"-title-row\">\r\n                                            <div class=\"-location\">{{ segment.addOnDate }} <span class=\"d-none d-md-inline\">&mdash;</span><span class=\"d-md-none\"><br /></span> {{ segment.addOnLocation }}</div>\r\n                                            <div class=\"-toggle\"><button aria-label=\"Toggle Shore Excursions\" @click.prevent.stop=\"toggleAddOn('shore-excursion-' + segmentIndex)\"><i :id=\"'add-on-toggle-shore-excursion-' + segmentIndex\" class=\"icon-plus-circle-ut\"></i></button></div>\r\n                                        </div>\r\n                                        <div :id=\"'add-on-container-shore-excursion-' + segmentIndex\" class=\"add-on-container\">\r\n                                            <add-on-tours-component v-for=\"(pkg, pkgIndex) in segment.addOns\" :key=\"pkgIndex\" :add-on=\"pkg\"></add-on-tours-component>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n\r\n                                <div v-if=\"sailing.postPackages.length > 0\">\r\n                                    <h2 class=\"text--serif\">Post-Packages</h2>\r\n                                    <div class=\"add-ons-box mt-2\">\r\n                                        <div class=\"-title-row\">\r\n                                            <div class=\"-location\" v-html=\"sailing.postPackages[0].location\"></div>\r\n                                            <div class=\"-toggle\"><button aria-label=\"Toggle Post-Packages\" @click.prevent.stop=\"toggleAddOn('postpackages')\"><i id=\"add-on-toggle-postpackages\" class=\"icon-plus-circle-ut\"></i></button></div>\r\n                                        </div>\r\n                                        <div id=\"add-on-container-postpackages\" class=\"add-on-container\">\r\n                                            <add-on-tours-component v-for=\"(pkg, pkgIndex) in sailing.postPackages\" :key=\"pkgIndex\" :add-on=\"pkg\"></add-on-tours-component>\r\n                                        </div>\r\n                                    </div>\r\n                                </div>\r\n                            </div>\r\n                        </li>\r\n                    </ul>\r\n                </div>\r\n            </div>\r\n        </div>\r\n        <div v-else class=\"v-loading -no-overlay my-3\"></div>\r\n    </div>\r\n    <LogoSplash v-else />\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { Options } from \"@splidejs/vue-splide\";\r\n    import AddOnToursComponent from \"components/products/details/add-on-tours.vue\";\r\n    import CruiseBenefitComponent from \"components/products/details/cruise-benefit.vue\";\r\n    import ProductItineraryComponent from \"components/products/details/product-itinerary.vue\";\r\n    import PromotionsComponent from \"components/products/details/product-promotions.vue\";\r\n    import TrackSailingComponent from \"components/products/details/track-sailing.vue\";\r\n    import RecommendedAdvisorsComponent from \"components/advisor/recommended-advisors.vue\";\r\n    import CarouselSliderComponent from \"components/shared/carousel-slider.vue\";\r\n    import ImageGalleryComponent from \"components/shared/image-gallery.vue\";\r\n    import LogoSplash from \"components/shared/logo-splash.vue\";\r\n    import TopSplashComponent from \"components/shared/top-splash.vue\";\r\n    import { AddOnPackage, ProductDetailsCruiseResponse } from \"interfaces/responses/product-detail-responses\";\r\n    import { RecommendedAdvisorQuery } from \"interfaces/advisor\";\r\n    import { CruiseBenefit } from \"interfaces/cruise\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { GalleryItem } from \"interfaces/image\";\r\n    import { ProductDetailsSailing, ProductTopSplash, Promotion } from \"interfaces/product\";\r\n    import { AddOnDayTours, SortedBenefits, TourEvent } from \"interfaces/tour\";\r\n    import { getProductDetails } from \"services/api/products\";\r\n    import { isNetworkUser, isSupplier, isVStaff } from \"services/auth/user-info\";\r\n    import { sanitizeUserGeneratedContent, toggleSlideWithFade } from \"services/helpers/html\";\r\n    import { generateMediaServerImageUrl, hydrateImageGallery } from \"services/helpers/images\";\r\n    import { toastError } from \"services/helpers/toasts\";\r\n    import { isEmbeddedMode, isMobileScreenWidth } from \"services/layout/environment\";\r\n    import { setB2BDesktopCookie } from \"services/layout/metadata\";\r\n    import { translateToConsumerUrl } from \"services/transformers/products\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { enableHearts } from \"services/wanderlist\";\r\n    import { cobrandLink, getPlural, parseURLParameters, slugify } from \"virtuoso-shared-web-ui\";\r\n    import { capitalizeFirst } from \"virtuoso-shared-web-ui\";\r\n    import { nextTick, ref, useTemplateRef } from \"vue\";\r\n\r\n    let hasMultipleHostedBenefits = false;\r\n    let topPromoName = \"\"; // Referenced by GA\r\n\r\n    const props = defineProps({\r\n        productId: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        suppressRecommendedAdvisors: {\r\n            type: Boolean,\r\n            default: false\r\n        }\r\n    });\r\n    const carouselConfig: Options = {\r\n        adjustableHeight: true,\r\n        start: 0\r\n    };    \r\n    const cruiseTitle = ref(\"\");\r\n    const heartableUrl = ref(\"\");\r\n    const hasBenefits = ref(false);\r\n    const isBenefitsCarouselInitialized = ref(false);\r\n    const isOverviewReady = ref(false);\r\n    const isReady = ref(false);\r\n    const legacyLink = cobrandLink(`/cruises/sailings/${props.productId}`);\r\n    const legacyLinkLabel = (isSupplier()) ? \"For Partners: Update Your Profile\" : \"For Advisors: Advanced Results\";\r\n    const productDetailRef = useTemplateRef(\"product-detail\");\r\n    const qsParams = parseURLParameters();\r\n    const recommendedAdvisorQuery = ref<RecommendedAdvisorQuery>({} as RecommendedAdvisorQuery);\r\n    const sailing = ref<ProductDetailsSailing>({} as ProductDetailsSailing);\r\n    const tabNavContainerRef = useTemplateRef(\"tab-nav-container\");\r\n    const topSplashData = ref<ProductTopSplash>({} as ProductTopSplash); \r\n\r\n    function autoExpandAndToggle(item: string): void {\r\n        toggleAddOn(item);\r\n    }\r\n\r\n    function goToSailing(): void {\r\n        const elSelect = document.getElementById(\"itinerary-nav\") as HTMLSelectElement;\r\n        const newId = parseInt(elSelect.value, 10);\r\n        if (newId && newId !== props.productId) {\r\n            window.location.href = elSelect.options[elSelect.selectedIndex].dataset.url;\r\n        }\r\n    }\r\n\r\n    function handleLegacyLinkClick(): void {\r\n        setB2BDesktopCookie();\r\n        trackEvent(\"legacy_page_click\", {\r\n            affiliation: `${sailing.value.companyId}`,\r\n            item_id: `${props.productId}`,\r\n            item_name: sailing.value.companyName,\r\n            item_category: capitalizeFirst(ProductType.CRUISES.slice(0,-1))\r\n        });\r\n    }\r\n\r\n    function hasOnlyOnePostPackage(): boolean {\r\n        return (sailing.value.prePackages.length === 0 && sailing.value.addOnDayTours.length === 0 && sailing.value.postPackages.length === 1);\r\n    }\r\n\r\n    function hasOnlyOnePrePackage(): boolean {\r\n        return (sailing.value.prePackages.length === 1 && sailing.value.addOnDayTours.length === 0 && sailing.value.postPackages.length === 0);\r\n    }\r\n\r\n    function hasOnlyOneShoreExcursion(): boolean {\r\n        return (sailing.value.prePackages.length === 0 && sailing.value.addOnDayTours.length === 1 && sailing.value.postPackages.length === 0);\r\n    }\r\n\r\n    function hydratePrePostPackages(packages: AddOnPackage[]): TourEvent[] {\r\n        const hydratedPackages: TourEvent[] = [];\r\n        packages.forEach((pkg: AddOnPackage) => {\r\n            const tourEventId = parseInt(pkg.packageMasterEntityID, 10);\r\n            hydratedPackages.push({\r\n                companyName: pkg.supplierName,\r\n                description: sanitizeUserGeneratedContent(pkg.packageDescription),\r\n                eventDate: pkg.packageDateFormatted,\r\n                eventLength: pkg.packageLength,\r\n                id: tourEventId,\r\n                location: pkg.locationFormatted,\r\n                name: pkg.packageName,\r\n                thumbnailImageUrl: (pkg.imageLibraryItems && pkg.imageLibraryItems[0].url) ? generateMediaServerImageUrl(pkg.imageLibraryItems[0].url, { width: 230 }) : \"https://virtuoso-prod.dotcms.cloud/images/photo-coming-soon-148x110.png\",\r\n                url: cobrandLink(`/packages/${pkg.packageMasterEntityID}/${slugify(pkg.packageName)}`),\r\n                virtuosoHotel: (pkg.supportingPropertyName) ? pkg.supportingPropertyName : \"\"\r\n            });\r\n        });\r\n        return hydratedPackages;\r\n    }\r\n\r\n    function loadOverview(): void {\r\n        const sailingOverview = window.VIRTUOSO.sailingOverviewData;\r\n\r\n        if (sailingOverview && sailingOverview.CruiseName) {\r\n            loadSailing(); // Start the full load ASAP\r\n\r\n            const sailingCruiseLength = (sailingOverview.CruiseLength).replace(\"days\", \"Days\");\r\n            const thisSailing: ProductDetailsSailing = {\r\n                addOnDayTours: [],\r\n                benefitsHostedGroups: [],\r\n                benefitsHQGroups: [],\r\n                benefitsExclusive: [],\r\n                brandUrl: \"\",\r\n                companyId: (sailingOverview.SupplierId) ? parseInt(sailingOverview.SupplierId, 10) : 0,\r\n                companyName: sailingOverview.SupplierName || \"\",\r\n                cruiseDepartureCode: \"\",\r\n                cruiseId: sailingOverview.MasterCruiseId,\r\n                cruiseMapUrl: \"\",\r\n                cruiseName: `${sailingOverview.CruiseName} (${sailingCruiseLength.replace(\" \", \"&nbsp;\")})`,\r\n                cruisePorts: `${sailingOverview.DeparturePort} to ${sailingOverview.ArrivalPort}`,\r\n                cruiseTypeByShip: \"\",\r\n                featuredImageUrl: sailingOverview.FeaturedImage || \"https://virtuoso-prod.dotcms.cloud/images/image-not-available-results-266x200.png\",\r\n                featuredVideoUrl: sailingOverview.FeaturedVideoUrl,\r\n                id: props.productId,\r\n                isCruiseTour: false,\r\n                itinerary: [],\r\n                postPackages: [],\r\n                prePackages: [],\r\n                promotions: [],\r\n                sailings: [],\r\n                shipId: 0,\r\n                shipName: sailingOverview.ShipName,\r\n                shipUrl: \"\",\r\n                travelDates: `${sailingOverview.DepartureDate} to ${sailingOverview.ReturnDate}`,\r\n                travelLength: sailingCruiseLength,\r\n                whatIsIncluded: \"\",\r\n                whatIsNotIncluded: \"\"\r\n            };\r\n\r\n            heartableUrl.value = `https://www.virtuoso.com/travel/luxury-cruises/cruises/${sailingOverview.MasterCruiseId}/${slugify(sailingOverview.CruiseName)}`;\r\n\r\n            sailing.value = thisSailing;\r\n            cruiseTitle.value = `${sailingOverview.SupplierName} - ${sailingOverview.CruiseName} (${(sailingOverview.CruiseLength)})`;\r\n\r\n            topSplashData.value = {\r\n                companyName: thisSailing.companyName,\r\n                featuredImageCaption: thisSailing.featuredImageCaption,\r\n                featuredImageUrl: thisSailing.featuredImageUrl,\r\n                featuredVideoUrl: thisSailing.featuredVideoUrl,\r\n                productName: thisSailing.cruiseName,\r\n                productType: ProductType.CRUISES,\r\n                wanderlistId: heartableUrl.value,\r\n                wanderlistTitle: cruiseTitle.value\r\n            };\r\n\r\n            isOverviewReady.value = true;\r\n\r\n            nextTick(() => {\r\n                enableHearts(productDetailRef.value);\r\n            });\r\n        } else {\r\n            redirectOnError();\r\n        }\r\n    }\r\n\r\n    function loadSailing(): void {\r\n        getProductDetails(ProductType.CRUISES, props.productId).then((resultSailing: ProductDetailsCruiseResponse) => {\r\n\r\n            if (resultSailing && resultSailing.companyName && resultSailing.companyName) {\r\n\r\n                const cruiseLength = (resultSailing.cruiseLength).replace(\"days\", \"Days\");\r\n\r\n                const thisSailing: ProductDetailsSailing = {\r\n                    addOnDayTours: [],\r\n                    benefitsHostedGroups: [],\r\n                    benefitsHQGroups: [],\r\n                    benefitsExclusive: [],\r\n                    brandUrl: cobrandLink(`/travel/luxury-cruises/cruise-lines/${resultSailing.companyId}/${slugify(resultSailing.companyName)}`),\r\n                    companyId: resultSailing.companyId || 0,\r\n                    companyName: resultSailing.companyName || \"\",\r\n                    cruiseDepartureCode: resultSailing.cruiseDepartureCode || \"\",\r\n                    cruiseId: `${resultSailing.cruiseId}`,\r\n                    cruiseMapUrl: resultSailing.cruiseLargeImagePath || \"\",\r\n                    cruiseName: `${resultSailing.cruiseName} (${cruiseLength.replace(\" \", \"&nbsp;\")})`,\r\n                    cruisePorts: resultSailing.cruisePorts,\r\n                    cruiseTypeByShip: resultSailing.cruiseTypeByShip,\r\n                    featuredImageUrl: (sailing.value.featuredImageUrl) ? sailing.value.featuredImageUrl : \"https://virtuoso-prod.dotcms.cloud/images/image-not-available-results-266x200.png\", // fallback, replaced later\r\n                    featuredVideoUrl: (sailing.value.featuredVideoUrl) ? sailing.value.featuredVideoUrl : \"\",\r\n                    id: props.productId,\r\n                    isCruiseTour: (resultSailing.cruiseType && resultSailing.cruiseType.toLowerCase() === \"cruisetour\") ? true : false,\r\n                    itinerary: [],\r\n                    postPackages: [],\r\n                    prePackages: [],\r\n                    promotions: [],\r\n                    sailings: [],\r\n                    shipId: resultSailing.shipId,\r\n                    shipName: resultSailing.shipName || \"\",\r\n                    shipUrl: cobrandLink(`/travel/luxury-cruises/ships/${resultSailing.shipId}/${slugify(resultSailing.shipName)}`),\r\n                    travelDates: resultSailing.travelDates,\r\n                    travelLength: cruiseLength,\r\n                    whatIsIncluded: \"\",\r\n                    whatIsNotIncluded: \"\"\r\n                };\r\n\r\n                // What's (Not) Included\r\n                if (resultSailing.whatIsIncludedItems) {\r\n                    if (resultSailing.whatIsIncludedItems.length > 1) {\r\n                        let theItems = \"\";\r\n                        resultSailing.whatIsIncludedItems.forEach((item: string) => {\r\n                            theItems += `<li>${item}</li>`;\r\n                        });\r\n                        thisSailing.whatIsIncluded = `<ul>${theItems}</ul>`;\r\n                    } else {\r\n                        thisSailing.whatIsIncluded = sanitizeUserGeneratedContent(resultSailing.whatIsIncludedItems[0]);\r\n                    }\r\n                }\r\n\r\n                if (resultSailing.whatIsNotIncludedItems) {\r\n                    if (resultSailing.whatIsNotIncludedItems.length > 1) {\r\n                        let theItems = \"\";\r\n                        resultSailing.whatIsNotIncludedItems.forEach((item: string) => {\r\n                            theItems += `<li>${item}</li>`;\r\n                        });\r\n                        thisSailing.whatIsNotIncluded = `<ul>${theItems}</ul>`;\r\n                    } else {\r\n                        thisSailing.whatIsNotIncluded = sanitizeUserGeneratedContent(resultSailing.whatIsNotIncludedItems[0]);\r\n                    }\r\n                }\r\n\r\n                // Images -- first image is the featured image\r\n                let galleryImages: GalleryItem[] = [];\r\n                if (resultSailing.imageLibraryItems && resultSailing.imageLibraryItems.length) {\r\n                    galleryImages = hydrateImageGallery(resultSailing.imageLibraryItems);\r\n                    thisSailing.featuredImageUrl = galleryImages[0].image;\r\n                    thisSailing.featuredImageCaption = galleryImages[0].description;\r\n                }\r\n                thisSailing.galleryImages = galleryImages;\r\n\r\n\r\n                // Featured Video\r\n                if (resultSailing.supplierVideos && resultSailing.supplierVideos.length) {\r\n                    const featuredVideo = resultSailing.supplierVideos.find((video) => video.isFeaturedVideo);\r\n                    if (featuredVideo) {\r\n                        thisSailing.featuredVideoCaption = featuredVideo.title;\r\n                        if (featuredVideo.webContentURL !== sailing.value.featuredVideoUrl) {\r\n                            thisSailing.featuredVideoUrl = featuredVideo.webContentURL; // Don't \"overwrite\" the property if it is the same from the overview, worried about the video resetting\r\n                        }\r\n                    }\r\n                }\r\n\r\n\r\n                // Other sailings, if populated\r\n                if (resultSailing.sailings && resultSailing.sailings.length && resultSailing.sailings.length > 1) {\r\n                    resultSailing.sailings.forEach((sailing) => {\r\n                        if (sailing.masterEntityId && sailing.travelDates && sailing.detailUrl) {\r\n                            thisSailing.sailings.push({\r\n                                id: sailing.masterEntityId,\r\n                                travelDates: sailing.travelDates,\r\n                                url: cobrandLink(translateToConsumerUrl(sailing.detailUrl))\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n\r\n\r\n                // Itinerary\r\n                if (resultSailing.itineraryPoints && resultSailing.itineraryPoints.length) {\r\n                    let previousDay = 0;\r\n                    let currentDay = 0;\r\n                    resultSailing.itineraryPoints.forEach((it) => {\r\n                        currentDay = it.dayOfCruise;\r\n                        if (it.dayOfCruise !== previousDay) {\r\n                            thisSailing.itinerary.push({\r\n                                dateFormatted: it.segmentDate,\r\n                                description: \"\",\r\n                                itineraryDay: currentDay,\r\n                                stops: []\r\n                            });\r\n                            previousDay = currentDay;\r\n                        }\r\n                        if (thisSailing.itinerary[currentDay - 1]) { // Sanity check, just in case\r\n                            thisSailing.itinerary[currentDay - 1].stops.push({\r\n                                isOnLand: it.isOnLand,\r\n                                location: it.portName,\r\n                                timeArrive: (it.timeStart && it.timeStart !== \"00:00:00\") ? it.timeStart : \"\",\r\n                                timeDepart: (it.timeEnd && it.timeEnd !== \"00:00:00\") ? it.timeEnd : \"\"\r\n                            });\r\n                            if (it.description && it.description !== \"\") {\r\n                                thisSailing.itinerary[currentDay - 1].description = sanitizeUserGeneratedContent(it.description);\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n\r\n\r\n                // Benefits\r\n                if (resultSailing.cruiseBenefits && resultSailing.cruiseBenefits.benefitPrograms && resultSailing.cruiseBenefits.benefitPrograms.length) {\r\n                    resultSailing.cruiseBenefits.benefitPrograms.forEach((benefitGroup) => {\r\n                        if (benefitGroup.name === \"Exclusive Benefits\") {\r\n                            if (benefitGroup.benefitGroups && benefitGroup.benefitGroups.length) {\r\n                                benefitGroup.benefitGroups.forEach((ben) => {\r\n                                    if (ben.sortedBenefits && ben.sortedBenefits.length) {\r\n                                        thisSailing.benefitsExclusive = populateBenefits(ben.sortedBenefits);\r\n                                    }\r\n                                });\r\n                            }\r\n\r\n                        } else if (benefitGroup.name === \"HQ Group Benefits\" && isNetworkUser()) {\r\n                            if (benefitGroup.benefitGroups && benefitGroup.benefitGroups.length) {\r\n                                benefitGroup.benefitGroups.forEach((ben) => {\r\n                                    if (ben.sortedBenefits && ben.sortedBenefits.length) {\r\n                                        thisSailing.benefitsHQGroups.push({\r\n                                            benefits: populateBenefits(ben.sortedBenefits),\r\n                                            visibilityCountries: (ben.visibilityCountries || \"\").replace(\",\", \", \")\r\n                                        });\r\n                                    }\r\n                                });\r\n                            }\r\n\r\n                        } else if (benefitGroup.name === \"Virtuoso Voyages Hosted Benefits\") {\r\n                            if (benefitGroup.benefitGroups && benefitGroup.benefitGroups.length) {\r\n                                benefitGroup.benefitGroups.forEach((hbg) => {\r\n\r\n                                    const hostedBenefits: CruiseBenefit[] = [];\r\n                                    const forAllBenefits: CruiseBenefit[] = [];\r\n                                    const hostList: string[] = [];\r\n                                    const hostTitle = (hbg.hosts && hbg.hosts.length && hbg.hosts[0].hostedAssignedName !== \"To Be Assigned\") ? `Your&nbsp;Onboard&nbsp;Host${getPlural(hbg.hosts.length)}: ` : \"Host \";\r\n\r\n                                    if (hbg.sortedBenefits && hbg.sortedBenefits.length) {\r\n                                        hbg.sortedBenefits.forEach((hb) => {\r\n                                            const tempBenefit: CruiseBenefit =\r\n                                            {\r\n                                                activityLevel: hb.activityLevel || \"\",\r\n                                                ageAppropriateness: hb.ageAppropriateness || \"\",\r\n                                                availability: hb.displayedAvailability,\r\n                                                benefitDate: hb.benefitDate,\r\n                                                duration: hb.benefitDuration || \"\",\r\n                                                capacity: hb.capacity,\r\n                                                description: sanitizeUserGeneratedContent(hb.benefitDescription),\r\n                                                experiences: (hb.activityType) ? hb.activityType.slice(0, -1).replaceAll(\"|\", \" &bull; \") : \"\",\r\n                                                id: hb.benefitId,\r\n                                                isCarAndDriver: hb.isCarAndDriver,\r\n                                                isEvent: hb.isEvent,\r\n                                                isForAllGuests: hb.isForAllGuests,\r\n                                                isOption: hb.isOption,\r\n                                                location: hb.benefitLocation,\r\n                                                meals: hb.meals || \"\",\r\n                                                notice: (hb.notice && !hb.isForAllGuests) ? hb.notice : \"\", // Only display the notice for hosted chosen benefits\r\n                                                name: hb.benefitName,\r\n                                                thumbnailImageUrl: hb.thumbnailImageUrl,\r\n                                                waitlist: hb.displayedWaitlist || \"\"\r\n                                            };\r\n\r\n                                            if (hb.isForAllGuests) {\r\n                                                forAllBenefits.push(tempBenefit);\r\n                                            } else {\r\n                                                hostedBenefits.push(tempBenefit);\r\n                                            }\r\n\r\n                                            hasBenefits.value = true;\r\n                                        });\r\n                                    }\r\n\r\n                                    if (hbg.hosts && hbg.hosts.length) {\r\n                                        hbg.hosts.forEach((host) => {\r\n                                            if (host.hostedAssignedName) {\r\n                                                const memberName = (host.memberName) ? `, ${host.memberName}` : \"\";\r\n                                                hostList.push(host.hostedAssignedName + memberName);\r\n                                            }\r\n                                        });\r\n                                    }\r\n\r\n                                    thisSailing.benefitsHostedGroups.push({\r\n                                        dates: (hbg.benefitGroupStartDate !== hbg.benefitGroupEndDate) ? `${hbg.benefitGroupStartDate} - ${hbg.benefitGroupEndDate}` : hbg.benefitGroupStartDate,\r\n                                        forAllBenefits: forAllBenefits,\r\n                                        hostedBenefits: hostedBenefits,\r\n                                        hosts: hostTitle + hostList.join(\", \")\r\n                                    });\r\n\r\n                                    if (hostedBenefits.length > 1) { // This controls whether we initialize the carousel or not\r\n                                        hasMultipleHostedBenefits = true;\r\n                                    }\r\n                                });\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n\r\n\r\n                // Add Ons -- Day tours and pre/post packages\r\n                if (resultSailing.addOns && resultSailing.addOns.hasAddOns) {\r\n                    // Pre Packages\r\n                    if (resultSailing.addOns.prePackages && resultSailing.addOns.prePackages.length) {\r\n                        thisSailing.prePackages = hydratePrePostPackages(resultSailing.addOns.prePackages);\r\n                    }\r\n\r\n                    // Post Packages\r\n                    if (resultSailing.addOns.postPackages && resultSailing.addOns.postPackages.length) {\r\n                        thisSailing.postPackages = hydratePrePostPackages(resultSailing.addOns.postPackages);\r\n                    }\r\n\r\n                    // Day Tours\r\n                    if (resultSailing.addOns.addOnDayTours && resultSailing.addOns.addOnDayTours.length) {\r\n                        const dayTours: AddOnDayTours[] = [];\r\n                        const validDayTourSegments = resultSailing.addOns.addOnDayTours.filter((dayTour) => {\r\n                            return dayTour.addOnDate && dayTour.addOnLocation && dayTour.dayTours;\r\n                        });\r\n\r\n                        validDayTourSegments.forEach((segment, segmentIndex: number) => {\r\n                            if (segment.dayTours && segment.dayTours.length) {\r\n                                dayTours.push({ // First add the date+location segment\r\n                                    addOnDate: segment.addOnDate,\r\n                                    addOnLocation: segment.addOnLocation,\r\n                                    addOns: []\r\n                                });\r\n\r\n                                segment.dayTours.forEach((pkg) => { // Then loop through the tours for that segment and add them\r\n                                    dayTours[segmentIndex].addOns.push({\r\n                                        activityLevel: pkg.activityLevelList || \"\",\r\n                                        ageAppropriateness: pkg.ageAppropriatenessList || \"\",\r\n                                        companyName: pkg.supplierName,\r\n                                        description: sanitizeUserGeneratedContent(pkg.dayTourDescription),\r\n                                        eventDate: pkg.dayTourDateFormatted,\r\n                                        eventLength: pkg.dayTourLength,\r\n                                        experiences: (pkg.bulletedActivityTypes) ? pkg.bulletedActivityTypes : \"\",\r\n                                        id: parseInt(pkg.dayTourMasterEntityID, 10), // cast to MEID string to number id\r\n                                        location: pkg.locationFormatted,\r\n                                        meals: pkg.mealsFormatted || \"\",\r\n                                        name: pkg.dayTourName,\r\n                                        thumbnailImageUrl: pkg.thumbnailImageUrl || \"\",\r\n                                        url: cobrandLink(`/travel/luxury-tours/${pkg.dayTourMasterEntityID}/${slugify(pkg.dayTourName)}`),\r\n                                        virtuosoHotel: \"\"\r\n                                    });\r\n                                });\r\n                            }\r\n                        });\r\n                        thisSailing.addOnDayTours = dayTours;\r\n                    }\r\n                }\r\n\r\n\r\n                // Promotions -- Virtuoso Exclusive Promotions added first\r\n                if (resultSailing.promotions && resultSailing.promotions.length) {\r\n                    const visiblePromotions: Promotion[] = [];\r\n                    resultSailing.promotions.forEach((promo) => {\r\n                        if (!promo.isAdvisorIncentive && !promo.incentiveTypeCode) {\r\n                            visiblePromotions.push({\r\n                                description: promo.description || \"\",\r\n                                endDateMS: (promo.travelEndDate) ? new Date(promo.travelEndDate).getTime() : 0,\r\n                                formattedTravelDates: promo.formattedTravelDates || \"\",\r\n                                isExclusive: false,\r\n                                name: promo.promotionName || \"\",\r\n                                promotionId: promo.masterEntityId,\r\n                                startDateMS: (promo.travelStartDate) ? new Date(promo.travelStartDate).getTime() : 0,\r\n                                url: (promo.masterEntityId) ? cobrandLink(`/promotions/${promo.masterEntityId}/${slugify(promo.promotionName)}`) : \"\"\r\n                            });\r\n                        }\r\n                    });\r\n\r\n                    thisSailing.promotions = visiblePromotions;\r\n                    topPromoName = (thisSailing.promotions.length) ? thisSailing.promotions[0].name : \"\";\r\n                }\r\n\r\n\r\n                sailing.value = thisSailing;\r\n                topSplashData.value.promotion = thisSailing.promotions[0] ?? topSplashData.value.promotion; // Update for promos\r\n\r\n                // Recommended Advisors\r\n                recommendedAdvisorQuery.value = {\r\n                    Id: thisSailing.id,\r\n                    InterestType: thisSailing.cruiseTypeByShip,\r\n                    ProductLocationCountry: \"\",\r\n                    ProductPois: \"\",\r\n                    ProductTypeName: \"Cruise\"\r\n                } as RecommendedAdvisorQuery;\r\n\r\n\r\n                isOverviewReady.value = true;\r\n                isReady.value = true;\r\n                \r\n                nextTick(() => {\r\n                    // Onload Tab support\r\n                    showThenJumpToTab();\r\n                    enableHearts(productDetailRef.value);\r\n\r\n\r\n                    if (hasOnlyOnePostPackage()) {\r\n                        autoExpandAndToggle(\"postpackages\");\r\n                    }\r\n\r\n                    if (hasOnlyOnePrePackage()) {\r\n                        autoExpandAndToggle(\"prepackages\");\r\n                    }\r\n\r\n                    if (hasOnlyOneShoreExcursion()) {\r\n                        autoExpandAndToggle(\"shore-excursion-0\");\r\n                    }\r\n                });\r\n\r\n            } else {\r\n                redirectOnError();\r\n            }\r\n        }, () => redirectOnError());\r\n    }\r\n    \r\n    function populateBenefits(rawBenefits: SortedBenefits[]): CruiseBenefit[] {\r\n\r\n        let benefitGroup: CruiseBenefit[] = [];\r\n        rawBenefits.forEach((eb) => {\r\n            benefitGroup.push({\r\n                description: sanitizeUserGeneratedContent(eb.benefitDescription),\r\n                id: eb.benefitId,\r\n                isCarAndDriver: eb.isCarAndDriver,\r\n                isEvent: eb.isEvent,\r\n                isForAllGuests: eb.isForAllGuests,\r\n                isOption: eb.isOption,\r\n                name: eb.benefitName,\r\n                notice: \"\", // Never display the notice for Exclusive benefits\r\n                thumbnailImageUrl: eb.thumbnailImageUrl\r\n            });\r\n            hasBenefits.value = true;\r\n        });\r\n        return benefitGroup;\r\n    }\r\n\r\n    function redirectOnError(): void {\r\n        toastError(\"Error retrieving data\");\r\n        setTimeout(() => {\r\n            location.href = cobrandLink(`/travel/luxury-cruises`);\r\n        }, 3000);\r\n    }\r\n\r\n    function setRecommendedAdvisorIds(advisor1MEID?: number, advisor2MEID?: number): void {\r\n        // get cruise index key in sessionStorage\r\n        const getVirtuosoCruiseSearchIndexValue = sessionStorage.getItem(`VirtuosoCruiseSearchIndex_${props.productId}`);\r\n\r\n        if (getVirtuosoCruiseSearchIndexValue) {\r\n            // then delete cruise index key in sessionStorage\r\n            sessionStorage.removeItem(`VirtuosoCruiseSearchIndex_${props.productId}`);\r\n        }\r\n        const cruise: ProductDetailsSailing = sailing.value;\r\n\r\n        trackEvent(\"view_item\", {\r\n            ...((getVirtuosoCruiseSearchIndexValue) && { index: parseInt(getVirtuosoCruiseSearchIndexValue, 10) }), // should add index with value if session key existed\r\n            item_id: `${props.productId}`,\r\n            item_name: cruise.companyName,\r\n            coupon: (cruise.promotions.length >= 1) ? \"Promotion Available\" : \"\",\r\n            item_category: \"Cruise\",\r\n            item_category2: `${cruise.shipName}`,\r\n            item_category3: cruise.travelLength,\r\n            item_category4: (advisor1MEID) ? `${advisor1MEID}` : \"\",\r\n            item_category5: (advisor2MEID) ? `${advisor2MEID}` : \"\"\r\n        });\r\n    }\r\n\r\n    function scrollToTabResponsive(tabName = \"\"): void {\r\n        if (isMobileScreenWidth()) {\r\n            return (tabName) ? document.getElementById(`tc-${tabName}`)?.scrollIntoView()\r\n                : document.querySelector(\".tab-content .-active\")?.scrollIntoView({ block: \"start\" });\r\n        }\r\n        tabNavContainerRef.value.scrollIntoView();\r\n    }\r\n\r\n    function showTab(tabName: string, preventJump = false, fromTopLink = false): void {\r\n        document.querySelectorAll(\".tab-nav-container .-active, .tab-content .-active\").forEach((el) => el.classList.remove(\"-active\"));\r\n        document.querySelectorAll(`#tab-${tabName}, #tc-${tabName}`).forEach((el) => el.classList.add(\"-active\"));\r\n\r\n        if (!preventJump) {\r\n            scrollToTabResponsive(tabName);\r\n        }\r\n\r\n        if (tabName === \"benefits\") {\r\n            if (hasMultipleHostedBenefits && !isBenefitsCarouselInitialized.value) {                        \r\n                isBenefitsCarouselInitialized.value = true;\r\n            }\r\n        }\r\n\r\n        if (fromTopLink) {\r\n\r\n            trackEvent(\"view_promotion\", {\r\n                item_id: `${sailing.value.promotions[0].promotionId}`,\r\n                item_name: topPromoName,\r\n                item_category: \"Promotion\",\r\n                item_variant: \"Cruise\",\r\n                item_category2: \"Promo Visibility: All\",\r\n                affiliation: `${props.productId}`\r\n            });\r\n        }\r\n\r\n    }\r\n\r\n    function showThenJumpToTab(): void {\r\n\r\n        const qsTabLabel = qsParams[\"tab\"];\r\n\r\n        nextTick(() => { // Tab Show then Scroll\r\n            // Show        \r\n            showTab(\"itinerary\", true); // default first tab\r\n\r\n            if (qsTabLabel && document.getElementById(`tc-${qsTabLabel}`)) { // check qsParam tab exists\r\n                showTab(qsTabLabel, true);\r\n            }\r\n            // Show Promo Manual Tab\r\n            if (qsParams.promotions === \"1\") { // If the manually added ?promotions=1 query string variable is present, scroll to the promotions section on load\r\n                const qsPromoTabName = (sailing.value.promotions.length) ? \"promotions\" : \"itinerary\";\r\n                showTab(qsPromoTabName, true);\r\n            }\r\n\r\n            // Default Scroll\r\n            if ((\"tab\" in qsParams) || (\"promotions\" in qsParams)) {\r\n                scrollToTabResponsive();\r\n            }\r\n        });\r\n    }\r\n\r\n    function toggleAddOn(id: string): void {\r\n        const btn = document.getElementById(`add-on-toggle-${id}`);\r\n        const container = document.getElementById(`add-on-container-${id}`);\r\n\r\n\r\n        btn.classList.toggle(\"icon-plus-circle-ut\");\r\n        btn.classList.toggle(\"icon-minus-circle-ut\");\r\n        toggleSlideWithFade(container, 500);\r\n    }\r\n\r\n    loadOverview(); // Immediately load the summary\r\n</script>\r\n","<template>\r\n    <div class=\"slab product-features mt-6\">\r\n        <div class=\"container\">\r\n            <h2 class=\"text--serif\">At the Hotel</h2>\r\n            <template v-for=\"hotelFeatureKey in Object.keys(hotelFeatures)\">\r\n                <div v-if=\"hotelFeatures[hotelFeatureKey as keyof ProductDetailHotelFeatures].length\" :key=\"hotelFeatureKey\" class=\"-category\">\r\n                    <h4>{{ hotelFeatureCategoryMap.get(hotelFeatureKey) }}</h4>\r\n                    <ul>\r\n                        <li v-for=\"feature in hotelFeatures[hotelFeatureKey as keyof ProductDetailHotelFeatures]\" :key=\"feature\">\r\n                            <i :class=\"hotelFeatureIconMap.get(`${hotelFeatureKey}-${feature}`) || 'icon-check-ut'\"></i>\r\n                            {{ feature }}\r\n                        </li>\r\n                    </ul>\r\n                </div>\r\n            </template>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { ProductDetailHotelFeatures } from \"interfaces/responses/product-detail-responses\";\r\n    import { PropType } from \"vue\";\r\n\r\n    defineProps({\r\n        hotelFeatures: {\r\n            type: Object as PropType<ProductDetailHotelFeatures>,\r\n            default: () => ({})\r\n        }\r\n    });\r\n\r\n    const hotelFeatureCategoryMap = new Map<string, string>([\r\n        [\"features\"     , \"Features\"    ],\r\n        [\"inYourRoom\"   , \"In Your Room\"],\r\n        [\"recreation\"   , \"Recreation\"  ],\r\n        [\"services\"     , \"Services\"    ]\r\n    ]);\r\n\r\n    const hotelFeatureIconMap = new Map<string, string>([\r\n        [\"features-24-hour Security\"               , \"icon-lock\"            ],\r\n        [\"features-Adults Only\"                    , \"icon-adult\"           ],\r\n        [\"features-Air Conditioning\"               , \"icon-air-conditioner\" ],\r\n        [\"features-All-inclusive\"                  , \"icon-all-inclusive\"   ],\r\n        [\"features-Banquet Facilities\"             , \"icon-banquet\"         ],\r\n        [\"features-Business Center\"                , \"icon-printer\"         ],\r\n        [\"features-Casino\"                         , \"icon-coins\"           ],\r\n        [\"features-Children's Programs\"            , \"icon-children\"        ],\r\n        [\"features-Club Floor\"                     , \"icon-disco\"           ],\r\n        [\"features-Complimentary Parking\"          , \"icon-parking\"         ],\r\n        [\"features-Conference Facilities\"          , \"icon-networking\"      ],\r\n        [\"features-Connecting Rooms\"               , \"icon-connected-rooms\" ],\r\n        [\"features-Culinary Program\"               , \"icon-culinary\"        ],\r\n        [\"features-Internet Access\"                , \"icon-connection\"      ],\r\n        [\"features-Library\"                        , \"icon-library\"         ],\r\n        [\"features-Lounge/Bar\"                     , \"icon-lounge\"          ],\r\n        [\"features-Meal Plans Available\"           , \"icon-meal-plans\"      ],\r\n        [\"features-Michelin Star Restaurant\"       , \"icon-michelin\"        ],\r\n        [\"features-Multi-lingual Staff\"            , \"icon-multi-lingual\"   ],\r\n        [\"features-Nightclub\"                      , \"icon-disco\"           ],\r\n        [\"features-Parking\"                        , \"icon-parking\"         ],\r\n        [\"features-Pet Friendly\"                   , \"icon-paw\"             ],\r\n        [\"features-Restaurant\"                     , \"icon-restaurant\"      ],\r\n        [\"features-Shopping\"                       , \"icon-shopping\"        ],\r\n        [\"features-Villas\"                         , \"icon-villa\"           ],\r\n        [\"features-Wheelchair Accessible\"          , \"icon-wheelchair\"      ],\r\n        [\"inYourRoom-Bathrobes\"                    , \"icon-bathrobe\"        ],\r\n        [\"inYourRoom-Butler Service\"               , \"icon-butler\"          ],\r\n        [\"inYourRoom-Complimentary Coffee/Tea\"     , \"icon-tea\"             ],\r\n        [\"inYourRoom-Complimentary Newspaper\"      , \"icon-newspaper\"       ],\r\n        [\"inYourRoom-Hair Dryer\"                   , \"icon-hair-dryer\"      ],\r\n        [\"inYourRoom-Iron/Ironing Board\"           , \"icon-iron\"            ],\r\n        [\"inYourRoom-Mini Bar\"                     , \"icon-mini-bar\"        ],\r\n        [\"inYourRoom-Safe\"                         , \"icon-safe\"            ],\r\n        [\"inYourRoom-Slippers\"                     , \"icon-slippers\"        ],\r\n        [\"recreation-Bicycle Rental\"               , \"icon-bicycle\"         ],\r\n        [\"recreation-Fitness Center\"               , \"icon-fitness\"         ],\r\n        [\"recreation-Golf\"                         , \"icon-golf\"            ],\r\n        [\"recreation-Horseback Riding\"             , \"icon-horseback-riding\"],\r\n        [\"recreation-Jacuzzi/Whirlpool\"            , \"icon-jacuzzi1\"        ],\r\n        [\"recreation-Pool\"                         , \"icon-pool\"            ],\r\n        [\"recreation-Sauna\"                        , \"icon-sauna\"           ],\r\n        [\"recreation-Skiing\"                       , \"icon-skiing\"          ],\r\n        [\"recreation-Snow Sports\"                  , \"icon-snow-sports\"     ],\r\n        [\"recreation-Spa\"                          , \"icon-spa\"             ],\r\n        [\"recreation-Tennis Courts\"                , \"icon-tennis\"          ],\r\n        [\"recreation-Water Sports\"                 , \"icon-water-sports\"    ],\r\n        [\"services-Babysitting Services\"           , \"icon-babysitting\"     ],\r\n        [\"services-Car Rental Desk\"                , \"icon-car\"             ],\r\n        [\"services-Complimentary Airport Transfers\", \"icon-shuttle\"         ],\r\n        [\"services-Concierge Desk\"                 , \"icon-concierge\"       ],\r\n        [\"services-Currency Exchange\"              , \"icon-exchange\"        ],\r\n        [\"services-Hearing Impaired Services\"      , \"icon-hearing-impaired\"],\r\n        [\"services-House Safe\"                     , \"icon-house-safe\"      ],\r\n        [\"services-Housekeeping -- Twice Daily\"    , \"icon-housekeeping\"    ],\r\n        [\"services-Laundry/Dry Cleaning/Pressing\"  , \"icon-laundry\"         ],\r\n        [\"services-Limousine Service\"              , \"icon-limo\"            ],\r\n        [\"services-Room Service\"                   , \"icon-room-service\"    ],\r\n        [\"services-Room Service 24-hours\"          , \"icon-room-service\"    ],\r\n        [\"services-Salon\"                          , \"icon-salon\"           ],\r\n        [\"services-Shoeshine Service\"              , \"icon-shoe\"            ],\r\n        [\"services-Turndown Service\"               , \"icon-turndown\"        ],\r\n        [\"services-Valet Parking\"                  , \"icon-valet\"           ],\r\n        [\"services-Wakeup Calls\"                   , \"icon-wakeup-call\"     ],\r\n        [\"services-Wedding Services\"               , \"icon-wedding\"         ]\r\n    ]);\r\n</script>\r\n","<template>\r\n    <ul v-if=\"rooms.length\" class=\"hotel-guest-rooms generic-cards -twocols -mobile-horizontal-scroll\" aria-label=\"room list\">\r\n        <li v-for=\"(room, index) in rooms\" :key=\"index\" class=\"guest-room-card\">\r\n            <div class=\"bg-white p-2 shadow-sm h-100\">\r\n                <h4 class=\"fw-bold\">{{ room.roomTypeName }}</h4>\r\n                <div class=\"d-flex gap-3 text-16 flex-column flex-md-row\">\r\n                    <div class=\"-room-description\" v-html=\"room.descriptionHtml\"></div>\r\n                    <div class=\"-room-features\">\r\n                        <ul aria-label=\"room feature list\">\r\n                            <li v-for=\"(feature, feature_idx) in getRoomFeatures(room.featureGroups)\" :key=\"feature_idx\" class=\"m-0 mw-100\">\r\n                                {{ feature }}\r\n                            </li>\r\n                        </ul>\r\n                        <button class=\"btn btn-sm btn-tertiary mt-2\" @click=\"(e) => handleViewMoreClick(e, index)\">\r\n                            View More\r\n                        </button>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </li>\r\n    </ul>\r\n\r\n    <ModalShell id=\"hotel-room-sidebar\" :open=\"showRoomSidebar\" modal-style=\"sidebar\" @close=\"showRoomSidebar=false\">\r\n        <div class=\"d-flex flex-column h-100\">\r\n            <div ref=\"sidebar-room-details\" class=\"p-5 text-16 overflow-auto\">\r\n                <h4 class=\"text-16 text-emphasis m-0\">{{ hotelName }}</h4>\r\n                <h4>{{ activeRoom.roomTypeName }}</h4>\r\n\r\n                <div class=\"py-3\" v-html=\"activeRoom.descriptionHtml\"></div>\r\n\r\n                <div>\r\n                    <template v-for=\"(featureGroup, fgIndex) in activeRoom.featureGroups\" :key=\"fgIndex\">\r\n                        <template v-if=\"featureGroup.features.length\">\r\n                            <div class=\"fw-bold mt-3\">{{ featureGroup.groupName }}</div>\r\n                            <ul class=\"room-feature-list d-flex flex-wrap\">\r\n                                <li v-for=\"(feature, fIndex) in featureGroup.features\" :key=\"fIndex\" class=\"mt-1\">{{ feature }}</li>\r\n                            </ul>\r\n                        </template>\r\n                    </template>\r\n                </div>\r\n            </div>\r\n            <div v-if=\"rooms.length > 1\" class=\"room-nav-buttons p-2 d-flex align-items-center w-100 mt-auto justify-content-between shadow-sm\">\r\n                <button class=\"btn btn-sm btn-tertiary d-flex align-items-center gap-1 flex-fill justify-content-center position-relative h-100\" @click=\"(e) => handleViewMoreClick(e, prevRoom.index)\">\r\n                    <i class=\"icon-angle-left text-16 position-absolute start-0 ps-2\"></i>\r\n                    <span class=\"ps-1\">{{ prevRoom.label }}</span>\r\n                </button>\r\n                <button class=\"btn btn-sm btn-tertiary d-flex align-items-center gap-1 flex-fill justify-content-center position-relative h-100\" @click=\"(e) => handleViewMoreClick(e, nextRoom.index)\">\r\n                    <span class=\"pe-1\">{{ nextRoom.label }}</span>\r\n                    <i class=\"icon-angle-right text-16 position-absolute end-0 pe-2\"></i>\r\n                </button>\r\n            </div>\r\n        </div>\r\n    </ModalShell>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import ModalShell from \"components/shared/modal-shell.vue\";\r\n    import { GuestRoom, GuestRoomFeatureGroup } from \"interfaces/responses/product-detail-responses\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { capitalizeFirst } from \"virtuoso-shared-web-ui\";\r\n    import { computed, PropType, ref, useTemplateRef } from \"vue\";\r\n\r\n\r\n    const props = defineProps({\r\n        hotelId: {\r\n            type: Number,\r\n            required: true\r\n        },\r\n        hotelName: {\r\n            type: String,\r\n            required: true\r\n        },\r\n        rooms: {\r\n            type: Array as PropType<GuestRoom[]>,\r\n            default: () => [] as GuestRoom[]\r\n        }\r\n    });\r\n\r\n    const showRoomSidebar = ref(false);\r\n    const activeItemIndex = ref(null);\r\n    const sideRoomDetailsRef = useTemplateRef(\"sidebar-room-details\");\r\n    const totalRooms = props.rooms.length;\r\n    \r\n    const activeRoom = computed(() => props.rooms[activeItemIndex.value]);\r\n\r\n    const nextRoom = computed(() => {\r\n        const targetIndex = (activeItemIndex.value < totalRooms -1) ? activeItemIndex.value + 1 : 0;\r\n\r\n        return {\r\n            label: props.rooms[targetIndex].roomTypeName,\r\n            index: targetIndex\r\n        };\r\n    });\r\n\r\n    const prevRoom = computed(() => {\r\n        const targetIndex = (activeItemIndex.value > 0) ? activeItemIndex.value - 1 : totalRooms - 1;\r\n\r\n        return {\r\n            label: props.rooms[targetIndex].roomTypeName,\r\n            index: targetIndex\r\n        };\r\n    });\r\n\r\n\r\n    function getRoomFeatures(groups: GuestRoomFeatureGroup[], max = 6) {\r\n        return groups.map((featureGroup) => featureGroup.features).flat().slice(0, max);\r\n    }\r\n\r\n    function handleViewMoreClick(event: Event, roomArrayIndex: number) {\r\n        (event.currentTarget as HTMLElement).blur();\r\n        activeItemIndex.value = roomArrayIndex;\r\n        showRoomSidebar.value = true;\r\n\r\n        sideRoomDetailsRef.value?.scrollTo({top: 0, behavior: \"smooth\"});\r\n\r\n        trackEvent(\"view_room_details\", {\r\n            item_id: props.hotelId.toString(),\r\n            item_name: props.hotelName,\r\n            item_category: capitalizeFirst(ProductType.HOTELS.slice(0,-1)),\r\n            item_variant: activeRoom.value.roomTypeName\r\n        });\r\n    }\r\n\r\n</script>\r\n","<template>\r\n    <div v-if=\"isReady\" ref=\"product-detail\" class=\"product-detail\">\r\n        <top-splash-component :top-splash-data=\"topSplashData\" @promo-click=\"showTab('promotions', false, true)\"></top-splash-component>\r\n        <div class=\"container mt-4\">\r\n            <div class=\"product-detail-overview\">\r\n                <div class=\"-info\">\r\n                    <h1 class=\"mb-3 weglot-exclude\" v-html=\"hotel.companyName\"></h1>\r\n                    <div v-if=\"hotel.location\" class=\"-location\" v-html=\"hotel.location\"></div>\r\n                    <div v-if=\"hotel.neighborhood\"><b>NEIGHBORHOOD:</b> {{ hotel.neighborhood }}</div>\r\n                    <div v-if=\"hotel.nearestAirport\"><b>NEAREST AIRPORT:</b> {{ hotel.nearestAirport }}</div>\r\n                    <div class=\"d-md-flex mt-0\">\r\n                        <div v-if=\"hotel.numberOfRooms\" class=\"me-md-3\"><b>SIZE:</b> {{ hotel.numberOfRooms }}</div>\r\n                        <div v-if=\"hotel.roomStyle\" class=\"me-md-3\"><b>ROOM STYLE:</b> {{ hotel.roomStyle }}</div>\r\n                        <div v-if=\"hotel.vibe\"><b>VIBE:</b> {{ hotel.vibe }}</div>\r\n                    </div>\r\n                    <hotel-experiences-component class=\"mt-3\" :experiences=\"hotel.experiences\"></hotel-experiences-component>\r\n                    <div class=\"-description mt-3\" v-html=\"hotel.bobDescription\"></div>\r\n                </div>\r\n                <div class=\"-gallery mt-5 mt-md-0 mb-6\">\r\n                    <image-gallery-component v-if=\"hotel.galleryImages && hotel.galleryImages.length\"\r\n                                             :gallery-data=\"hotel.galleryImages\"\r\n                                             :product-id=\"hotel.id.toString()\"\r\n                                             :product-name=\"hotel.companyName\"\r\n                                             :product-type=\"ProductType.HOTELS\"></image-gallery-component>\r\n                    <div v-if=\"hotel.tip\" class=\"advisor-tip mt-3 mb-0\">\r\n                        <h3>Insider Tip</h3>\r\n                        <div class=\"mt-2\" v-html=\"hotel.tip\"></div>\r\n                    </div>\r\n                    <recommended-advisors-component v-if=\"!suppressRecommendedAdvisors\" :advisor-query=\"recommendedAdvisorQuery\" :hide-cobranded-button=\"true\" :set-recommended-advisor-ids=\"setRecommendedAdvisorIds\" :product-type=\"ProductType.HOTELS\"></recommended-advisors-component>\r\n                    <a v-if=\"!isAdvisorOrVStaff && !isSupplier() && !isEmbeddedMode()\" id=\"b2blink-check-rates-availability\" class=\"btn btn-primary-emphasis btn-sm mt-3 d-block\" :href=\"bookingLink\" @click=\"handleLegacyLinkClick\">Check Rates and Availability</a>\r\n                    <a v-if=\"isSupplier() && !isEmbeddedMode()\" id=\"b2blink-update-your-profile\" class=\"btn btn-primary-emphasis btn-sm mt-3 d-none d-md-block\" :href=\"bookingLinkForAdvisors\" @click=\"handleLegacyLinkClick\">For Partners: Update Your Profile</a>\r\n                    <a v-if=\"isAdvisorOrVStaff && !isEmbeddedMode()\" id=\"b2blink-info-booking\" class=\"btn btn-primary-emphasis btn-sm mt-3 d-block\" :href=\"bookingLinkForAdvisors\" @click=\"handleLegacyLinkClick\">For Advisors: Info & Booking</a>\r\n                    <button class=\"wl-heartable -save-this mt-3\" data-wl-type=\"hotel\" :data-wl-id=\"productId\" :data-wl-title=\"hotel.companyName\" :data-wl-list-name=\"hotel.country\" aria-label=\"Save to Wanderlist\"></button>\r\n                </div>\r\n                <div v-if=\"hotel.amenities\" class=\"-amenities mt-4\">\r\n                    <h2 class=\"text--serif\">Virtuoso travelers receive:</h2>\r\n                    <div class=\"mt-2\" v-html=\"hotel.amenities\"></div>\r\n                    <div class=\"mt-3\">Many of these perks and amenities are only available when you book your stay through a Virtuoso travel advisor.</div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n        <hotel-features-component v-if=\"hotel.hotelFeatures\" :hotel-features=\"hotel.hotelFeatures\"></hotel-features-component>\r\n        <div class=\"container my-6\">\r\n            <MapView type=\"product\" :product-map-config=\"productMapConfig\" />\r\n        </div>\r\n        <div v-if=\"showTabBlock\" id=\"detail-tabs\"></div>\r\n        <div v-if=\"showTabBlock\" class=\"container d-none d-md-block\">\r\n            <ul ref=\"tab-nav-container\" class=\"tab-nav-container\">\r\n                <li v-if=\"hotel.guestRooms.length\" id=\"tab-rooms\"><button @click=\"showTab('rooms')\">Guest Rooms &amp; Suites</button></li>\r\n                <li v-if=\"hotel.promotions.length\" id=\"tab-promotions\"><button @click=\"showTab('promotions')\">Promotions &amp; Packages</button></li>\r\n                <li v-if=\"hotel.healthAndSafety\" id=\"tab-health\"><button @click=\"showTab('health')\">Health &amp; Safety Protocols</button></li>\r\n                <li v-if=\"hotel.reviewsCount > 0\" id=\"tab-reviews\"><button @click=\"showTab('reviews')\">Reviews &amp; Recommendations</button></li>\r\n                <li v-if=\"hasSustainabilityContent\" id=\"tab-sustainability\"><button @click=\"showTab('sustainability')\">Sustainability</button></li>\r\n            </ul>\r\n        </div>\r\n        <div v-if=\"showTabBlock\" class=\"slab -tab-slab\">\r\n            <div class=\"container\">\r\n                <ul class=\"tab-content\">\r\n                    <li v-if=\"hotel.guestRooms.length\" id=\"tc-rooms\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('rooms')\">Guest Rooms &amp; Suites</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Guest Rooms &amp; Suites</h4>\r\n                            <hotel-guest-rooms-component :hotel-name=\"hotel.companyName\" :hotel-id=\"hotel.id\" :rooms=\"hotel.guestRooms\"></hotel-guest-rooms-component>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"hotel.promotions.length\" id=\"tc-promotions\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('promotions')\">Promotions &amp; Packages</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"-title\">Promotions &amp; Packages</h4>\r\n                            <promotions-component :product-type=\"ProductType.HOTELS\" :promotions=\"hotel.promotions\"></promotions-component>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"hotel.healthAndSafety\" id=\"tc-health\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('health')\">Health &amp; Safety Protocols</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Health &amp; Safety Protocols</h4>\r\n                            <div v-html=\"hotel.healthAndSafety\"></div>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"hotel.reviewsCount > 0\" id=\"tc-reviews\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('reviews')\">Reviews &amp; Recommendations</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Reviews &amp; Recommendations</h4>\r\n                            <product-reviews-component :company-id=\"hotel.companyId\" :product-type=\"ProductType.HOTELS\" :reviews-data=\"reviewsData\"></product-reviews-component>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"hasSustainabilityContent\" id=\"tc-sustainability\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('sustainability')\">Sustainability</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Sustainability</h4>\r\n                            <template v-if=\"hotel.sustainability\">\r\n                                <h4 class=\"fw-bold\">Our Commitment</h4>\r\n                                <div class=\"mb-3\" v-html=\"hotel.sustainability\"></div>\r\n                            </template>\r\n                            <template v-if=\"hotel.sustainabilityCertifications.length > 0\">\r\n                                <h4 class=\"fw-bold\">Our Credentials</h4>\r\n                                <ul class=\"centered-list mb-3\">\r\n                                    <li v-for=\"(cert, index) in hotel.sustainabilityCertifications\" :key=\"index\"><a :href=\"cert.url\" target=\"_blank\" v-html=\"cert.text\"></a></li>\r\n                                </ul>\r\n                            </template>\r\n                            <template v-if=\"hotel.sustainabilityVideoUrl\">\r\n                                <video controls playsinline :src=\"hotel.sustainabilityVideoUrl\" width=\"100%\"></video>\r\n                            </template>\r\n                        </div>\r\n                    </li>\r\n                </ul>\r\n            </div>\r\n        </div>\r\n    </div>\r\n    <LogoSplash v-else />\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import HotelExperiencesComponent from \"components/products/details/hotel-experiences.vue\";\r\n    import HotelFeaturesComponent from \"components/products/details/hotel-features.vue\";\r\n    import HotelGuestRoomsComponent from \"components/products/details/hotel-guest-rooms.vue\";\r\n    import PromotionsComponent from \"components/products/details/product-promotions.vue\";\r\n    import ProductReviewsComponent from \"components/products/details/product-reviews.vue\";\r\n    import RecommendedAdvisorsComponent from \"components/advisor/recommended-advisors.vue\";\r\n    import ImageGalleryComponent from \"components/shared/image-gallery.vue\";\r\n    import LogoSplash from \"components/shared/logo-splash.vue\";\r\n    import MapView from \"components/shared/map-view.vue\";\r\n    import TopSplashComponent from \"components/shared/top-splash.vue\";\r\n    import { DotCMSProductDetailPageResponse } from \"interfaces/responses/dotcms-responses\";\r\n    import { ProductDetailsHotelResponse } from \"interfaces/responses/product-detail-responses\";\r\n    import { RecommendedAdvisorQuery } from \"interfaces/advisor\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { ProductDetailsHotel } from \"interfaces/hotel\";\r\n    import { GalleryItem } from \"interfaces/image\";\r\n    import { ProductTopSplash, Promotion } from \"interfaces/product\";\r\n    import { getCmsContent } from \"services/api/cms\";\r\n    import { getProductDetails } from \"services/api/products\";\r\n    import { isAdvisor, isSupplier, isVStaff } from \"services/auth/user-info\";\r\n    import { formatLocation } from \"services/helpers/destinations\";\r\n    import { hydrateImageGallery } from \"services/helpers/images\";\r\n    import { toastError } from \"services/helpers/toasts\";\r\n    import { isEmbeddedMode, isMobileScreenWidth } from \"services/layout/environment\";\r\n    import { renderMetadata, setB2BDesktopCookie } from \"services/layout/metadata\";\r\n    import { getSustainabilityCerts } from \"services/transformers/products\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { enableHearts } from \"services/wanderlist\";\r\n    import { cobrandLink, getPlural, parseURLParameters } from \"virtuoso-shared-web-ui\";\r\n    import { capitalizeFirst } from \"virtuoso-shared-web-ui\";\r\n    import { nextTick, ref, useTemplateRef } from \"vue\";\r\n\r\n    let topPromoName = \"\"; // Referenced by GA\r\n\r\n    const qsParams = parseURLParameters();\r\n\r\n    const props = defineProps({\r\n        productId: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        suppressRecommendedAdvisors: {\r\n            type: Boolean,\r\n            default: false\r\n        }\r\n    });\r\n\r\n    const bookingLink = ref(\"\");\r\n    const bookingLinkForAdvisors = ref(\"\");\r\n    const hotel = ref<ProductDetailsHotel>({} as ProductDetailsHotel);\r\n    const hasSustainabilityContent = ref(false);\r\n    const isAdvisorOrVStaff = (isAdvisor() || isVStaff());\r\n    const isReady = ref(false);\r\n    const productDetailRef = useTemplateRef(\"product-detail\");\r\n    const productMapConfig = ref({ \r\n        popupHtml: \"\",\r\n        longitude: 0,\r\n        latitude: 0\r\n    });\r\n    const recommendedAdvisorQuery = ref<RecommendedAdvisorQuery>({} as RecommendedAdvisorQuery);\r\n    const reviewsData = ref({});\r\n    const showTabBlock = ref(false);\r\n    const tabNavContainerRef = useTemplateRef(\"tab-nav-container\");\r\n    const topSplashData = ref<ProductTopSplash>({} as ProductTopSplash);\r\n\r\n    function handleLegacyLinkClick(): void {\r\n        setB2BDesktopCookie();\r\n        trackEvent(\"legacy_page_click\", {\r\n            affiliation: `${hotel.value.companyId}`,\r\n            item_id: `${props.productId}`,\r\n            item_name: hotel.value.companyName,\r\n            item_category: capitalizeFirst(ProductType.HOTELS.slice(0,-1))\r\n        });\r\n    }\r\n\r\n    function loadHotel(): void {\r\n        let resultHotel: ProductDetailsHotelResponse;\r\n        let cmsJSON = {} as DotCMSProductDetailPageResponse;\r\n\r\n        const hotelContentPromise = getProductDetails(ProductType.HOTELS, props.productId);\r\n        hotelContentPromise.then((hotelResponse: ProductDetailsHotelResponse) => {\r\n            resultHotel = hotelResponse;\r\n        }); // Reject is caught in the Promise.all below\r\n\r\n        const cmsContentPromise = getCmsContent<DotCMSProductDetailPageResponse[]>({\r\n            contentTypes: [\"ProductDetailPage\"],\r\n            depth: 1,\r\n            limit: 1,\r\n            queryClauses: [\r\n                `+(ProductDetailPage.productId:${props.productId})`\r\n            ]\r\n        });\r\n        cmsContentPromise.then((productJSON) => { // Most products won't have content in dotCMS\r\n            if (productJSON?.length) {\r\n                cmsJSON = productJSON[0];\r\n            }\r\n        }); // Reject is caught in the Promise.all below\r\n\r\n        Promise.all([hotelContentPromise, cmsContentPromise]).then(() => {\r\n\r\n            if (resultHotel && resultHotel.companyName) {\r\n\r\n                const hasAddress = (resultHotel.companyInfo && resultHotel.companyInfo.addresses && resultHotel.companyInfo.addresses.length);\r\n\r\n                const thisHotel: ProductDetailsHotel = {\r\n                    address1: (hasAddress && resultHotel.companyInfo.addresses[0].addressLine1) ? resultHotel.companyInfo.addresses[0].addressLine1 : \"\",\r\n                    address2: (hasAddress && resultHotel.companyInfo.addresses[0].addressLine2) ? resultHotel.companyInfo.addresses[0].addressLine2 : \"\",\r\n                    address3: (hasAddress && resultHotel.companyInfo.addresses[0].addressLine3) ? resultHotel.companyInfo.addresses[0].addressLine3 : \"\",\r\n                    amenities: resultHotel.virtuosoAmenitiesHtml,\r\n                    bobDescription: resultHotel.asSeenInTravelFolioDescription,\r\n                    companyId: resultHotel.companyId || 0, // Only used for retrieving reviews\r\n                    country: resultHotel.companyInfo.addresses[0].country,\r\n                    experiences: (resultHotel.hotelExperiences && resultHotel.hotelExperiences.length) ? resultHotel.hotelExperiences : [],\r\n                    featuredImageUrl: \"https://virtuoso-prod.dotcms.cloud/images/image-not-available-results-266x200.png\", // fallback, replaced later\r\n                    guestRooms: (resultHotel.guestRooms) ? resultHotel.guestRooms : [],\r\n                    healthAndSafety: (resultHotel.supplierHealthAndSafetyHtml) ? resultHotel.supplierHealthAndSafetyHtml : \"\",\r\n                    hotelFeatures: {\r\n                        features: (resultHotel.hotelFeatures.features && resultHotel.hotelFeatures.features.length) ? resultHotel.hotelFeatures.features : [],\r\n                        inYourRoom: (resultHotel.hotelFeatures.inYourRoom && resultHotel.hotelFeatures.inYourRoom.length) ? resultHotel.hotelFeatures.inYourRoom : [],\r\n                        recreation: (resultHotel.hotelFeatures.recreation && resultHotel.hotelFeatures.recreation.length) ? resultHotel.hotelFeatures.recreation : [],\r\n                        services: (resultHotel.hotelFeatures.services && resultHotel.hotelFeatures.services.length) ? resultHotel.hotelFeatures.services : []\r\n                    },\r\n                    id: props.productId,\r\n                    latitude: (resultHotel.latitude) ? resultHotel.latitude : 0,\r\n                    longitude: (resultHotel.longitude) ? resultHotel.longitude : 0,\r\n                    companyName: cmsJSON.title || resultHotel.companyName,\r\n                    neighborhood: (resultHotel.neighborhood) ? resultHotel.neighborhood : \"\",\r\n                    numberOfRooms: (resultHotel.numberOfRooms) ? `${resultHotel.numberOfRooms} room${getPlural(resultHotel.numberOfRooms)}` : \"\",\r\n                    promotions: [],\r\n                    roomStyle: (resultHotel.roomStyle) ? resultHotel.roomStyle : \"\",\r\n                    sustainability: (resultHotel.supplierSustainability) ? resultHotel.supplierSustainability : \"\",\r\n                    sustainabilityCertifications: getSustainabilityCerts(resultHotel.sustainabilityCertifications),\r\n                    sustainabilityVideoUrl: resultHotel.sustainabilityVideoUrl,\r\n                    tip: (resultHotel.asSeenInTravelFolioInTheKnow) ? resultHotel.asSeenInTravelFolioInTheKnow : \"\",\r\n                    vibe: (resultHotel.hotelVibes) ? resultHotel.hotelVibes : \"\"\r\n                };\r\n\r\n                // Location\r\n                if (hasAddress) {\r\n                    thisHotel.location = formatLocation(resultHotel.companyInfo.addresses[0].city, resultHotel.companyInfo.addresses[0].state, resultHotel.companyInfo.addresses[0].country);\r\n                }\r\n\r\n                // Images -- first image is the featured image\r\n                let galleryImages: GalleryItem[] = [];\r\n                if (resultHotel.imageLibraryItems && resultHotel.imageLibraryItems.length) {\r\n                    galleryImages = hydrateImageGallery(resultHotel.imageLibraryItems);\r\n                    thisHotel.featuredImageUrl = galleryImages[0].image;\r\n                    thisHotel.featuredImageCaption = galleryImages[0].description;\r\n                }\r\n                thisHotel.galleryImages = galleryImages;\r\n\r\n                // Featured Video\r\n                if (resultHotel.supplierVideos && resultHotel.supplierVideos.length) {\r\n                    const featuredVideo = resultHotel.supplierVideos.find((video) => video.isFeaturedVideo);\r\n                    if (featuredVideo) {\r\n                        thisHotel.featuredVideoCaption = featuredVideo.title;\r\n                        thisHotel.featuredVideoUrl = featuredVideo.webContentURL;\r\n                    }\r\n                }\r\n\r\n                // Nearest airport\r\n                if (resultHotel.nearestAirportDescription) {\r\n                    thisHotel.nearestAirport = resultHotel.nearestAirportDescription;\r\n                    if (resultHotel.nearestAirportDistanceInMiles) {\r\n                        thisHotel.nearestAirport += ` - ${resultHotel.nearestAirportDistanceInMiles} mi/${Math.round(resultHotel.nearestAirportDistanceInMiles * 1.609)} km`;\r\n                    }\r\n                }\r\n\r\n                // Promotions -- Virtuoso Exclusive Promotions added first\r\n                const combinedPromotions: Promotion[] = [];\r\n                const sourcePromotionsExclusives = (resultHotel.virtuosoExclusivePromotions && resultHotel.virtuosoExclusivePromotions.length) ? resultHotel.virtuosoExclusivePromotions : [];\r\n                const sourcePromotionsNormal = (resultHotel.promotions && resultHotel.promotions.length) ? resultHotel.promotions : [];\r\n                [...sourcePromotionsExclusives, ...sourcePromotionsNormal].forEach((promo) => {\r\n                    if (!promo.isAdvisorIncentive && !promo.incentiveTypeCode) {\r\n                        combinedPromotions.push({\r\n                            description: promo.description || \"\",\r\n                            endDateMS: (promo.travelEndDate) ? new Date(promo.travelEndDate).getTime() : 0,\r\n                            formattedTravelDates: promo.formattedTravelDates || \"\",\r\n                            isExclusive: (promo.promotionType === \"Virtuoso Exclusive Hotel Offer\"),\r\n                            name: promo.promotionName || \"\",\r\n                            promotionId: promo.masterEntityId,\r\n                            startDateMS: (promo.travelStartDate) ? new Date(promo.travelStartDate).getTime() : 0,\r\n                            url: (promo.masterEntityId) ? cobrandLink(`/${(promo.promotionType === \"Virtuoso Exclusive Hotel Offer\") ? \"virtuosoexclusivepromotions\" : \"promotions\"}/${promo.masterEntityId}`) : \"\"\r\n                        });\r\n                    }\r\n                });\r\n\r\n                // Check for featured promotion and reorder the array if necessary\r\n                if (cmsJSON.featuredPromotionId && combinedPromotions.length > 1) {\r\n                    const featuredPromoIndex = combinedPromotions.findIndex((promo) => parseInt(cmsJSON.featuredPromotionId, 10) === promo.promotionId);\r\n                    if (featuredPromoIndex > 0) {\r\n                        const featuredItem = combinedPromotions.splice(featuredPromoIndex, 1);\r\n                        combinedPromotions.unshift(featuredItem[0]);\r\n                    }\r\n                }\r\n\r\n                thisHotel.promotions = combinedPromotions;\r\n                topPromoName = (thisHotel.promotions.length) ? thisHotel.promotions[0].name : \"\";\r\n                hasSustainabilityContent.value = !!(thisHotel.sustainability || thisHotel.sustainabilityCertifications.length || thisHotel.sustainabilityVideoUrl);\r\n\r\n\r\n                // Reviews metadata -- actual reviews are pulled in separate component\r\n                const reviewsObj = (resultHotel.reviewsInfoJson) ? JSON.parse(resultHotel.reviewsInfoJson) : {};\r\n                thisHotel.reviewsCount = (reviewsObj && reviewsObj.TotalActiveReviews) ? reviewsObj.TotalActiveReviews : 0;\r\n                thisHotel.reviewsPercent = (reviewsObj && reviewsObj.TotalRecommendedPercent) ? Math.round(reviewsObj.TotalRecommendedPercent) : 100;\r\n                if (thisHotel.reviewsCount > 0) {\r\n                    // passed to reviews component\r\n                    reviewsData.value = {\r\n                        percent: `<b>${thisHotel.reviewsPercent}% Recommended</b>`,\r\n                        count: `<b>${thisHotel.reviewsCount} Review${getPlural(thisHotel.reviewsCount)}</b>`\r\n                    };\r\n                }\r\n\r\n                // Build map popup HTML\r\n                let mapPopupHtml = `<h3>${thisHotel.companyName}</h3>`;\r\n                if (hasAddress) {\r\n                    mapPopupHtml += (thisHotel.address1) ? `${thisHotel.address1}<br>` : \"\";\r\n                    mapPopupHtml += (thisHotel.address2) ? `${thisHotel.address2}<br>` : \"\";\r\n                    mapPopupHtml += (thisHotel.address3) ? `${thisHotel.address3}<br>` : \"\";\r\n                    mapPopupHtml += (thisHotel.location) ? thisHotel.location : \"\";\r\n                }\r\n                productMapConfig.value = {\r\n                    popupHtml: mapPopupHtml,\r\n                    latitude: thisHotel.latitude,\r\n                    longitude: thisHotel.longitude\r\n                };\r\n\r\n                bookingLink.value = cobrandLink(`/hotels/${thisHotel.id}?flow=1`);\r\n                bookingLinkForAdvisors.value = cobrandLink(`/hotels/${thisHotel.id}`);\r\n                hotel.value = thisHotel;\r\n\r\n                topSplashData.value = {\r\n                    ...(thisHotel.promotions.length && { promotion: thisHotel.promotions[0] }), // set Promotion if it exists\r\n                    companyName: thisHotel.companyName,\r\n                    featuredImageCaption: thisHotel.featuredImageCaption,\r\n                    featuredImageUrl: thisHotel.featuredImageUrl,\r\n                    featuredVideoUrl: thisHotel.featuredVideoUrl,\r\n                    productName: thisHotel.companyName,\r\n                    productType: ProductType.HOTELS,\r\n                    wanderlistId: props.productId.toString(),\r\n                    wanderlistName: thisHotel.country\r\n                } as ProductTopSplash;\r\n\r\n                renderMetadata({\r\n                    description: thisHotel.bobDescription,\r\n                    title: thisHotel.companyName\r\n                });\r\n\r\n\r\n                // Recommended Advisors\r\n                recommendedAdvisorQuery.value = {\r\n                    Id: thisHotel.id,\r\n                    InterestType: \"\",\r\n                    ProductLocationCountry: (hasAddress) ? resultHotel.companyInfo.addresses[0].country : \"\",\r\n                    ProductPois: \"\",\r\n                    ProductTypeName: \"Hotel\"\r\n                } as RecommendedAdvisorQuery;\r\n\r\n                isReady.value = true;\r\n               \r\n\r\n\r\n                nextTick(() => {\r\n                    // Onload tab support for this hotel\r\n                    showThenJumpToTab();\r\n                    enableHearts(productDetailRef.value);\r\n                });\r\n\r\n            } else {\r\n                redirectOnError();\r\n            }\r\n        }, () => redirectOnError());\r\n    }\r\n\r\n    function redirectOnError(): void {\r\n        toastError(\"Error retrieving data\");\r\n        setTimeout(() => { location.href = cobrandLink(`/travel/luxury-hotels`); }, 3000);\r\n    }\r\n\r\n    function setRecommendedAdvisorIds(advisor1MEID?: number, advisor2MEID?: number): void {\r\n        // get hotel index key in sessionStorage\r\n        const getVirtuosoHotelSearchIndexValue = sessionStorage.getItem(`VirtuosoHotelSearchIndex_${props.productId}`);\r\n\r\n        if (getVirtuosoHotelSearchIndexValue) {\r\n            // then delete hotel index key in sessionStorage\r\n            sessionStorage.removeItem(`VirtuosoHotelSearchIndex_${props.productId}`);\r\n        }\r\n\r\n        trackEvent(\"view_item\", {\r\n            ...((getVirtuosoHotelSearchIndexValue) && { index: parseInt(getVirtuosoHotelSearchIndexValue, 10) }), // should add index with value if session key existed\r\n            item_id: `${props.productId}`,\r\n            item_name: hotel.value.companyName,\r\n            coupon: (hotel.value.promotions.length >= 1) ? \"Promotion Available\" : \"\",\r\n            item_category: \"Hotel\",\r\n            item_category2: `${hotel.value.reviewsCount}`,\r\n            item_category3: hotel.value.vibe,\r\n            item_category4: (advisor1MEID) ? `${advisor1MEID}` : \"\",\r\n            item_category5: (advisor2MEID) ? `${advisor2MEID}` : \"\",\r\n            item_variant: hotel.value.roomStyle\r\n        });\r\n    }\r\n\r\n    function scrollToTabResponsive(tabName = \"\"): void {\r\n        if (isMobileScreenWidth()) {\r\n            return (tabName) ? document.getElementById(`tc-${tabName}`)?.scrollIntoView()\r\n                : document.querySelector(\".tab-content .-active\")?.scrollIntoView({ block: \"start\" });\r\n        }\r\n        tabNavContainerRef.value.scrollIntoView();\r\n    }\r\n\r\n    function showTab(tabName: string, preventJump = false, fromTopLink = false): void {\r\n        document.querySelectorAll(\".tab-nav-container .-active, .tab-content .-active\").forEach((el) => el.classList.remove(\"-active\"));\r\n        document.querySelectorAll(`#tab-${tabName}, #tc-${tabName}`).forEach((el) => el.classList.add(\"-active\"));\r\n\r\n        if (!preventJump) {\r\n            scrollToTabResponsive(tabName);\r\n        }\r\n\r\n        if (fromTopLink) {\r\n            trackEvent(\"view_promotion\", {\r\n                item_id: `${hotel.value.promotions[0].promotionId}`,\r\n                item_name: topPromoName,\r\n                item_category: \"Promotion\",\r\n                item_variant: (hotel.value.promotions[0].isExclusive) ? \"Virtuoso Exclusive Hotel Offer\" : \"Hotel/Resort\",\r\n                affiliation: `${props.productId}`\r\n            });\r\n        }\r\n    }\r\n\r\n    function showThenJumpToTab(): void {\r\n        const defaultTabName =\r\n            (hotel.value.guestRooms.length) ? \"rooms\" :\r\n            (hotel.value.promotions.length) ? \"promotions\" :\r\n            (hotel.value.healthAndSafety) ? \"health\" :\r\n            (hotel.value.reviewsCount > 0) ? \"reviews\" :\r\n            (hasSustainabilityContent.value) ? \"sustainability\" : \"\";\r\n\r\n        const qsTabLabel = qsParams[\"tab\"];\r\n\r\n        showTabBlock.value = (defaultTabName.length > 0);\r\n\r\n        nextTick(() => { // Tab Show then Scroll\r\n            // Show\r\n            if (defaultTabName) { // first tab\r\n                showTab(defaultTabName, true);\r\n            }\r\n            if (qsTabLabel && document.getElementById(`tc-${qsTabLabel}`)) { // check qsParam tab exists\r\n                showTab(qsTabLabel, true);\r\n            }\r\n            // Show Promo Manual Tab\r\n            if (qsParams.promotions === \"1\") { // If the manually added ?promotions=1 query string variable is present, scroll to the promotions section on load\r\n                const qsPromoTabName = (hotel.value.promotions.length) ? \"promotions\" : defaultTabName;\r\n                showTab(qsPromoTabName, true);\r\n            }\r\n            // Default Scroll\r\n            if ((\"tab\" in qsParams) || (\"promotions\" in qsParams)) {\r\n                scrollToTabResponsive();\r\n            }\r\n        });\r\n    }\r\n\r\n    loadHotel();\r\n    \r\n</script>\r\n","<template>\r\n    <div class=\"product-features -narrow mt-2\">\r\n        <ul>\r\n            <li v-for=\"experience in tourExperiences\" :key=\"experience\">\r\n                <i :class=\"tourExperienceIconMap.get(`tour-${experience}`) || 'icon-check-ut'\"></i>\r\n                {{ experience }}\r\n            </li>\r\n        </ul>\r\n    </div>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import { PropType } from \"vue\";\r\n\r\n    const tourExperienceIconMap = new Map([\r\n        [\"tour-Adventure\"                     , \"icon-h20-adventure\"      ],\r\n        [\"tour-Air & Helicopter Tours\"        , \"icon-Air\"                ],\r\n        [\"tour-Cruises & Water Tours\"         , \"icon-Cruises\"            ],\r\n        [\"tour-Culture, History & Arts\"       , \"icon-h20-local-immersion\"],\r\n        [\"tour-Family Vacations\"              , \"icon-Family\"             ],\r\n        [\"tour-Festivals & Events\"            , \"icon-festivals\"          ],\r\n        [\"tour-Food & Wine\"                   , \"icon-Food\"               ],\r\n        [\"tour-Islands & Beaches\"             , \"icon-h20-beach\"          ],\r\n        [\"tour-LGBTQ Travel\"                  , \"icon-lgbtq\"              ],\r\n        [\"tour-Rail Journeys\"                 , \"icon-Rail\"               ],\r\n        [\"tour-Romance, Weddings & Honeymoons\", \"icon-Romance\"            ],\r\n        [\"tour-Sightseeing\"                   , \"icon-Sightseeing\"        ],\r\n        [\"tour-Sports\"                        , \"icon-h20-golf\"           ],\r\n        [\"tour-Walking & Biking\"              , \"icon-Walking\"            ],\r\n        [\"tour-Wellness\"                      , \"icon-h20-wellness-ut\"    ],\r\n        [\"tour-Wheelchair Accessible\"         , \"icon-wheelchair\"         ],\r\n        [\"tour-Wildlife & Nature\"             , \"icon-Wildlife\"           ]\r\n    ]);\r\n\r\n\r\n    defineProps({\r\n        tourExperiences: {\r\n            type: Array as PropType<string[]>,\r\n            default: undefined\r\n        }\r\n    });\r\n</script>\r\n","<template>\r\n    <div v-if=\"isReady\" ref=\"product-detail\" class=\"product-detail\">\r\n        <top-splash-component :top-splash-data=\"topSplashData\" @promo-click=\"showTab('promotions', false, true)\"></top-splash-component>\r\n        <div class=\"container mt-4\">\r\n            <div class=\"product-detail-overview mb-6\">\r\n                <div>\r\n                    <h1 v-html=\"tour.tourName\"></h1>\r\n                    <div class=\"mt-1\">\r\n                        {{ tour.tourType }}\r\n                        <template v-if=\"tour.subType\">\r\n                            | {{ tour.subType }}\r\n                        </template>\r\n                    </div>\r\n\r\n                    <div class=\"mt-2 -description\">\r\n                        <div v-if=\"tour.childTours.length > 1\" class=\"mt-2\">\r\n                            Travel Dates<br />\r\n                            <template v-if=\"isEmbeddedMode()\">\r\n                                Ask your advisor about available travel dates\r\n                            </template>\r\n                            <label v-else class=\"select--styled\">\r\n                                <select id=\"itinerary-nav\" class=\"w-100\" aria-label=\"Select Travel Dates\" @change=\"goToTour()\">\r\n                                    <option v-for=\"(item, index) in tour.childTours\"\r\n                                            :key=\"index\"\r\n                                            :value=\"item.id\"\r\n                                            :selected=\"item.id === tour.id\"\r\n                                            :data-url=\"item.url\"\r\n                                            v-html=\"item.travelDates\"></option>\r\n                                </select>\r\n                            </label>\r\n                        </div>\r\n                        <template v-else>\r\n                            <b>{{ tour.travelDates }}</b>\r\n                            <br />\r\n                        </template>\r\n                        <b v-html=\"formattedLocation\"></b><br />\r\n                        <a v-if=\"tour.brandUrl && !isEmbeddedMode()\" class=\"weglot-exclude\" :href=\"tour.brandUrl\">\r\n                            <b v-html=\"tour.companyName\"></b>\r\n                        </a>\r\n                        <b v-else class=\"weglot-exclude\" v-html=\"tour.companyName\"></b>\r\n                    </div>\r\n\r\n                    <div v-if=\"isDayTour\" class=\"mt-2\">\r\n                        <div v-if=\"tour.meals\">Meals: <b v-html=\"tour.meals\"></b></div>\r\n                        <div v-if=\"tour.ageAppropriateness\" class=\"mt-1\">\r\n                            Recommended Ages: <b v-html=\"tour.ageAppropriateness\"></b>\r\n                        </div>\r\n                        <div v-if=\"tour.activityLevel\" class=\"mt-1\">\r\n                            Activity Level: <b v-html=\"tour.activityLevel\"></b>\r\n                            <b v-if=\"isWheelchairAccessible\">&bull; Wheelchair Accessible</b>\r\n                        </div>\r\n                    </div>\r\n\r\n                    <tour-experiences-component v-if=\"tour.experiences.length\"\r\n                                                :tour-experiences=\"tour.experiences\"></tour-experiences-component>\r\n\r\n                    <div v-if=\"tour.tourDescription\"\r\n                         class=\"mt-3 truncate-vertical truncate-15\"\r\n                         data-view-more-text=\"More details\"\r\n                         data-view-less-text=\"Fewer details\"\r\n                         v-html=\"tour.tourDescription\"></div>\r\n\r\n                    <h2 class=\"text--serif mt-3\">At a Glance</h2>\r\n\r\n                    <MapView v-if=\"routeMapConfig.routeMarkers.length\" type=\"route\" :route-map-config=\"routeMapConfig\" />\r\n\r\n                    <div v-if=\"tour.whatIsIncluded\" class=\"mt-2\">\r\n                        <div class=\"mb-1\"><b>Included</b></div>\r\n                        <div v-html=\"tour.whatIsIncluded\"></div>\r\n                    </div>\r\n\r\n                    <div v-if=\"tour.whatIsNotIncluded\" class=\"mt-2\">\r\n                        <div class=\"mb-1\"><b>Not Included</b></div>\r\n                        <div v-html=\"tour.whatIsNotIncluded\"></div>\r\n                    </div>\r\n                </div>\r\n                <div class=\"-gallery mt-5 mt-md-0 mb-6\">\r\n                    <image-gallery-component v-if=\"tour.galleryImages && tour.galleryImages.length\"\r\n                                             :gallery-data=\"tour.galleryImages\"\r\n                                             :product-id=\"tour.id.toString()\"\r\n                                             :product-name=\"tour.tourName\"\r\n                                             :product-type=\"catalogType\"></image-gallery-component>\r\n                    <recommended-advisors-component v-if=\"!suppressRecommendedAdvisors\"\r\n                                                    :advisor-query=\"recommendedAdvisorQuery\"\r\n                                                    :product-type=\"catalogType\"\r\n                                                    :set-recommended-advisor-ids=\"setRecommendedAdvisorIds\"></recommended-advisors-component>\r\n                    <a v-if=\"isNetworkUser() && !isEmbeddedMode()\"\r\n                       id=\"b2blink-legacy-link-label\"\r\n                       class=\"btn btn-primary-emphasis btn-sm d-block mt-3\"\r\n                       :href=\"legacyLink\"\r\n                       @click=\"handleLegacyLinkClick\">{{ legacyLinkLabel }}</a>\r\n                    <button class=\"wl-heartable -save-this mt-3\"\r\n                            data-wl-type=\"tour\"\r\n                            :data-wl-id=\"heartableUrl\"\r\n                            :data-wl-title=\"tour.tourName\"\r\n                            :data-wl-list-name=\"wanderlistTourName\"\r\n                            aria-label=\"Save to Wanderlist\"></button>\r\n                </div>\r\n            </div>\r\n        </div>\r\n        <div v-if=\"showTabBlock\" id=\"detail-tabs\"></div>\r\n        <div v-if=\"showTabBlock\" class=\"container d-none d-md-block\">\r\n            <ul ref=\"tabNavContainer\" class=\"tab-nav-container\">\r\n                <li v-if=\"tour.itinerary.length > 1\" id=\"tab-itinerary\">\r\n                    <button @click=\"showTab('itinerary')\">Itinerary</button>\r\n                </li>\r\n                <li v-if=\"tour.virtuosoBenefits\" id=\"tab-benefits\">\r\n                    <button @click=\"showTab('benefits')\">Virtuoso Benefits</button>\r\n                </li>\r\n                <li v-if=\"tour.promotions.length\" id=\"tab-promotions\">\r\n                    <button @click=\"showTab('promotions')\">Promotions</button>\r\n                </li>\r\n                <li v-if=\"tour.addOnDayTours.length\" id=\"tab-add-ons\">\r\n                    <button @click=\"showTab('add-ons')\">Add-ons</button>\r\n                </li>\r\n            </ul>\r\n        </div>\r\n        <div v-if=\"showTabBlock\" class=\"slab -tab-slab\">\r\n            <div class=\"container\">\r\n                <ul class=\"tab-content\">\r\n                    <li v-if=\"tour.itinerary.length > 1\" id=\"tc-itinerary\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('itinerary')\">\r\n                            Itinerary\r\n                        </button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Itinerary</h4>\r\n                            <product-itinerary-component :itinerary=\"tour.itinerary\"\r\n                                                         :product-type=\"catalogType\"\r\n                                                         :is-cruise-tour=\"false\"></product-itinerary-component>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"tour.virtuosoBenefits\" id=\"tc-benefits\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('benefits')\">\r\n                            Virtuoso Benefits\r\n                        </button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Virtuoso Benefits</h4>\r\n                            <h2 class=\"text--serif\">Exclusively for Virtuoso Guests</h2>\r\n                            <div class=\"mt-2\" v-html=\"tour.virtuosoBenefits\"></div>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"tour.promotions.length\" id=\"tc-promotions\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('promotions')\">\r\n                            Promotions\r\n                        </button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"-title\">Promotions</h4>\r\n                            <promotions-component :product-type=\"catalogType\" :promotions=\"tour.promotions\"></promotions-component>\r\n                        </div>\r\n                    </li>\r\n                    <li v-if=\"tour.addOnDayTours.length\" id=\"tc-add-ons\">\r\n                        <button class=\"tab-nav\" @click=\"showTab('add-ons')\">Add-ons</button>\r\n                        <div class=\"-container\">\r\n                            <h4 class=\"tab-title\">Add-ons</h4>\r\n                            <div class=\"mb-4\">\r\n                                <h2 class=\"text--serif\">Excursions</h2>\r\n                                <div v-for=\"(segment, segmentIndex) in tour.addOnDayTours\" :key=\"segmentIndex\" class=\"add-ons-box mt-2\">\r\n                                    <div class=\"-title-row\">\r\n                                        <div class=\"-location\">\r\n                                            {{ segment.addOnDate }}\r\n                                            <span class=\"d-none d-md-inline\">&mdash;</span><span class=\"d-md-none\"><br /></span>\r\n                                            {{ segment.addOnLocation }}\r\n                                        </div>\r\n                                        <div class=\"-toggle\">\r\n                                            <button @click.prevent.stop=\"toggleAddOn(segmentIndex)\">\r\n                                                <i :id=\"'add-on-toggle-shore-excursion-' + segmentIndex\" class=\"icon-plus-circle-ut\"></i>\r\n                                            </button>\r\n                                        </div>\r\n                                    </div>\r\n                                    <div :id=\"'add-on-container-shore-excursion-' + segmentIndex\" class=\"add-on-container\">\r\n                                        <add-on-tours-component v-for=\"(pkg, pkgIndex) in segment.addOns\" :key=\"pkgIndex\" :add-on=\"pkg\"></add-on-tours-component>\r\n                                    </div>\r\n                                </div>\r\n                            </div>\r\n                        </div>\r\n                    </li>\r\n                </ul>\r\n            </div>\r\n        </div>\r\n    </div>\r\n    <LogoSplash v-else />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import AddOnToursComponent from \"components/products/details/add-on-tours.vue\";\r\n    import ProductItineraryComponent from \"components/products/details/product-itinerary.vue\";\r\n    import PromotionsComponent from \"components/products/details/product-promotions.vue\";\r\n    import TourExperiencesComponent from \"components/products/details/tour-experiences.vue\";\r\n    import RecommendedAdvisorsComponent from \"components/advisor/recommended-advisors.vue\";\r\n    import ImageGalleryComponent from \"components/shared/image-gallery.vue\";\r\n    import LogoSplash from \"components/shared/logo-splash.vue\";\r\n    import MapView from \"components/shared/map-view.vue\";\r\n    import TopSplashComponent from \"components/shared/top-splash.vue\";\r\n    import { tourBrandSupplierTypesRestricted } from \"config/collections\";\r\n    import { ProductDetailsTourResponse } from \"interfaces/responses/product-detail-responses\";\r\n    import { RecommendedAdvisorQuery } from \"interfaces/advisor\";\r\n    import { ProductType, SupplierType } from \"interfaces/enums\";\r\n    import { GalleryItem } from \"interfaces/image\";\r\n    import { ProductDetailsTour, ProductTopSplash, Promotion } from \"interfaces/product\";\r\n    import { AddOnDayTours, DayTourPackage } from \"interfaces/tour\";\r\n    import { getProductDetails } from \"services/api/products\";\r\n    import { isNetworkUser, isSupplier } from \"services/auth/user-info\";\r\n    import { sanitizeUserGeneratedContent, toggleSlideWithFade } from \"services/helpers/html\";\r\n    import { hydrateImageGallery } from \"services/helpers/images\";\r\n    import { toastError } from \"services/helpers/toasts\";\r\n    import { applyVerticalTruncation } from \"services/helpers/truncation\";\r\n    import { isEmbeddedMode, isMobileScreenWidth } from \"services/layout/environment\";\r\n    import { setB2BDesktopCookie } from \"services/layout/metadata\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { enableHearts } from \"services/wanderlist\";\r\n    import { capitalizeFirst, cobrandLink, parseURLParameters, slugify } from \"virtuoso-shared-web-ui\";\r\n    import { nextTick, ref, useTemplateRef } from \"vue\";\r\n\r\n    let topPromoName = \"\"; // Referenced by GA\r\n\r\n    const qsParams = parseURLParameters();\r\n    const props = defineProps({\r\n        productId: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        suppressRecommendedAdvisors: {\r\n            type: Boolean,\r\n            default: false\r\n        }\r\n    });\r\n\r\n    const catalogType = ProductType.TOURS;\r\n    const heartableUrl = document.querySelector(\"link[rel='canonical']\")?.getAttribute(\"href\");\r\n    const isDayTour = ref(false);\r\n    const isReady = ref(false);\r\n    const isWheelchairAccessible = ref(false);\r\n    const formattedLocation = ref(\"\");\r\n    const legacyLink = cobrandLink(`/tours/${props.productId}`);\r\n    const legacyLinkLabel = (isSupplier()) ? \"For Partners: Update Your Profile\" : \"For Advisors: Advanced Results\";\r\n    const productDetailRef = useTemplateRef(\"product-detail\");\r\n    const recommendedAdvisorQuery = ref<RecommendedAdvisorQuery>({} as RecommendedAdvisorQuery);\r\n    const routeMapConfig = ref({ routeMarkers: [] });\r\n    const showTabBlock = ref(false);\r\n    const topSplashData = ref<ProductTopSplash>({} as ProductTopSplash);\r\n    const tour = ref<ProductDetailsTour>({} as ProductDetailsTour);\r\n    const wanderlistTourName = ref(\"\");\r\n    const tabNavContainerRef = useTemplateRef(\"tabNavContainer\");\r\n\r\n    function goToTour(): void {\r\n        const elSelect = document.getElementById(\"itinerary-nav\") as HTMLSelectElement;\r\n        const newId = parseInt(elSelect.value, 10);\r\n        if (newId && newId !== props.productId) {\r\n            window.location.href = elSelect.options[elSelect.selectedIndex].dataset.url;\r\n        }\r\n    }\r\n\r\n    function handleLegacyLinkClick(): void {\r\n        setB2BDesktopCookie();\r\n        trackEvent(\"legacy_page_click\", {\r\n            affiliation: `${tour.value.companyId}`,\r\n            item_id: `${props.productId}`,\r\n            item_name: tour.value.companyName,\r\n            item_category: capitalizeFirst(ProductType.TOURS.slice(0,-1))\r\n        });\r\n    }\r\n\r\n    function loadTour(): void {\r\n        getProductDetails(catalogType, props.productId).then((resultTour: ProductDetailsTourResponse) => {\r\n            if (resultTour && resultTour.companyName) {\r\n                const brandUrl = (tourBrandSupplierTypesRestricted.includes(resultTour.companyType as SupplierType)) ? cobrandLink(`/travel/luxury-tours/tour-operators/${resultTour.companyId}/${slugify(resultTour.companyName)}`) : \"\";\r\n\r\n                const thisTour: ProductDetailsTour = {\r\n                    addOnDayTours: [],\r\n                    companyId: resultTour.companyId || 0, // Only used for retrieving reviews\r\n                    brandUrl: brandUrl,\r\n                    childTours: [],\r\n                    experiences: resultTour.tourExperiences || [],\r\n                    featuredImageUrl: \"https://virtuoso-prod.dotcms.cloud/images/image-not-available-results-266x200.png\", // fallback, replaced later\r\n                    id: props.productId,\r\n                    itinerary: [],\r\n                    companyName: resultTour.companyName,\r\n                    promotions: [],\r\n                    activityLevel: resultTour.tourActivityLevels, // Day tours only?\r\n                    ageAppropriateness: resultTour.tourAgeAppropriateness,\r\n                    meals: resultTour.meals ? resultTour.meals.join(\", \") : \"\", // Day tours only?\r\n                    supplierType: resultTour.companyType as SupplierType,\r\n                    tourCategory: resultTour.tourCategory,\r\n                    tourDescription: (resultTour.tourDescription) ? sanitizeUserGeneratedContent(resultTour.tourDescription) : \"\",\r\n                    tourLength: resultTour.tourLength,\r\n                    tourName: `${resultTour.tourName} (${(resultTour.tourLength.trim()).replace(\" \", \"&nbsp;\").replace(\"days\", \"Days\").replace(\"hours\", \"Hours\")})`,\r\n                    tourNameWithoutLength: resultTour.tourName,\r\n                    tourType: resultTour.tourType,\r\n                    travelDates: resultTour.travelDates,\r\n                    virtuosoBenefits: resultTour.virtuosoBenefitsDesc || \"\",\r\n                    whatIsIncluded: \"\",\r\n                    whatIsNotIncluded: \"\"\r\n                };\r\n\r\n                isDayTour.value = (thisTour.tourType === \"Day Tour\");\r\n\r\n                isWheelchairAccessible.value = thisTour.experiences.includes(\"Wheelchair Accessible\");\r\n                formattedLocation.value = resultTour.embarkation;\r\n\r\n                if (resultTour.disembarkation && (!isDayTour.value || resultTour.embarkation !== resultTour.disembarkation)) {\r\n                    formattedLocation.value += ` to ${resultTour.disembarkation}`;\r\n                }\r\n\r\n\r\n                // What's (Not) Included\r\n                if (resultTour.whatIsIncludedItems && resultTour.whatIsIncludedItems.length) {\r\n                    thisTour.whatIsIncluded = (resultTour.whatIsIncludedItems.length > 1)\r\n                        ? `<ul>${resultTour.whatIsIncludedItems.map((item) => `<li>${item}</li>`).join(\"\")}</ul>`\r\n                        : sanitizeUserGeneratedContent(resultTour.whatIsIncludedItems[0]);\r\n                }\r\n\r\n                if (resultTour.whatIsNotIncludedItems && resultTour.whatIsNotIncludedItems.length) {\r\n                    thisTour.whatIsNotIncluded = (resultTour.whatIsNotIncludedItems.length > 1)\r\n                        ? `<ul>${resultTour.whatIsNotIncludedItems.map((item) => `<li>${item}</li>`).join(\"\")}</ul>`\r\n                        : sanitizeUserGeneratedContent(resultTour.whatIsNotIncludedItems[0]);\r\n                }\r\n\r\n                // Images -- first image is the featured image\r\n                let galleryImages: GalleryItem[] = [];\r\n                if (resultTour.imageLibraryItems && resultTour.imageLibraryItems.length) {\r\n                    galleryImages = hydrateImageGallery(resultTour.imageLibraryItems);\r\n                    thisTour.featuredImageUrl = galleryImages[0].image;\r\n                    thisTour.featuredImageCaption = galleryImages[0].description;\r\n                }\r\n                thisTour.galleryImages = galleryImages;\r\n\r\n                // Featured Video\r\n                if (resultTour.supplierVideos && resultTour.supplierVideos.length) {\r\n                    const featuredVideo = resultTour.supplierVideos.find((video) => video.isFeaturedVideo);\r\n                    if (featuredVideo) {\r\n                        thisTour.featuredVideoCaption = featuredVideo.title;\r\n                        thisTour.featuredVideoUrl = featuredVideo.webContentURL;\r\n                    }\r\n                }\r\n\r\n\r\n                // Child tours, if populated\r\n                if (resultTour.childProducts && resultTour.childProducts.length && resultTour.childProducts.length > 1) {\r\n                    resultTour.childProducts.forEach((childTour) => {\r\n                        if (childTour.masterEntityId) { // && childTour.travelDates\r\n                            thisTour.childTours.push({\r\n                                id: childTour.masterEntityId,\r\n                                travelDates: `${childTour.travelStartDate} - ${childTour.travelEndDate}`, // childTour.travelDates,\r\n                                url: cobrandLink(`/travel/luxury-tours/${childTour.masterEntityId}/${slugify(resultTour.tourName)}`)\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n\r\n                // Add \"Select Dates\" option at the beginning if this is a master tour\r\n                if (thisTour.childTours.length && !thisTour.childTours.some((childTour) => childTour.id === thisTour.id )) {\r\n                    thisTour.childTours.unshift({\r\n                        id: null,\r\n                        travelDates: \"Select Dates\",\r\n                        url: \"\"\r\n                    });\r\n                }\r\n\r\n\r\n                // Itinerary\r\n                if (resultTour.itineraryPoints && resultTour.itineraryPoints.length) {\r\n                    let countryFound = 0;\r\n                    let previousDay = 0;\r\n                    let currentDay = 0;\r\n                    let previousDataDay = 0; // The day number from the data -- tours sometimes have insane, inaccurate day numbers (e.g. 138, 139, 1)\r\n                    resultTour.itineraryPoints.forEach((it) => {\r\n                        if (it.dayOfTour > (previousDay + 1) || it.dayOfTour < previousDay) { // Bad data -- \"this\" day is more than one day ahead or behind of the last day\r\n                            currentDay = (it.dayOfTour === previousDataDay) ? currentDay : currentDay + 1;\r\n                        } else {\r\n                            currentDay = it.dayOfTour;\r\n                        }\r\n\r\n                        if (currentDay !== previousDay) {\r\n                            thisTour.itinerary.push({\r\n                                country: it.country,\r\n                                dateFormatted: (thisTour.tourType === \"Multi-Day Tour\" && thisTour.tourCategory === \"NoSpecificDeparture\") ? \"\" : it.segmentDate,\r\n                                description: \"\",\r\n                                hotelName: it.hotelName,\r\n                                itineraryDay: currentDay,\r\n                                meals: it.mealsFormatted || \"None\",\r\n                                stops: []\r\n                            });\r\n                            previousDay = currentDay;\r\n                        }\r\n\r\n                        if (thisTour.itinerary[currentDay - 1]) { // Sanity check, just in case\r\n                            thisTour.itinerary[currentDay - 1].stops.push({\r\n                                latitude: it.portLatitude || 0,\r\n                                location: it.portName || \"N/A\",\r\n                                longitude: it.portLongitude || 0\r\n                            });\r\n                        }\r\n\r\n                        if (it.portLatitude && it.portLongitude && it.portLatitude !== 0 && it.portLongitude !== 0) {\r\n                            routeMapConfig.value.routeMarkers.push({\r\n                                masterEntityId: 0,\r\n                                pinCoordinate: {\r\n                                    latitude: it.portLatitude,\r\n                                    longitude: it.portLongitude\r\n                                },\r\n                                pinType: 0,\r\n                                locationPath: \"\",\r\n                                title: it.portName\r\n                            });\r\n                        }\r\n\r\n                        if (it.stopDescription && it.stopDescription !== \"\") {\r\n                            if (thisTour.itinerary[currentDay - 1]) { // Sanity check, just in case\r\n                                thisTour.itinerary[currentDay - 1].description = sanitizeUserGeneratedContent(it.stopDescription);\r\n                            }\r\n                        }\r\n                        previousDataDay = it.dayOfTour;\r\n\r\n                        // Wanderlist, Default List Name\r\n                        if (it.country && countryFound === 0) {\r\n                            wanderlistTourName.value = it.country;\r\n                            countryFound++;\r\n                        } else if (countryFound === 1) { // -- Multi-Day Tour\r\n                            if (it.country && it.country !== wanderlistTourName.value) {\r\n                                wanderlistTourName.value += ` and ${it.country}`;\r\n                                countryFound++;\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n\r\n                // Add Ons -- Day tours\r\n                if (resultTour.addOns && resultTour.addOns.addOnDayTours && resultTour.addOns.addOnDayTours.length) {\r\n                    const dayTours: AddOnDayTours[] = [];\r\n                    resultTour.addOns.addOnDayTours.forEach((segment, segmentIndex: number) => {\r\n                        if (segment.dayTours && segment.dayTours.length) {\r\n                            dayTours.push({ // First add the date+location segment\r\n                                addOnDate: segment.addOnDate,\r\n                                addOnLocation: segment.addOnLocation,\r\n                                addOns: []\r\n                            });\r\n\r\n                            segment.dayTours.forEach((pkg: DayTourPackage) => { // Then loop through the tours for that segment and add them\r\n                                dayTours[segmentIndex].addOns.push({\r\n                                    activityLevel: pkg.activityLevelList || \"\",\r\n                                    ageAppropriateness: pkg.ageAppropriatenessList || \"\",\r\n                                    companyName: pkg.supplierName,\r\n                                    description: sanitizeUserGeneratedContent(pkg.dayTourDescription),\r\n                                    eventDate: pkg.dayTourDateFormatted,\r\n                                    eventLength: pkg.dayTourLength,\r\n                                    experiences: (pkg.bulletedActivityTypes) ? pkg.bulletedActivityTypes : \"\",\r\n                                    id: parseInt(pkg.dayTourMasterEntityID, 10),\r\n                                    location: pkg.locationFormatted,\r\n                                    meals: pkg.mealsFormatted || \"\",\r\n                                    name: pkg.dayTourName,\r\n                                    thumbnailImageUrl: pkg.thumbnailImageUrl || \"\",\r\n                                    url: cobrandLink(`/packages/${pkg.dayTourMasterEntityID}/${slugify(pkg.dayTourName)}`),\r\n                                    virtuosoHotel: \"\"\r\n                                });\r\n                            });\r\n                        }\r\n                    });\r\n                    thisTour.addOnDayTours = dayTours;\r\n                }\r\n\r\n\r\n                // Promotions -- Virtuoso Exclusive Promotions added first\r\n                if (resultTour.promotions && resultTour.promotions.length) {\r\n                    const visiblePromotions: Promotion[] = [];\r\n                    resultTour.promotions.forEach((promo) => {\r\n                        if (!promo.isAdvisorIncentive && !promo.incentiveTypeCode) {\r\n                            visiblePromotions.push({\r\n                                description: promo.description || \"\",\r\n                                endDateMS: (promo.travelEndDate) ? new Date(promo.travelEndDate).getTime() : 0,\r\n                                formattedTravelDates: promo.formattedTravelDates || \"\",\r\n                                isExclusive: false,\r\n                                name: promo.promotionName || \"\",\r\n                                promotionId: promo.masterEntityId,\r\n                                startDateMS: (promo.travelStartDate) ? new Date(promo.travelStartDate).getTime() : 0,\r\n                                url: (promo.masterEntityId) ? cobrandLink(`/promotions/${promo.masterEntityId}`) : \"\"\r\n                            });\r\n                        }\r\n                    });\r\n\r\n                    thisTour.promotions = visiblePromotions;\r\n                    topPromoName = (thisTour.promotions.length) ? thisTour.promotions[0].name : \"\";\r\n                }\r\n\r\n                tour.value = thisTour;\r\n\r\n                topSplashData.value = {\r\n                    companyName: thisTour.companyName,\r\n                    featuredImageCaption: thisTour.featuredImageCaption,\r\n                    featuredImageUrl: thisTour.featuredImageUrl,\r\n                    featuredVideoUrl: thisTour.featuredVideoUrl,\r\n                    productName: thisTour.tourName,\r\n                    productType: ProductType.TOURS,\r\n                    ...(thisTour.promotions[0] && { promotion: thisTour.promotions[0] }),\r\n                    wanderlistId: heartableUrl,\r\n                    wanderlistName: wanderlistTourName.value\r\n                } as ProductTopSplash;\r\n\r\n\r\n\r\n                // Recommended Advisors -- country of second day for multi-day tours, first day otherwise\r\n                let recommendedAdvisorCountry = \"\";\r\n                if (thisTour.itinerary.length) {\r\n                    if (isDayTour.value) {\r\n                        recommendedAdvisorCountry = thisTour.itinerary[0].country;\r\n                    } else {\r\n                        recommendedAdvisorCountry = (thisTour.itinerary.length > 1) ? thisTour.itinerary[1].country : thisTour.itinerary[0].country;\r\n                    }\r\n                }\r\n\r\n                recommendedAdvisorQuery.value = {\r\n                    Id: thisTour.id,\r\n                    InterestType: \"\",\r\n                    ProductLocationCountry: recommendedAdvisorCountry,\r\n                    ProductPois: \"\",\r\n                    ProductTypeName: \"Tour\"\r\n                } as RecommendedAdvisorQuery;\r\n\r\n                isReady.value = true;                \r\n\r\n                nextTick(() => {\r\n                    // Onload scroll to tab support\r\n                    showThenJumpToTab();\r\n                    if (thisTour.tourDescription) {\r\n                        applyVerticalTruncation(document.querySelectorAll(\".product-detail-overview .truncate-vertical\"));\r\n                    }\r\n\r\n                    enableHearts(productDetailRef.value);\r\n                });\r\n\r\n            } else {\r\n                redirectOnError();\r\n            }\r\n        }, () => redirectOnError());\r\n    }\r\n\r\n    function redirectOnError(): void {\r\n        toastError(\"Error retrieving data\");\r\n        setTimeout(() => {\r\n            location.href = cobrandLink(`/travel/luxury-tours`);\r\n        }, 3000);\r\n    }\r\n\r\n    function scrollToTabResponsive(tabName = \"\"): void {\r\n        if (isMobileScreenWidth()) {\r\n            return (tabName) ? document.getElementById(`tc-${tabName}`)?.scrollIntoView()\r\n                : document.querySelector(\".tab-content .-active\")?.scrollIntoView({ block: \"start\" });\r\n        }\r\n        tabNavContainerRef.value.scrollIntoView();\r\n    }\r\n\r\n    function setRecommendedAdvisorIds(advisor1MEID?: number, advisor2MEID?: number): void {\r\n\r\n        const getVirtuosoTourSearchIndexValue = sessionStorage.getItem(`VirtuosoTourSearchIndex_${props.productId}`);\r\n\r\n        if (getVirtuosoTourSearchIndexValue) {\r\n            sessionStorage.removeItem(`VirtuosoTourSearchIndex_${props.productId}`);\r\n        }\r\n\r\n        trackEvent(\"view_item\", {\r\n            ...((getVirtuosoTourSearchIndexValue) && { index: parseInt(getVirtuosoTourSearchIndexValue, 10) }), // should add index with value if session key existed\r\n            item_id: `${props.productId}`,\r\n            item_name: tour.value.tourNameWithoutLength,\r\n            coupon: (tour.value.promotions.length >= 1) ? \"Promotion Available\" : \"\",\r\n            item_category: \"Tour\",\r\n            item_category2: (tour.value.activityLevel) ? `${tour.value.activityLevel}` : \"\",\r\n            item_category3: tour.value.tourLength,\r\n            item_category4: (advisor1MEID) ? `${advisor1MEID}` : \"\",\r\n            item_category5: (advisor2MEID) ? `${advisor2MEID}` : \"\",\r\n            item_variant: `${tour.value.galleryImages.length} photos`\r\n        });\r\n    };\r\n\r\n    function showTab(tabName: string, preventJump = false, fromTopLink = false): void {\r\n        document.querySelectorAll(\".tab-nav-container .-active, .tab-content .-active\").forEach((el) => el.classList.remove(\"-active\"));\r\n        document.querySelectorAll(`#tab-${tabName}, #tc-${tabName}`).forEach((el) => el.classList.add(\"-active\"));\r\n\r\n        if (!preventJump) {\r\n            scrollToTabResponsive(tabName);\r\n        }\r\n\r\n        if (fromTopLink) {\r\n\r\n            trackEvent(\"view_promotion\", {\r\n                item_id: `${tour.value.promotions[0].promotionId}`,\r\n                item_name: topPromoName,\r\n                item_category: \"Promotion\",\r\n                item_variant: \"Tour\",\r\n                item_category2: \"Promo Visibility: All\",\r\n                affiliation: `${props.productId}`\r\n            });\r\n        }\r\n    }\r\n\r\n    function showThenJumpToTab(): void {\r\n        // Which bottom tab should be selected by default\r\n        const defaultTabName =\r\n            (tour.value.itinerary.length > 1) ? \"itinerary\" :\r\n            (tour.value.virtuosoBenefits) ? \"benefits\" :\r\n            (tour.value.promotions.length) ? \"promotions\" :\r\n            (tour.value.addOnDayTours.length) ? \"add-ons\" : \"\";\r\n\r\n        const qsTabLabel = qsParams[\"tab\"];\r\n\r\n        showTabBlock.value = (defaultTabName.length > 0);\r\n\r\n        nextTick(() => { // Tab Show then Scroll\r\n            // Show\r\n            if (defaultTabName) { // first tab\r\n                showTab(defaultTabName, true);\r\n            }\r\n            if (qsTabLabel && document.getElementById(`tc-${qsTabLabel}`)) { // check qsParam tab exists\r\n                showTab(qsTabLabel, true);\r\n            }\r\n            // Show Promo Manual Tab\r\n            if (qsParams.promotions === \"1\") { // If the manually added ?promotions=1 query string variable is present, scroll to the promotions section on load\r\n                const qsPromoTabName = (tour.value.promotions.length) ? \"promotions\" : defaultTabName;\r\n                showTab(qsPromoTabName, true);\r\n            }\r\n            // Default Scroll\r\n            if ((\"tab\" in qsParams) || (\"promotions\" in qsParams)) {\r\n                scrollToTabResponsive();\r\n            }\r\n        });\r\n\r\n    }\r\n\r\n    function toggleAddOn(id: number): void {\r\n        const btn = document.getElementById(`add-on-toggle-shore-excursion-${id}`);\r\n        const container = document.getElementById(`add-on-container-shore-excursion-${id}`);\r\n\r\n\r\n        btn.classList.toggle(\"icon-plus-circle-ut\");\r\n        btn.classList.toggle(\"icon-minus-circle-ut\");\r\n        toggleSlideWithFade(container, 500);  \r\n    }\r\n\r\n    loadTour();\r\n\r\n</script>\r\n","const desktopRootMargin = \"-214px\"; // -152 header height - 60 .-info height\r\nconst desktopRootMarginNearStickySubhead = \"-294px 0px 0px 0px\";\r\nconst mobileTopRootMargin = \"-122px\"; // -56 header height - 66 .-info height\r\n\r\n/**\r\n *\r\n * @param {HTMLElement} advisorHeader - selector for '.advisor-header'\r\n * @param {HTMLElement} stickyHeader - selector for '.sticky-advisor-header'\r\n * */\r\nfunction advisorHeaderNameObserver(advisorHeader: HTMLElement, stickyHeader: HTMLElement): void {\r\n    const config = {\r\n        rootMargin: `${(window.innerWidth >= 1200 ? desktopRootMargin : mobileTopRootMargin)} 0px 0px 0px`, // include nav bar height desktop & mobile\r\n        threshold: 0\r\n    };\r\n\r\n    const stickyObserver = new IntersectionObserver((entries: IntersectionObserverEntry[]) => {\r\n        entries.forEach((entry: IntersectionObserverEntry) => {\r\n            if (!entry.isIntersecting) { // not visible in viewport\r\n                advisorHeader.classList.add(\"-sticky\");\r\n                stickyHeader.classList.add(\"-sticky\");\r\n            } else {\r\n                stickyHeader.classList.remove(\"-sticky\");\r\n                advisorHeader.classList.remove(\"-sticky\");\r\n            }\r\n        });\r\n    }, config);\r\n\r\n    stickyObserver.observe(advisorHeader);\r\n}\r\n\r\n\r\n\r\nfunction setActiveTab(tab: HTMLElement): void {\r\n    if (!tab.classList.contains(\"-active\")) {\r\n        Array.from(tab.parentElement.children).forEach((tab) => tab.classList.remove(\"-active\"));\r\n        tab.classList.add(\"-active\");\r\n    }\r\n}\r\n\r\n\r\n\r\n/**\r\n * Sets up observers with different thresholds for each section\r\n */\r\nfunction observeSections(): void {\r\n    const aboutTab = document.getElementById(\"tab-about\");\r\n    const placesTab = document.getElementById(\"tab-places\");\r\n    const reviewsTab = document.getElementById(\"tab-reviews\");\r\n\r\n    // About section\r\n    const aboutObserver = new IntersectionObserver((entries) => {\r\n        entries.forEach((entry) => {\r\n            if (entry.isIntersecting) {\r\n                if (entry.intersectionRatio > 0.5) {\r\n                    setActiveTab(aboutTab);\r\n                } else { // This catches scrolling up when the threshold wasn't offscreen\r\n                    if (placesTab && placesTab.classList.contains(\"-active\")) {\r\n                        setActiveTab(aboutTab);\r\n                    }\r\n                }\r\n            }\r\n        });\r\n    }, { threshold: [0.5, 0.9], rootMargin: desktopRootMarginNearStickySubhead });\r\n    aboutObserver.observe(document.getElementById(\"about\"));\r\n\r\n    // Places Visited section\r\n    if (placesTab) {\r\n        const placesObserver = new IntersectionObserver((entries) => {\r\n            entries.forEach((entry) => {\r\n                if (entry.isIntersecting) {\r\n                    setActiveTab(placesTab);\r\n                }\r\n            });\r\n        }, { threshold: 0.5, rootMargin: desktopRootMarginNearStickySubhead });\r\n        placesObserver.observe(document.getElementById(\"places\"));\r\n    }\r\n\r\n    // Reviews & Recommendations section\r\n    if (reviewsTab) {\r\n        const reviewsObserver = new IntersectionObserver((entries) => {\r\n            entries.forEach((entry) => {\r\n                if (entry.isIntersecting) {\r\n                    if (entry.intersectionRatio > 0.25) {\r\n                        setActiveTab(reviewsTab);\r\n                    } else { // This catches scrolling down when the threshold wasn't off screen\r\n                        if (placesTab && placesTab.classList.contains(\"-active\")) {\r\n                            setActiveTab(reviewsTab);\r\n                        }\r\n                    }\r\n                }\r\n            });\r\n        }, { threshold: [0.25, 0.5], rootMargin: desktopRootMarginNearStickySubhead });\r\n        reviewsObserver.observe(document.getElementById(\"reviews\"));\r\n    }\r\n}\r\n\r\n\r\n/**\r\n * Runs Observers for the Advisor Detail Page\r\n * to implement sticky subhead and subnav highlighting\r\n */\r\nexport function initAdvisorSubhead(): void {\r\n    const advisorHeader = document.querySelector<HTMLElement>(\".advisor-header\");\r\n    const stickyHeader = document.querySelector<HTMLElement>(\".sticky-advisor-header\");\r\n    const sections = document.querySelectorAll(\"section\");\r\n\r\n    if (advisorHeader && stickyHeader && sections.length) {\r\n        // Sticky subhead\r\n        advisorHeaderNameObserver(advisorHeader, stickyHeader);\r\n\r\n        // Subnav highlighting\r\n        observeSections();\r\n    } else {\r\n        console.warn(\"Page sections not found, not applying observers\");\r\n    }\r\n}\r\n","<template>\r\n    <div v-if=\"isReady\" class=\"product-detail -advisor\">\r\n        <div class=\"container px-lg-0\">\r\n            <div class=\"advisor-header context-dark\">\r\n                <div class=\"-photo\">\r\n                    <img :src=\"advisor.featuredImageUrl\" :title=\"'Photo of ' + advisor.advisorName\" :alt=\"'Photo of ' + advisor.advisorName\">\r\n                </div>\r\n                <div class=\"-info\">\r\n                    <h1 class=\"mb-2\">{{ advisor.advisorFirstName }}<br />{{ advisor.advisorLastName }}</h1>\r\n                    <div class=\"-agency\">{{ advisor.icPrefix }}<a :href=\"advisor.agencyUrl\" v-html=\"advisor.companyName\"></a></div>\r\n                    <div class=\"-location\" v-html=\"advisor.location\"></div>\r\n                </div>\r\n                <div class=\"-links pt-2 pt-md-1\">\r\n                    <ul v-if=\"advisor.socialMedia.length\" class=\"list-unstyled list-inline mb-0\">\r\n                        <li v-for=\"(website, index) in advisor.socialMedia\" :key=\"index\"><a :href=\"website.siteUrl\" class=\"text-decoration-none\" target=\"_blank\" rel=\"external\"><i :class=\"socialMediaIconMap.get(website.siteName)\"></i></a></li>\r\n                    </ul>\r\n                </div>\r\n            </div>\r\n            <div class=\"sticky-advisor-header bg--white justify-content-sm-center\">\r\n                <div class=\"-info context-dark\">\r\n                    <div class=\"h2\" v-html=\"advisor.advisorName\"></div>\r\n                </div>\r\n                <div class=\"d-flex flex-row justify-content-lg-between align-items-center my-2\">\r\n                    <div class=\"d-none d-xl-block\">\r\n                        <ul class=\"tab-nav-container\">\r\n                            <li id=\"tab-about\" class=\"-active\"><button @click=\"jumpToSection('about')\">About Me</button></li>\r\n                            <li v-if=\"placesVisitedMapConfig.mapMarkers.length\" id=\"tab-places\"><button @click=\"jumpToSection('places')\">Places Visited</button></li>\r\n                            <li v-if=\"advisor.reviewsCount > 0\" id=\"tab-reviews\"><button @click=\"jumpToSection('reviews')\">Reviews &amp; Recommendations</button></li>\r\n                        </ul>\r\n                    </div>\r\n                    <div v-if=\"advisor.isAcceptingNewClients\" class=\"-contact-button\">\r\n                        <advisor-contact-button-component class=\"-inline\" :advisor=\"advisorContactButtonInfo(advisor)\" event-name=\"Advisor Detail\" button-style=\"sub-head\"></advisor-contact-button-component>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n            <section id=\"about\">\r\n                <div class=\"product-detail-overview\">\r\n                    <div class=\"-info\">\r\n                        <div v-if=\"advisor.companyLogoUrl\" class=\"d-block d-md-none my-3 text-center -logo\">\r\n                            <a :href=\"advisor.agencyUrl\"><img :src=\"advisor.companyLogoUrl\" :title=\"advisor.icPrefix + advisor.companyName\" :alt=\"advisor.icPrefix + advisor.companyName\" /></a>\r\n                        </div>\r\n                        <h2 class=\"text--serif fw-normal\">About Me</h2>\r\n                        <div class=\"-description mt-3\" v-html=\"advisor.description\"></div>\r\n                    </div>\r\n                    <div class=\"-gallery mt-5 mt-md-0 mb-6\">\r\n                        <div v-if=\"advisor.companyLogoUrl\" class=\"d-none d-md-block mb-4 text-center -logo\">\r\n                            <a :href=\"advisor.agencyUrl\"><img :src=\"advisor.companyLogoUrl\" :title=\"advisor.icPrefix + advisor.companyName\" :alt=\"advisor.icPrefix + advisor.companyName\" /></a>\r\n                        </div>\r\n                        <div v-if=\"advisor.interests.length || advisor.destinations.length\">\r\n                            <h4 class=\"mb-2\">Travel Specialties</h4>\r\n                            <div class=\"row mb-3\">\r\n                                <div v-if=\"advisor.interests.length\" class=\"col-6\">\r\n                                    <b>Interests</b><br />\r\n                                    <ul class=\"list-unstyled mt-half\">\r\n                                        <li v-for=\"(interest, index) in advisor.interests\" :key=\"index\" v-html=\"interest\"></li>\r\n                                    </ul>\r\n                                </div>\r\n                                <div v-if=\"advisor.destinations.length\" class=\"col-6\">\r\n                                    <b>Destinations</b><br />\r\n                                    <ul class=\"list-unstyled mt-half\">\r\n                                        <li v-for=\"(destination, destIndex) in advisor.destinations\" :key=\"destination\" :class=\"[(destIndex > 4 && !showExtraDestinations) ? 'd-none' : '']\"\r\n                                            v-html=\"destination\"></li>\r\n                                        <li v-if=\"advisor.destinations.length > 5 && !showExtraDestinations\"><button class=\"btn btn-link btn-sm p-0\" @click=\"showExtraDestinations = true\">View All</button></li>\r\n                                    </ul>\r\n                                </div>\r\n                            </div>\r\n                        </div>\r\n                        <template v-if=\"languagesCSV\">\r\n                            <h4>Languages</h4>\r\n                            <div class=\"mb-3\" v-html=\"languagesCSV\"></div>\r\n                        </template>\r\n                        <template v-if=\"advisor.sellingTravelSince\">\r\n                            <h4>Planning Travel Since:</h4>\r\n                            <div class=\"mb-3\" v-html=\"advisor.sellingTravelSince\"></div>\r\n                        </template>\r\n                        <div v-if=\"advisor.isVVCertifiedHost\" class=\"text-center\">\r\n                            <img src=\"https://virtuoso-prod.dotcms.cloud/images/products/vv-certified-host.png\" title=\"Virtuoso Voyages Certified Host\" alt=\"Virtuoso Voyages Certified Host\" width=\"200\" height=\"118\" />\r\n                        </div>\r\n                        <a v-if=\"isNetworkUser\" class=\"btn btn-primary-emphasis btn-sm d-block mt-3\" :href=\"cobrandLink(`/advisors/${props.productId}`)\" @click=\"handleLegacyLinkClick\">{{ (isAdvisor()) ? \"For Advisors: Update Your Profile\" : \"For Partners: Advanced Results\" }}</a>\r\n                    </div>\r\n                </div>\r\n            </section>\r\n            <section v-if=\"placesVisitedMapConfig.mapMarkers.length\" id=\"places\">\r\n                <h2 class=\"text--serif fw-normal mb-3 mb-xl-0\">Places Visited</h2>\r\n                <table class=\"largeMapTableContainer mx-auto\">\r\n                    <tbody>\r\n                        <tr>\r\n                            <td class=\"largeMapCell\">\r\n                                <MapView type=\"placesVisited\" :places-visited-map-config=\"placesVisitedMapConfig\" />\r\n                            </td>\r\n                            <td class=\"largeMapListCell\">\r\n                                <div class=\"largeMapListDiv\">\r\n                                    <table class=\"largeMapListTable f16\"></table>\r\n                                </div>\r\n                            </td>\r\n                        </tr>\r\n                    </tbody>\r\n                </table>\r\n            </section>\r\n            <section v-if=\"advisor.reviewsCount > 0\" id=\"reviews\">\r\n                <h2 class=\"text--serif fw-normal mb-3\">Reviews &amp; Recommendations</h2>\r\n                <product-reviews-component v-if=\"!suppressReviews\" :company-id=\"advisor.id\" :product-type=\"ProductType.ADVISORS\" :reviews-data=\"reviewsData\"></product-reviews-component>\r\n            </section>\r\n        </div>\r\n    </div>\r\n    <LogoSplash v-else />\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import ProductReviewsComponent from \"components/products/details/product-reviews.vue\";\r\n    import AdvisorContactButtonComponent from \"components/advisor/advisor-contact-button.vue\";\r\n    import LogoSplash from \"components/shared/logo-splash.vue\";\r\n    import MapView from \"components/shared/map-view.vue\";\r\n    import { AdvisorVisitedPlace, ProductDetailsAdvisorResponse } from \"interfaces/responses/product-detail-responses\";\r\n    import { AdvisorContactButton } from \"interfaces/advisor\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { MapMarker } from \"interfaces/map\";\r\n    import { ProductDetailsAdvisor } from \"interfaces/product\";\r\n    import { getProductDetails } from \"services/api/products\";\r\n    import { isAdvisor, isNetworkUser, virtuosoUser } from \"services/auth/user-info\";\r\n    import { formatLocation } from \"services/helpers/destinations\";\r\n    import { generateMediaServerImageUrl } from \"services/helpers/images\";\r\n    import { toastError } from \"services/helpers/toasts\";\r\n    import { renderMetadata } from \"services/layout/metadata\";\r\n    import { initAdvisorSubhead } from \"services/layout/sticky-subhead\";\r\n    import { formatAdvisorAgencyName } from \"services/transformers/products\";\r\n    import { trackEvent } from \"services/analytics\";\r\n    import { capitalizeFirst, cobrandLink, getCobrandType, getPlural, slugify } from \"virtuoso-shared-web-ui\";\r\n    import { nextTick, ref } from \"vue\";\r\n\r\n\r\n    const props = defineProps({\r\n        productId: {\r\n            type: Number,\r\n            default: undefined\r\n        },\r\n        suppressReviews: {\r\n            type: Boolean,\r\n            default: false\r\n        }\r\n    });\r\n\r\n    const advisor = ref<ProductDetailsAdvisor>({} as ProductDetailsAdvisor);\r\n    const isReady = ref(false);\r\n    const languagesCSV = ref(\"\");\r\n    const reviewsData = ref({});\r\n    const showExtraDestinations = ref(false);\r\n    const placesVisitedMapConfig = ref({ mapMarkers: [] as MapMarker[]});\r\n\r\n    const socialMediaIconMap = new Map([\r\n        [\"Facebook\", \"icon-facebook-circle\"],\r\n        [\"Instagram\", \"icon-instagram-circle\"],\r\n        [\"LinkedIn\", \"icon-linkedin-circle\"],\r\n        [\"Pinterest\", \"icon-pinterest-circle\"],\r\n        [\"Twitter\", \"icon-twitter-circle\"],\r\n        [\"YouTube\", \"icon-youtube-circle\"],\r\n        [\"Facebook\", \"icon-facebook-circle\"],\r\n        [\"Facebook\", \"icon-facebook-circle\"],\r\n        [\"Facebook\", \"icon-facebook-circle\"]\r\n    ]);\r\n\r\n    if (getCobrandType() === \"advisor\" && virtuosoUser.cobrandModel.advisorMeid !== props.productId) {\r\n        location.href = cobrandLink(`/travel`);\r\n    } else {\r\n        loadAdvisor();\r\n    }\r\n\r\n    function advisorContactButtonInfo(advisor: ProductDetailsAdvisor): AdvisorContactButton {\r\n        return {\r\n            company: advisor.companyName,\r\n            companyId: advisor.companyId,\r\n            country: advisor.agencyCountryName,\r\n            email: advisor.advisorEmail,\r\n            id: advisor.id,\r\n            name: advisor.advisorName,\r\n            phone: advisor.advisorPhone,\r\n            productType: ProductType.ADVISORS\r\n        };\r\n    }\r\n\r\n    function handleLegacyLinkClick(): void {\r\n        trackEvent(\"legacy_page_click\", {\r\n            affiliation: `${advisor.value.companyId}`,\r\n            item_id: `${props.productId}`,\r\n            item_name: advisor.value.advisorName,\r\n            item_category: capitalizeFirst(ProductType.ADVISORS.slice(0,-1))\r\n        });\r\n    }\r\n\r\n    function jumpToSection(sectionName: string): void {\r\n        document.querySelector(\".tab-nav-container .-active\").classList.remove(\"-active\");\r\n        document.getElementById(`tab-${sectionName}`).classList.add(\"-active\");\r\n\r\n        document.getElementById(sectionName)?.scrollIntoView();\r\n        setTimeout(function () {\r\n            document.getElementById(sectionName)?.scrollIntoView(); // In case the sticky header appearing/disappearing caused a shift\r\n        }, 1);\r\n    }\r\n\r\n    function loadAdvisor(): void {\r\n        getProductDetails(ProductType.ADVISORS, props.productId).then((resultAdvisor: ProductDetailsAdvisorResponse) => {\r\n\r\n            if (resultAdvisor && resultAdvisor.advisorName) {\r\n                const thisAdvisor: ProductDetailsAdvisor = {\r\n                    advisorEmail: resultAdvisor.advisorEmail,\r\n                    advisorFirstName: resultAdvisor.advisorFirstName,\r\n                    advisorLastName: resultAdvisor.advisorLastName,\r\n                    advisorName: resultAdvisor.advisorName,\r\n                    advisorPhone: resultAdvisor.officePhone,\r\n                    agencyCountryName: resultAdvisor.agencyCountryName,\r\n                    agencyUrl: cobrandLink(`/agencies/${resultAdvisor.companyId}/${slugify(resultAdvisor.companyName)}`),\r\n                    companyId: resultAdvisor.companyId,\r\n                    companyLogoUrl: resultAdvisor.companyLogo,\r\n                    companyName: resultAdvisor.companyName,\r\n                    dbaName: resultAdvisor.advisorDoingBusinessAs,\r\n                    description: resultAdvisor.advisorAboutMe,\r\n                    destinations: resultAdvisor.advisorSpecialtyCountries || [],\r\n                    featuredImageUrl: generateMediaServerImageUrl(resultAdvisor.advisorProfileImageUrl, { width: 200 }),\r\n                    icPrefix: formatAdvisorAgencyName(resultAdvisor.companyName, resultAdvisor.advisorIsIndependentContractor, resultAdvisor.advisorDoingBusinessAs, true),\r\n                    id: resultAdvisor.advisorMasterEntityId,\r\n                    interests: resultAdvisor.advisorInterestTypes || [],\r\n                    isAcceptingNewClients: resultAdvisor.isAdvisorAcceptingNewClients,\r\n                    isIC: resultAdvisor.advisorIsIndependentContractor,\r\n                    isVVCertifiedHost: resultAdvisor.isVVCertifiedHost,\r\n                    languages: resultAdvisor.advisorLanguages || [],\r\n                    location: \"\", // Derived below\r\n                    reviewsCount: resultAdvisor.totalActiveReviews || 0,\r\n                    reviewsPercent: resultAdvisor.totalRecommendedPercent || 0,\r\n                    sellingTravelSince: Number(resultAdvisor.advisorSellingTravelSinceYear) || null,\r\n                    socialMedia: [] // Derived below\r\n                };\r\n\r\n                // Advisor Address\r\n                if (resultAdvisor.profileAddresses && resultAdvisor.profileAddresses.length) {\r\n                    const primaryAddress = resultAdvisor.profileAddresses.find((item) => item.typeName === \"Primary\");\r\n                    if (primaryAddress) {\r\n                        thisAdvisor.location = formatLocation(\r\n                            primaryAddress.city,\r\n                            primaryAddress.state,\r\n                            primaryAddress.country\r\n                        );\r\n                    }\r\n                }\r\n\r\n                languagesCSV.value = thisAdvisor.languages.join(\", \");\r\n\r\n                // Social Media\r\n                if (resultAdvisor.profileWebSites && resultAdvisor.profileWebSites.length) {\r\n                    (resultAdvisor.profileWebSites).forEach((website) => {\r\n                        if (website.typeName && website.typeName !== \"Primary\" && website.link) {\r\n                            thisAdvisor.socialMedia.push({\r\n                                siteName: website.typeName,\r\n                                siteUrl: website.link\r\n                            });\r\n                        }\r\n                    });\r\n                }\r\n\r\n                // Reviews\r\n                if (thisAdvisor.reviewsCount > 0) {\r\n                    reviewsData.value = {\r\n                        percent: `<b>${thisAdvisor.reviewsPercent}% Recommended</b>`,\r\n                        count: `<b>${thisAdvisor.reviewsCount} Review${getPlural(thisAdvisor.reviewsCount)}</b>`\r\n                    };\r\n                }\r\n\r\n\r\n                // Places Visited map data\r\n                const placesVisited: AdvisorVisitedPlace[] = resultAdvisor.advisorVisitedPlaces || [];\r\n\r\n                if (placesVisited.length) {\r\n                    placesVisited.forEach((place) => {\r\n                        placesVisitedMapConfig.value.mapMarkers.push({\r\n                            Id: place.pointOfInterestId,\r\n                            PushpinLabel: \"\", // Always blank?\r\n                            SequenceLabel: `${place.pointOfInterestId}`,\r\n                            Longitude: place.longitude,\r\n                            Latitude: place.latitude,\r\n                            InfoWindowHtml: `<h3>${place.placeName}, ${place.countryName}</h3><div>Last Trip: ${place.lastYearVisited}<br>Number of Trips: ${place.numOfVisits}`,\r\n                            Title: `${place.placeName}, ${place.countryName}`,\r\n                            CountryCodeISO2: place.countryCodeISO2,\r\n                            CountryId: place.countryId,\r\n                            Date: `${place.lastYearVisited}`,\r\n                            NumOfVisits: place.numOfVisits\r\n                        });\r\n                    });\r\n                }\r\n\r\n                advisor.value = thisAdvisor;\r\n\r\n                renderMetadata({\r\n                    title: thisAdvisor.advisorName\r\n                });\r\n\r\n                isReady.value = true;\r\n\r\n                // Apply sticky subhead and highlighted subnav observers\r\n                nextTick(function () {\r\n                    initAdvisorSubhead();\r\n                });\r\n\r\n                // GA4 tracking\r\n                const getVirtuosoAdvisorSearchIndexValue = sessionStorage.getItem(`VirtuosoAdvisorSearchIndex_${props.productId}`);\r\n\r\n                if (getVirtuosoAdvisorSearchIndexValue) {\r\n                    sessionStorage.removeItem(`VirtuosoAdvisorSearchIndex_${props.productId}`);\r\n                }\r\n\r\n                trackEvent(\"view_item\",\r\n                    {\r\n                        ...((getVirtuosoAdvisorSearchIndexValue) && { index: parseInt(getVirtuosoAdvisorSearchIndexValue, 10) }), // should add index with value if session key existed\r\n                        item_id: `${props.productId}`,\r\n                        item_name: advisor.value.advisorName,\r\n                        item_brand: (advisor.value.isIC) ? advisor.value.dbaName : advisor.value.companyName,\r\n                        item_category: \"Advisor\",\r\n                        item_category2: advisor.value.location,\r\n                        item_category3: `${advisor.value.reviewsCount}`,\r\n                        item_category4: (advisor.value.isVVCertifiedHost) ? \"virtuoso voyages\" : \"\",\r\n                        item_variant: (advisor.value.isIC) ? \"independent contractor\" : \"advisor\",\r\n                        affiliation: (advisor.value.isIC) ? advisor.value.companyName : \"\"\r\n                    });\r\n            } else {\r\n                redirectOnError();\r\n            }\r\n        }, () => redirectOnError());\r\n    };\r\n\r\n    function redirectOnError(): void {\r\n        toastError(\"Record not found or you don't have access to view it\");\r\n        setTimeout(function () {\r\n            location.href = cobrandLink(`/travel/advisors`);\r\n        }, 3000);\r\n    }\r\n</script>\r\n","<template>\r\n    <component :is=\"detailsComponentMap[detailsComponentKey]\" :product-id=\"productId\"></component>\r\n</template>\r\n\r\n\r\n<script setup lang=\"ts\">\r\n    import CruiseDetailsComponent from \"components/products/details/cruise-details.vue\";\r\n    import HotelDetailsComponent from \"components/products/details/hotel-details.vue\";\r\n    import TourDetailsComponent from \"components/products/details/tour-details.vue\";\r\n    import AdvisorDetailsComponent from \"components/advisor/advisor-details.vue\";\r\n    import { ProductType } from \"interfaces/enums\";\r\n    import { PropType } from \"vue\";\r\n    import type { Component } from \"vue\";   \r\n\r\n    const props = defineProps({\r\n        catalogType: {\r\n            type: String as PropType<ProductType>,\r\n            default: undefined\r\n        },\r\n        productId: {\r\n            type: Number,\r\n            default: undefined\r\n        }\r\n    }); \r\n    // Map of component names to actual components\r\n    const detailsComponentMap: Record<string, Component> = {\r\n        \"cruise-details-component\": CruiseDetailsComponent,\r\n        \"hotel-details-component\": HotelDetailsComponent,\r\n        \"tour-details-component\": TourDetailsComponent,\r\n        \"advisor-details-component\": AdvisorDetailsComponent\r\n    };\r\n\r\n    const detailsComponentKey = props.catalogType.toLowerCase().slice(0, -1) + \"-details-component\";\r\n</script>\r\n","import ProductDetailsComponent from \"components/products/details/product-details.vue\";\r\nimport { ProductType } from \"interfaces/enums\";\r\nimport { captureRedirectData } from \"services/analytics\";\r\nimport { cobrandLink } from \"virtuoso-shared-web-ui\";\r\nimport { createApp } from \"vue\";\r\nimport { mountApp } from \"vue-app\";\r\n\r\n\r\nif (window.VIRTUOSO.productType && window.VIRTUOSO.productId) {\r\n    const app = createApp(ProductDetailsComponent,\r\n        {\r\n            catalogType: window.VIRTUOSO.productType,\r\n            productId: window.VIRTUOSO.productId\r\n        }\r\n    );\r\n    mountApp(app, \"page-app\");\r\n} else {\r\n    captureRedirectData();\r\n    if (window.VIRTUOSO.productType) {\r\n        const redirUrl = (window.VIRTUOSO.productType === ProductType.ADVISORS) ? \"/travel/advisors\" : `/travel/luxury-${window.VIRTUOSO.productType}`;\r\n        console.error(\"Product ID not provided\");\r\n        location.href = cobrandLink(redirUrl);\r\n    } else {\r\n        console.error(\"Product Type not provided\");\r\n        location.href = cobrandLink(\"/travel\");\r\n    }\r\n}\r\n\r\n"],"names":["props","__props","collapseMobileFields","ref","hostedBenefitNumberLabel","getPlural","benefitRef","useTemplateRef","expandHostedBenefits","splideElement","evt","applyVerticalTruncation","truncateElements","element","viewMoreText","viewLessText","initialHeight","innerWrap","maxHeight","applyTruncationHandlers","el","handleTransitionEnd","e","isCruise","ProductType","isTour","nextTick","clientNamesValue","_useModel","canViewComponent","isAdvisor","isVStaff","isEmbeddedMode","showTrackCruiseForm","validationText","isLoading","doTrackCruise","saveTrackSailing","resultJSON","toastSuccess","toggleTrackSailingForm","toastError","clearValue","provide","computed","advisorSearchquery","advisorCatalogLinkFiltered","cobrandLink","isNetworkUser","gaCategory","hasAdvisors","recommendedAdvisors","translateB2BFacetToConsumer","getAdvisors","advisorContactButtonInfo","advisor","parseAdvisorMeidFromUrlString","firstRecommendedAdvisor","lastRecommendedAdvisor","isCobranded","getRecommendedAdvisors","advisorsJSON","validAdvisors","generateMediaServerImageUrl","translateToConsumerUrl","extractCountryFromLocationString","err","hasMultipleHostedBenefits","topPromoName","carouselConfig","cruiseTitle","heartableUrl","hasBenefits","isBenefitsCarouselInitialized","isOverviewReady","isReady","legacyLink","legacyLinkLabel","isSupplier","productDetailRef","qsParams","parseURLParameters","recommendedAdvisorQuery","sailing","tabNavContainerRef","topSplashData","autoExpandAndToggle","item","toggleAddOn","goToSailing","elSelect","newId","handleLegacyLinkClick","setB2BDesktopCookie","trackEvent","capitalizeFirst","hasOnlyOnePostPackage","hasOnlyOnePrePackage","hasOnlyOneShoreExcursion","hydratePrePostPackages","packages","hydratedPackages","pkg","tourEventId","sanitizeUserGeneratedContent","slugify","loadOverview","sailingOverview","loadSailing","sailingCruiseLength","thisSailing","enableHearts","redirectOnError","getProductDetails","resultSailing","cruiseLength","theItems","galleryImages","hydrateImageGallery","featuredVideo","video","previousDay","currentDay","it","benefitGroup","ben","populateBenefits","hbg","hostedBenefits","forAllBenefits","hostList","hostTitle","hb","tempBenefit","host","memberName","dayTours","dayTour","segment","segmentIndex","visiblePromotions","promo","showThenJumpToTab","rawBenefits","eb","setRecommendedAdvisorIds","advisor1MEID","advisor2MEID","getVirtuosoCruiseSearchIndexValue","cruise","scrollToTabResponsive","tabName","isMobileScreenWidth","_a","_b","showTab","preventJump","fromTopLink","qsTabLabel","qsPromoTabName","id","btn","container","toggleSlideWithFade","hotelFeatureCategoryMap","hotelFeatureIconMap","showRoomSidebar","activeItemIndex","sideRoomDetailsRef","totalRooms","activeRoom","nextRoom","targetIndex","prevRoom","getRoomFeatures","groups","max","featureGroup","handleViewMoreClick","event","roomArrayIndex","bookingLink","bookingLinkForAdvisors","hotel","hasSustainabilityContent","isAdvisorOrVStaff","productMapConfig","reviewsData","showTabBlock","loadHotel","resultHotel","cmsJSON","hotelContentPromise","hotelResponse","cmsContentPromise","getCmsContent","productJSON","hasAddress","thisHotel","getSustainabilityCerts","formatLocation","combinedPromotions","sourcePromotionsExclusives","sourcePromotionsNormal","featuredPromoIndex","featuredItem","reviewsObj","mapPopupHtml","renderMetadata","getVirtuosoHotelSearchIndexValue","defaultTabName","tourExperienceIconMap","catalogType","isDayTour","isWheelchairAccessible","formattedLocation","routeMapConfig","tour","wanderlistTourName","goToTour","loadTour","resultTour","brandUrl","tourBrandSupplierTypesRestricted","thisTour","childTour","countryFound","previousDataDay","recommendedAdvisorCountry","getVirtuosoTourSearchIndexValue","desktopRootMargin","desktopRootMarginNearStickySubhead","mobileTopRootMargin","advisorHeaderNameObserver","advisorHeader","stickyHeader","config","entries","entry","setActiveTab","tab","observeSections","aboutTab","placesTab","reviewsTab","initAdvisorSubhead","sections","languagesCSV","showExtraDestinations","placesVisitedMapConfig","socialMediaIconMap","getCobrandType","virtuosoUser","loadAdvisor","jumpToSection","sectionName","resultAdvisor","thisAdvisor","formatAdvisorAgencyName","primaryAddress","website","placesVisited","place","getVirtuosoAdvisorSearchIndexValue","detailsComponentMap","CruiseDetailsComponent","HotelDetailsComponent","TourDetailsComponent","AdvisorDetailsComponent","detailsComponentKey","app","createApp","ProductDetailsComponent","mountApp","captureRedirectData","redirUrl"],"mappings":"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"}