' +\r\n '
' + item.name + '
' +\r\n '
Phone: ' + item.contactNumber + '
' +\r\n // '
Email: ' + item.EmailAddress + '
' +\r\n '
';\r\n\r\n allowedBounds.extend(new google.maps.LatLng(lat, lng));\r\n\r\n //Links up the infoWindow on click event\r\n gmarkers.push(dealershipMarker);\r\n\r\n google.maps.event.addListener(dealershipMarker, 'click', (function (dealershipMarker, i) {\r\n return function () {\r\n infoWindow.setContent(iwContent);\r\n infoWindow.open(map, dealershipMarker);\r\n }\r\n })\r\n (dealershipMarker, i));\r\n\r\n }\r\n });\r\n\r\n map.fitBounds(allowedBounds);\r\n\r\n scrollToElement($(props.searchByLocation), 500, true, 50);\r\n}\r\n\r\nasync function injectNearestDealershipsList(data) {\r\n\r\n const result = await buildNearestDealershipsListService(data);\r\n\r\n await injectHtml(props.dealershipResultsListWrapper, result);\r\n\r\n setTimeout(function () {\r\n\r\n //TODO: bind any events that may be required.\r\n\r\n $('#dealership-results-wrapper [data-toggle=\"tooltip\"]').tooltip();\r\n\r\n }, 100);\r\n\r\n}\r\n\r\nasync function injectNearestDealershipsForCheckoutList(data) {\r\n\r\n const result = await buildNearestDealershipsForCheckoutListService(data);\r\n\r\n await injectHtml(props.dealershipForCheckoutResultsListWrapper, result);\r\n\r\n setTimeout(function () {\r\n\r\n //bind dealership selection events. NOTE: these are imported from the checkout file.\r\n initDealershipMapEvents();\r\n\r\n }, 100);\r\n\r\n}\r\n\r\n\r\nfunction clearLocations() {\r\n\r\n infoWindow.close();\r\n\r\n map.getStreetView().setVisible(false);\r\n\r\n // Remove markers from map and array\r\n for (var i = 0; i < gmarkers.length; i++) {\r\n gmarkers[i].setMap(null);\r\n }\r\n gmarkers.length = 0;\r\n}\r\n\r\n\r\nfunction buildDynamicUrl() {\r\n\r\n //currently this only utilises the value of the search text box\r\n var locationValue = $(props.myLocation).val();\r\n var urlQuerystring = '';\r\n\r\n if (history.pushState) {\r\n\r\n if (!isEmpty(locationValue)) {\r\n\r\n urlQuerystring = '?location=' + locationValue;\r\n }\r\n\r\n var newurl = window.location.origin + window.location.pathname + urlQuerystring;\r\n window.history.pushState({ path: newurl }, '', newurl);\r\n }\r\n\r\n}\r\n\r\nfunction initShareUrlEvent() {\r\n\r\n $(props.shareLocation).off('click').on('click', function (e) {\r\n\r\n var dummy = document.createElement('input'),\r\n text = window.location.href;\r\n\r\n document.body.appendChild(dummy);\r\n dummy.value = text;\r\n dummy.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(dummy);\r\n\r\n $(props.shareLocation).tooltip('show');\r\n\r\n setTimeout(function () {\r\n\r\n $(props.shareLocation).tooltip('hide');\r\n\r\n }, 1500);\r\n\r\n });\r\n\r\n}\r\n\r\n\r\n\r\n//API CALLS\r\n\r\nasync function getNearestDealershipsService(data) {\r\n\r\n //no TRY CATCH as handled by parent\r\n const response = await http.post('/support/getnearestdealerships', data);\r\n\r\n return response.data;\r\n}\r\n\r\n\r\nasync function buildNearestDealershipsListService(data) {\r\n\r\n //no TRY CATCH as handled by parent\r\n //NOTE: post must be used or the selected filters list is lost\r\n const response = await http.post('/support/buildnearestdealershipslist', data);\r\n\r\n return response.data;\r\n}\r\n\r\nasync function buildNearestDealershipsForCheckoutListService(data) {\r\n\r\n //no TRY CATCH as handled by parent\r\n //NOTE: post must be used or the selected filters list is lost\r\n const response = await http.post('/support/buildnearestdealershipsforcheckoutlist', data);\r\n\r\n return response.data;\r\n}\r\n\r\n\r\n","import http from \"../../services/httpService\";\r\nimport { injectHtml } from \"../../utils/htmlUtil\";\r\nimport { openDialog, dialogModel } from \"../common/dialog\";\r\nimport forms from \"../common/forms\";\r\nimport { error, isEmpty, initToggleIconRotate, rotateElement } from \"../common/global\";\r\nimport { catchError } from \"../../utils/errorUtil\";\r\n\r\nconst props = {\r\n\r\n orderPlacedSuccessMarker: '#marker-order-success',\r\n convertGuestAccountWrapper: '#convert-guest-account-wrapper',\r\n addToBasketListItem: '.add-to-basket-list-item',\r\n selectProductOptionMessage: '#select-product-option-message',\r\n\r\n};\r\n\r\nexport function initPaymentSuccess() {\r\n\r\n if ($(props.convertGuestAccountWrapper).length) {\r\n initConvertGuestAccountEvents();\r\n }\r\n\r\n if ($(props.orderPlacedSuccessMarker).length) {\r\n\r\n //upon order success call a site URL that will call a service that will generate the required order workflow emails (and pdf's).\r\n processOrderEmailTasksService();\r\n\r\n buildGaFourDatalayerModel();\r\n }\r\n}\r\n\r\nfunction initConvertGuestAccountEvents() {\r\n\r\n catchError(async function () {\r\n\r\n const formObject = $('#convert-guest-account-form');\r\n const save_button = $('#submit-convert-convert-account');\r\n\r\n //initialise jquery validation for the injected form\r\n const validator = forms.onloadValidationSetupByObject(formObject);\r\n\r\n $(save_button).off('click').on('click', async function () {\r\n saveConvertGuestAccountForm(formObject, validator);\r\n });\r\n });\r\n}\r\n\r\nasync function saveConvertGuestAccountForm(formObject, validator) {\r\n\r\n //validate form\r\n if (formObject.valid()) {\r\n\r\n const buttonTextWrapper = $('.submit-button-text-wrapper');\r\n const activityIndicators = $('.submit-button-activity');\r\n\r\n buttonTextWrapper.hide();\r\n activityIndicators.show().css(\"display\", \"inline-block\");\r\n\r\n //NOTE: passing true to the second element will briefly enable all disabled form elements prior to form serialization and submission.\r\n forms.formUnderSubmission(true, true);\r\n\r\n setTimeout(async function () {\r\n\r\n const formValues = formObject.serialize();\r\n\r\n //attempt POST save, the check response\r\n const response = await convertGuestAccountService(formValues);\r\n\r\n if (response.responseType === \"SUCCESS\") {\r\n\r\n //hide form, display confirmation panel\r\n $('#convert-account-form-wrapper').hide(500, function () {\r\n\r\n $('#account-converted-confirmation-wrapper').show(500);\r\n });\r\n }\r\n else {\r\n //display failure notification in some way\r\n var failureMessage = response.responseMessage;\r\n\r\n //display failure snackbar\r\n openSnackbar({\r\n ...snackbarModel,\r\n content: failureMessage,\r\n remain: true\r\n });\r\n }\r\n\r\n forms.formUnderSubmission(false, true);\r\n\r\n buttonTextWrapper.show();\r\n activityIndicators.show().css(\"display\", \"none\");\r\n\r\n }, 1000);\r\n } else {\r\n\r\n forms.scrollToFirstError(validator, $(document).height() * 0.5);\r\n }\r\n\r\n}\r\n\r\n//LEGACY FUNCTION. Retained until GA4 implementation is in place.\r\nasync function buildGtmDatalayerModel() {\r\n\r\n const data = {\r\n orderId: $(props.orderPlacedSuccessMarker).data('oid')\r\n };\r\n\r\n const response = await getGtmDataModel(data);\r\n\r\n if (response.responseType === \"SUCCESS\") {\r\n\r\n //need to build the GTM datalayer object and push to GTM\r\n var gtmOrderItems = [];\r\n\r\n for (var i = 0; i < response.orderItems.length; i++) {\r\n\r\n var orderItem = response.orderItems[i];\r\n\r\n if (!orderItem.isDiscount) {\r\n\r\n gtmOrderItems.push({\r\n 'sku': orderItem.sku,\r\n 'name': orderItem.title,\r\n 'category': orderItem.category,\r\n 'price': orderItem.unitPriceExclVat,\r\n 'quantity': orderItem.quantity\r\n });\r\n }\r\n else {\r\n\r\n gtmOrderItems.push({\r\n\r\n //'sku' changes to 'coupon' for the voucher item\r\n 'coupon': orderItem.sku,\r\n 'name': orderItem.title,\r\n 'category': orderItem.category,\r\n 'price': orderItem.unitPriceExclVat,\r\n 'quantity': orderItem.quantity\r\n });\r\n }\r\n }\r\n\r\n window.dataLayer = window.dataLayer || [];\r\n\r\n dataLayer.push({\r\n 'transactionId': response.orderId,\r\n 'transactionAffiliation': response.affiliation,\r\n 'transactionTotal': response.orderTotal,\r\n 'transactionTax': response.vat,\r\n 'transactionShipping': response.delivery,\r\n 'transactionProducts': gtmOrderItems\r\n });\r\n }\r\n else {\r\n\r\n //should we do anything if this fails?\r\n }\r\n\r\n}\r\n\r\nasync function buildGaFourDatalayerModel() {\r\n\r\n const data = {\r\n orderId: $(props.orderPlacedSuccessMarker).data('oid')\r\n };\r\n\r\n const response = await getGaFourDataModel(data);\r\n\r\n if (response.responseType === \"SUCCESS\") {\r\n\r\n //need to build the GTM datalayer object and push to GTM - this is for GA4 e commerce tracking\r\n var gtmOrderItems = [];\r\n\r\n for (var i = 0; i < response.orderItems.length; i++) {\r\n\r\n var orderItem = response.orderItems[i];\r\n\r\n gtmOrderItems.push({\r\n item_id: orderItem.sku,\r\n item_name: orderItem.title,\r\n affiliation: orderItem.affiliation,\r\n coupon: orderItem.coupon,\r\n discount: orderItem.discount,\r\n index: i,\r\n item_brand: orderItem.itemBrand,\r\n item_category: orderItem.itemCategory,\r\n item_category2: orderItem.itemCategory2,\r\n item_category3: orderItem.itemCategory3,\r\n item_category4: orderItem.itemCategory4,\r\n item_category5: orderItem.itemCategory5,\r\n\r\n price: orderItem.unitPriceInclVat,\r\n quantity: orderItem.quantity\r\n });\r\n }\r\n\r\n window.dataLayer = window.dataLayer || [];\r\n\r\n var order = {\r\n event: 'purchase',\r\n ecommerce: {\r\n transaction_id: response.orderId,\r\n value: response.orderTotal,\r\n tax: response.vat,\r\n shipping: response.delivery,\r\n currency: response.currency,\r\n coupon: response.coupon,\r\n items: gtmOrderItems\r\n }\r\n };\r\n\r\n dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object.\r\n dataLayer.push(order);\r\n }\r\n else {\r\n\r\n //should we do anything if this fails?\r\n }\r\n\r\n}\r\n\r\nasync function convertGuestAccountService(data) {\r\n\r\n //no TRY CATCH as handled by parent\r\n //calls a service to convert the guest account to a retail account\r\n const response = await http.post('/account/convertguestaccount', data);\r\n\r\n return response.data;\r\n}\r\n\r\nasync function processOrderEmailTasksService() {\r\n\r\n //no TRY CATCH as handled by parent\r\n const response = await http.get('/processorderemailtasksasync');\r\n\r\n return response.data;\r\n}\r\n\r\nasync function getGaFourDataModel(data) {\r\n\r\n //no TRY CATCH as handled by parent\r\n const response = await http.get('/seo/ordergafourmodel', data);\r\n\r\n return response.data;\r\n}","import { catchError } from \"../../utils/errorUtil\";\r\nimport { isBrowserChrome } from \"../common/global\";\r\n\r\nconst props = {\r\n //MARKERS\r\n warrantyRegFormMarker: '#m-warranty-reg-form',\r\n contactUsFormMarker: '#m-contact-us-form',\r\n becomeDealerMarker: '#m-become-dealer-form',\r\n\r\n //WARRANTY FORM\r\n warrantyDealershipSelected: '#DealershipPurchasedFromId',\r\n warrantyDealershipSelectedOther: '#DealershipPurchasedFromOtherInfo',\r\n\r\n //CONTACT US\r\n locationMap: '#location-map'\r\n};\r\n\r\n//for Contact Us location map\r\nvar map = null;\r\nvar infoWindow = null;\r\nvar locationMarker, i = null;\r\nvar geocoder = null;\r\n\r\n\r\nexport function initSiteForms() {\r\n\r\n if ($(props.warrantyRegFormMarker).length) {\r\n\r\n initWarrantyRegPageEvents();\r\n }\r\n\r\n if ($(props.contactUsFormMarker).length) {\r\n\r\n initContactUsPageEvents();\r\n }\r\n\r\n if ($(props.becomeDealerMarker).length) {\r\n\r\n initBecomeDealerPageEvents();\r\n }\r\n}\r\n\r\nasync function initWarrantyRegPageEvents() {\r\n\r\n $(props.warrantyDealershipSelected).off('change').on('change', function (e) {\r\n\r\n if ($(this).val() == \"0\") {\r\n\r\n //other selected. display banner for Other options\r\n $(props.warrantyDealershipSelectedOther).show(500);\r\n } else {\r\n\r\n $(props.warrantyDealershipSelectedOther).hide(500);\r\n }\r\n\r\n });\r\n\r\n //loquate initialisation\r\n var addressFields = [\r\n { element: \"address-search\", field: \"\" },\r\n { element: \"Address1\", field: \"Line1\" },\r\n { element: \"Address2\", field: \"Line2\", mode: pca.fieldMode.POPULATE },\r\n { element: \"Address3\", field: \"City\", mode: pca.fieldMode.POPULATE },\r\n { element: \"City\", field: \"Province\", mode: pca.fieldMode.POPULATE },\r\n { element: \"Postcode\", field: \"PostalCode\" }\r\n ];\r\n\r\n var addressOptions = { key: \"ZC65-ZN49-DG59-RE95\", countries: { codesList: \"GBR\" }, setCountryByIP: false };\r\n\r\n var control = new pca.Address(addressFields, addressOptions);\r\n\r\n //prevents chrome ac getting in the way\r\n if (isBrowserChrome() === true) {\r\n\r\n for (i = 0; control.fields.length > i; i++) {\r\n\r\n $('#' + control.fields[i].element).prop('autocomplete', 'PCATEST');\r\n\r\n };\r\n };\r\n}\r\n\r\nasync function initBecomeDealerPageEvents() {\r\n\r\n //loquate initialisation\r\n var addressFields = [\r\n { element: \"address-search\", field: \"\" },\r\n { element: \"Address1\", field: \"Line1\" },\r\n { element: \"Address2\", field: \"Line2\", mode: pca.fieldMode.POPULATE },\r\n { element: \"Address3\", field: \"City\", mode: pca.fieldMode.POPULATE },\r\n { element: \"City\", field: \"Province\", mode: pca.fieldMode.POPULATE },\r\n { element: \"Postcode\", field: \"PostalCode\" }\r\n ];\r\n\r\n var addressOptions = { key: \"ZC65-ZN49-DG59-RE95\", countries: { codesList: \"GBR\" }, setCountryByIP: false };\r\n\r\n var control = new pca.Address(addressFields, addressOptions);\r\n\r\n //prevents chrome ac getting in the way\r\n if (isBrowserChrome() === true) {\r\n\r\n for (i = 0; control.fields.length > i; i++) {\r\n\r\n $('#' + control.fields[i].element).prop('autocomplete', 'PCATEST');\r\n\r\n };\r\n };\r\n}\r\n\r\n\r\nasync function initContactUsPageEvents() {\r\n\r\n initialiseLocationMap();\r\n}\r\n\r\n\r\nasync function initialiseLocationMap() {\r\n\r\n var allowedBounds = new google.maps.LatLngBounds();\r\n\r\n geocoder = new google.maps.Geocoder();\r\n var latlng = new google.maps.LatLng(51.8347123, 0.1500933);\r\n var mapOptions = {\r\n mapTypeControl: false,\r\n fullscreenControl: false,\r\n zoom: 10,\r\n //mapTypeId: google.maps.MapTypeId.ROADMAP,\r\n region: 'uk'//,\r\n //styles: [{ \"featureType\": \"all\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"on\" }] }, { \"featureType\": \"all\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"all\", \"elementType\": \"labels.text.fill\", \"stylers\": [{ \"saturation\": 36 }, { \"color\": \"#000000\" }, { \"lightness\": \"35\" }, { \"gamma\": \"1\" }] }, { \"featureType\": \"all\", \"elementType\": \"labels.text.stroke\", \"stylers\": [{ \"visibility\": \"off\" }, { \"color\": \"#000000\" }, { \"lightness\": 16 }] }, { \"featureType\": \"all\", \"elementType\": \"labels.icon\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"administrative\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 20 }] }, { \"featureType\": \"administrative\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 17 }, { \"weight\": 1.2 }] }, { \"featureType\": \"administrative.locality\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"simplified\" }] }, { \"featureType\": \"administrative.locality\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"lightness\": \"-11\" }] }, { \"featureType\": \"administrative.locality\", \"elementType\": \"labels.text\", \"stylers\": [{ \"color\": \"#fc5d1e\" }] }, { \"featureType\": \"administrative.land_parcel\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"on\" }] }, { \"featureType\": \"landscape\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 20 }] }, { \"featureType\": \"poi\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 21 }] }, { \"featureType\": \"poi.park\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"poi.park\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"poi.park\", \"elementType\": \"labels.text.stroke\", \"stylers\": [{ \"visibility\": \"simplified\" }] }, { \"featureType\": \"poi.park\", \"elementType\": \"labels.icon\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"road\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"simplified\" }] }, { \"featureType\": \"road\", \"elementType\": \"labels.icon\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"road.highway\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"color\": \"#475058\" }, { \"lightness\": \"-48\" }, { \"saturation\": \"-73\" }, { \"weight\": \"3.98\" }] }, { \"featureType\": \"road.highway\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 29 }, { \"weight\": 0.2 }] }, { \"featureType\": \"road.arterial\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 18 }] }, { \"featureType\": \"road.arterial\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"lightness\": \"7\" }] }, { \"featureType\": \"road.arterial\", \"elementType\": \"labels.text.fill\", \"stylers\": [{ \"lightness\": \"63\" }] }, { \"featureType\": \"road.local\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 16 }, { \"visibility\": \"off\" }] }, { \"featureType\": \"road.local\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"visibility\": \"on\" }, { \"lightness\": \"-8\" }, { \"gamma\": \"1.73\" }] }, { \"featureType\": \"road.local\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"lightness\": \"-1\" }] }, { \"featureType\": \"road.local\", \"elementType\": \"labels.text.fill\", \"stylers\": [{ \"lightness\": \"24\" }] }, { \"featureType\": \"transit\", \"elementType\": \"all\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"transit\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#000000\" }, { \"lightness\": 19 }] }, { \"featureType\": \"water\", \"elementType\": \"geometry\", \"stylers\": [{ \"color\": \"#475058\" }, { \"lightness\": 17 }] }, { \"featureType\": \"water\", \"elementType\": \"geometry.fill\", \"stylers\": [{ \"color\": \"#d1e0e9\" }, { \"lightness\": \"-70\" }, { \"saturation\": \"-75\" }] }, { \"featureType\": \"water\", \"elementType\": \"geometry.stroke\", \"stylers\": [{ \"visibility\": \"off\" }] }, { \"featureType\": \"water\", \"elementType\": \"labels.text.fill\", \"stylers\": [{ \"lightness\": \"-54\" }, { \"hue\": \"#ff0000\" }] }]\r\n };\r\n map = new google.maps.Map(document.getElementById(\"location-map\"),\r\n mapOptions);\r\n\r\n // ***** Markers *****\r\n infoWindow = new google.maps.InfoWindow();\r\n\r\n google.maps.event.addListenerOnce(map, 'idle', function () {\r\n\r\n // do something only the first time the map is loaded\r\n geocoder.geocode({\r\n 'address': 'hayter mowers cm23 4bu'\r\n }, async function (results, status) {\r\n if (status == google.maps.GeocoderStatus.OK) {\r\n\r\n if (locationMarker) locationMarker.setMap(null);\r\n\r\n allowedBounds = new google.maps.LatLngBounds();\r\n\r\n var markerIcon = {\r\n url: \"/images/core/dealerships/finder.png\",\r\n scaledSize: new google.maps.Size(26, 35)\r\n };\r\n\r\n locationMarker = new google.maps.Marker({\r\n map: map,\r\n title: 'Hayter Mowers',\r\n position: results[0].geometry.location,\r\n icon: markerIcon\r\n });\r\n\r\n var customLat = results[0].geometry.location.lat();\r\n var customLng = results[0].geometry.location.lng();\r\n\r\n allowedBounds.extend(new google.maps.LatLng(customLat, customLng));\r\n\r\n map.fitBounds(allowedBounds);\r\n\r\n map.setZoom(15);\r\n map.panTo(results[0].geometry.location)\r\n\r\n // Build info Window\r\n var iwContent = '