{"version":3,"file":"CompareVehicles-ec0f2bfe.js","sources":["../../src/views/CompareVehicles.vue"],"sourcesContent":["<template>\r\n <PageLayout :module-title=\"moduleTitle\">\r\n <!-- HERO IMAGES SECTION -->\r\n\r\n <!-- Used as a reference for the sticky hero to trigger -->\r\n <div ref=\"comparisonHero\"></div>\r\n <article class=\"comparison-hero-section\" :class=\"mobileDevices ? '' : stickyClass\">\r\n <div :class=\"[{ container: !mobileDevices && stickyClass }, 'comparison-grid__container mobile-container']\">\r\n <CarComparisonHero\r\n v-for=\"(carData, index) in comparisonStore.carsToCompare\"\r\n :key=\"`car__${index}`\"\r\n :car-data=\"carData\"\r\n :api-status=\"apiStatus\"\r\n :index=\"index\"\r\n />\r\n </div>\r\n </article>\r\n\r\n <!-- offset the content below the sticky hero so the jump to sticky isn't so jarring -->\r\n <article :style=\"{ marginTop: Boolean(stickyClass) && !mobileDevices ? '12rem' : '0' }\">\r\n <CarSpecsTabularAccordions :tabular-data=\"tabularDataProps.tabularData\" :cars-to-compare=\"comparisonStore.carsToCompare\" :is-mobile=\"mobileDevices\" />\r\n </article>\r\n\r\n <ScrollToTop v-if=\"mobileDevices\" />\r\n\r\n <hr class=\"bottom-page-hr\" />\r\n </PageLayout>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { useQuery } from '@vue/apollo-composable';\r\nimport { ref, onBeforeMount } from 'vue';\r\nimport { carAdvisoryService } from '../foundation/apiCarAdvisoryService';\r\nimport { MAX_LIMIT, useCarComparisonStore } from '../foundation/stores/carComparisonStore';\r\nimport { DefaultCompareVehiclesDatasourceId } from '../foundation/apiConstant';\r\nimport { COMPARE_VEHICLES_DS_QUERY } from '../foundation/queries';\r\nimport { storeToRefs } from 'pinia';\r\nimport { useRoute } from 'vue-router';\r\nimport { useMonitorElementVisibility } from '../composables/useMonitorElementVisibility';\r\nimport { useBreakpoints } from '@vueuse/core';\r\nimport { APP_BREAKPOINTS } from '../foundation/appConstants';\r\nimport { ApiStatusTypes } from '../foundation/types/apiStatusTypes';\r\nimport PageLayout from '../layouts/PageLayout.vue';\r\nimport CarComparisonHero from '../components/car-comparison/CarComparisonHero.vue';\r\nimport CarSpecsTabularAccordions from '../components/car-stats/CarSpecsTabularAccordions.vue';\r\nimport { useAnalytics } from '../composables/useAnalytics';\r\nimport { useUrlBuilder } from '../composables/useUrlBuilder';\r\nimport { AnalyticsEventNames, AnalyticsEvents, AnalyticsEventTypes } from '../foundation/enums/AnalyticsEvents';\r\nimport ScrollToTop from '../components/global/ScrollToTop.vue';\r\nimport { useContentStore } from '../foundation/stores/contentStore';\r\n\r\n// Get the datasourceId from the dynamic component props and pass to GraphQL as a query variable\r\nconst props = defineProps<{\r\n datasourceId: string;\r\n}>();\r\n\r\n// Composables\r\nconst route = useRoute();\r\nconst breakpoints = useBreakpoints(APP_BREAKPOINTS);\r\nconst contentStore = useContentStore();\r\ncontentStore.fetchCarDetailsTabularDataProps(props.datasourceId);\r\n\r\n// High level variables\r\nconst { carDetailsTabularDataProps: tabularDataProps } = storeToRefs(contentStore);\r\n\r\nconst queryVars = { datasource: props.datasourceId ?? DefaultCompareVehiclesDatasourceId };\r\nconst vehicleIdsInUrl = route.query.vehicleIds;\r\nconst mobileDevices = breakpoints.smallerOrEqual('sm'); // only larger than sm\r\n\r\n//Analytics\r\nconst analytics = useAnalytics();\r\nconst pushAnalyticsOnlyOnce = ref(false);\r\n// Pinia Store\r\nconst comparisonStore = useCarComparisonStore();\r\nconst { showCarComparisonFooter } = storeToRefs(comparisonStore);\r\nshowCarComparisonFooter.value = false;\r\n\r\n// Vue 3 refs & reactives\r\nconst comparisonHero = ref(null);\r\nconst apiStatus = ref<ApiStatusTypes>('IDLE');\r\nconst moduleTitle = ref('My car comparison');\r\n\r\n// Computed\r\nconst { stickyClass } = useMonitorElementVisibility(comparisonHero);\r\n\r\n// Data fetching\r\n// Retrieve the module datasource content via GraphQL\r\nuseQuery(COMPARE_VEHICLES_DS_QUERY, queryVars).onResult((result) => {\r\n moduleTitle.value = result.data.datasource.moduleTitle?.value ?? moduleTitle.value;\r\n});\r\n\r\n// On Before Mount Hook\r\n// Retreive car data either from API or car comparison store\r\nonBeforeMount(initCompareVehiclesPage);\r\n\r\n/**\r\n * Initial page load for compare vehicles page.\r\n */\r\nasync function initCompareVehiclesPage() {\r\n // If no vehicle ids available in the URL, then populate\r\n // the page with empty car comparison grid items\r\n if (!vehicleIdsInUrl) {\r\n return setCarsToCompare(['', '', '']);\r\n }\r\n\r\n if (vehicleIdsInUrl) {\r\n const vehicleIdsArray = (vehicleIdsInUrl as string).split(',');\r\n\r\n // If there are less IDs than the MAX_LIMIT, simply add them.\r\n // This allows us to show an empty vehicle slot in the UI.\r\n while (vehicleIdsArray.length < 3) {\r\n vehicleIdsArray.push('');\r\n }\r\n\r\n setCarsToCompare(vehicleIdsArray);\r\n }\r\n}\r\n\r\nfunction pushToAnalytics(vehicleData: any[]) {\r\n try {\r\n var analyticsData = {\r\n eventInfo: {\r\n navigation: {\r\n name: AnalyticsEventNames.ViewComparison,\r\n type: AnalyticsEventTypes.CarCompare,\r\n selectedCars: vehicleData,\r\n },\r\n },\r\n };\r\n if (!pushAnalyticsOnlyOnce.value) analytics.push(AnalyticsEvents.NavigationClickToComparison, analyticsData);\r\n pushAnalyticsOnlyOnce.value = true;\r\n } catch (error) {\r\n console.warn('fail to push data to analytics', error);\r\n }\r\n}\r\n\r\n/**\r\n * Set the cars to compare in the UI.\r\n * Restrict vehicle limit to the MAX_LIMIT set (eg, 3 cars max).\r\n *\r\n * Assumptions:\r\n * - If a user has cars in their comparison cart (which are stored in local storage) and then\r\n * they load a new url with different car IDs, the entire comparison cart will be\r\n * repopulated with the new cars from the vehicle IDs in the URL.\r\n *\r\n * @param vehicleIds An array of Vehicle IDs\r\n */\r\nasync function setCarsToCompare(vehicleIds: string[]): Promise<void> {\r\n const vehiclesToLoad = vehicleIds.slice(0, MAX_LIMIT);\r\n apiStatus.value = 'LOADING';\r\n var vehicleData = [];\r\n for (let index = 0; index < vehiclesToLoad.length; index++) {\r\n try {\r\n const id = vehiclesToLoad[index];\r\n const data: Record<string, any> = await carAdvisoryService.fetchVehicleById(id);\r\n if (id) {\r\n vehicleData.push({\r\n makeName: data.Make,\r\n modelName: data.Model,\r\n badgeName: data.Trim,\r\n year: `${data.Year_low} - ${data.Year_high}`,\r\n bodyType: data.Body_type,\r\n engineType: data.Overall_EngineType,\r\n URL: useUrlBuilder().getCarDetailsUrl(data.Vehicle_UID, `${data.Year_low} - ${data.Year_high}`, data.Make, data.Model),\r\n });\r\n }\r\n comparisonStore.updateFetchedVehicles(id, data);\r\n comparisonStore.updateCarToCompare(index, id ?? '');\r\n } catch (err) {\r\n console.error('vehicleDataRequestsError', err);\r\n apiStatus.value = 'ERROR';\r\n }\r\n }\r\n pushToAnalytics(vehicleData);\r\n // All cars are loaded successfully\r\n apiStatus.value = 'IDLE';\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n.sticky {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n background: #fff;\r\n box-shadow: 0.25rem 0 0.3rem rgba(0, 0, 0, 0.16);\r\n clip-path: inset(-0.3rem 0 -0.3rem -0.3rem); // Hack to remove right box shadow\r\n\r\n &.comparison-hero-section {\r\n width: 100%;\r\n z-index: 1000;\r\n padding-bottom: 1rem;\r\n\r\n .comparison-grid__container {\r\n padding: 0 0.5rem;\r\n margin: 0 auto;\r\n max-height: 8rem;\r\n\r\n &.mobile-container {\r\n margin: 0 !important;\r\n max-width: 100%;\r\n padding: 0;\r\n\r\n @media screen and (min-width: #{$breakpoint-md}) {\r\n margin: auto !important;\r\n max-width: inherit;\r\n }\r\n }\r\n\r\n @media screen and (min-width: #{$breakpoint-lg}) {\r\n padding: 0 0.5rem;\r\n }\r\n\r\n @media screen and (min-width: #{$breakpoint-xxl}) {\r\n padding: 0;\r\n }\r\n }\r\n }\r\n} // end .sticky\r\n\r\n.comparison-hero-section {\r\n padding-top: 1rem;\r\n}\r\n\r\n.comparison-grid {\r\n &__container {\r\n display: grid;\r\n grid-template-columns: 1fr;\r\n grid-auto-rows: 1fr 1fr 1fr;\r\n gap: 1rem 1rem;\r\n height: 100%;\r\n\r\n @media (min-width: $breakpoint-sm) {\r\n grid-auto-flow: column;\r\n grid-template-columns: 1fr 1fr 1fr;\r\n grid-auto-rows: 1fr;\r\n }\r\n }\r\n\r\n &__item {\r\n height: 100vh;\r\n }\r\n}\r\n\r\n.comparison-accordion__container {\r\n position: relative;\r\n}\r\n\r\n.bottom-page-hr {\r\n color: $racq-pale-blue-border;\r\n border: 2px solid $racq-pale-blue-border;\r\n margin: 6.25rem 0 2.5rem;\r\n}\r\n</style>\r\n"],"names":["route","useRoute","breakpoints","useBreakpoints","APP_BREAKPOINTS","contentStore","useContentStore","props","tabularDataProps","storeToRefs","queryVars","DefaultCompareVehiclesDatasourceId","vehicleIdsInUrl","mobileDevices","analytics","useAnalytics","pushAnalyticsOnlyOnce","ref","comparisonStore","useCarComparisonStore","showCarComparisonFooter","comparisonHero","apiStatus","moduleTitle","stickyClass","useMonitorElementVisibility","useQuery","COMPARE_VEHICLES_DS_QUERY","result","_a","onBeforeMount","initCompareVehiclesPage","setCarsToCompare","vehicleIdsArray","pushToAnalytics","vehicleData","analyticsData","AnalyticsEventNames","AnalyticsEventTypes","AnalyticsEvents","error","vehicleIds","vehiclesToLoad","MAX_LIMIT","index","id","data","carAdvisoryService","useUrlBuilder","err"],"mappings":"2oDAyDMA,EAAQC,IACRC,EAAcC,GAAeC,CAAe,EAC5CC,EAAeC,IACRD,EAAA,gCAAgCE,EAAM,YAAY,EAG/D,KAAM,CAAE,2BAA4BC,CAAiB,EAAIC,EAAYJ,CAAY,EAE3EK,EAAY,CAAE,WAAYH,EAAM,cAAgBI,CAAmC,EACnFC,EAAkBZ,EAAM,MAAM,WAC9Ba,EAAgBX,EAAY,eAAe,IAAI,EAG/CY,EAAYC,IACZC,EAAwBC,EAAI,EAAK,EAEjCC,EAAkBC,IAClB,CAAE,wBAAAC,CAAA,EAA4BX,EAAYS,CAAe,EAC/DE,EAAwB,MAAQ,GAG1B,MAAAC,EAAiBJ,EAAI,IAAI,EACzBK,EAAYL,EAAoB,MAAM,EACtCM,EAAcN,EAAI,mBAAmB,EAGrC,CAAE,YAAAO,CAAA,EAAgBC,GAA4BJ,CAAc,EAIlEK,EAASC,EAA2BjB,CAAS,EAAE,SAAUkB,GAAW,OAClEL,EAAY,QAAQM,EAAAD,EAAO,KAAK,WAAW,cAAvB,YAAAC,EAAoC,QAASN,EAAY,KAAA,CAC9E,EAIDO,EAAcC,CAAuB,EAKrC,eAAeA,GAA0B,CAGvC,GAAI,CAACnB,EACH,OAAOoB,EAAiB,CAAC,GAAI,GAAI,EAAE,CAAC,EAGtC,GAAIpB,EAAiB,CACb,MAAAqB,EAAmBrB,EAA2B,MAAM,GAAG,EAItD,KAAAqB,EAAgB,OAAS,GAC9BA,EAAgB,KAAK,EAAE,EAGzBD,EAAiBC,CAAe,CAClC,CACF,CAEA,SAASC,EAAgBC,EAAoB,CACvC,GAAA,CACF,IAAIC,EAAgB,CAClB,UAAW,CACT,WAAY,CACV,KAAMC,EAAoB,eAC1B,KAAMC,GAAoB,WAC1B,aAAcH,CAChB,CACF,CAAA,EAEGnB,EAAsB,OAAiBF,EAAA,KAAKyB,GAAgB,4BAA6BH,CAAa,EAC3GpB,EAAsB,MAAQ,SACvBwB,GACC,QAAA,KAAK,iCAAkCA,CAAK,CACtD,CACF,CAaA,eAAeR,EAAiBS,EAAqC,CACnE,MAAMC,EAAiBD,EAAW,MAAM,EAAGE,CAAS,EACpDrB,EAAU,MAAQ,UAClB,IAAIa,EAAc,CAAA,EAClB,QAASS,EAAQ,EAAGA,EAAQF,EAAe,OAAQE,IAC7C,GAAA,CACF,MAAMC,EAAKH,EAAeE,GACpBE,EAA4B,MAAMC,EAAmB,iBAAiBF,CAAE,EAC1EA,GACFV,EAAY,KAAK,CACf,SAAUW,EAAK,KACf,UAAWA,EAAK,MAChB,UAAWA,EAAK,KAChB,KAAM,GAAGA,EAAK,cAAcA,EAAK,YACjC,SAAUA,EAAK,UACf,WAAYA,EAAK,mBACjB,IAAKE,EAAA,EAAgB,iBAAiBF,EAAK,YAAa,GAAGA,EAAK,cAAcA,EAAK,YAAaA,EAAK,KAAMA,EAAK,KAAK,CAAA,CACtH,EAEa5B,EAAA,sBAAsB2B,EAAIC,CAAI,EAC9B5B,EAAA,mBAAmB0B,EAAOC,GAAM,EAAE,QAC3CI,GACC,QAAA,MAAM,2BAA4BA,CAAG,EAC7C3B,EAAU,MAAQ,OACpB,CAEFY,EAAgBC,CAAW,EAE3Bb,EAAU,MAAQ,MACpB"}