{"version":3,"file":"modules/srpMain-b1-696f5ee9f53b2f50c552.js","mappings":"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AmC0zF,EAAaxzF,iBACjD,CAAC,2BAAiCwzF,EAAavzF,oBAC/C,CAAC,2BAAiCuzF,EAAazzF,iBAKjD,MAAO,CACLgjF,gBAHsB5wH,OAAOuK,KAAK+2H,GAAa92H,QAAQ2oH,GAAamO,EAAYnO,GAAY,IAI5FpmG,kBACAmX,eACAquF,qBACD,IAeQgP,IATuC,QAClD,KACA,MACA,CAACx0G,EAAiBmX,KAAiB,CACjCnX,kBACAmX,oBAI+C,QACjDhY,EACA,MACA,CAAC6/E,EAAetzE,KAAe,CAC7BszE,gBACAtzE,kBAQS+oG,GAAgD,QAC3D,KACA,MACA,CAACv9G,EAAkBoqG,KAAuB,CACxCpqG,mBACAoqG,yBAOSoT,GAAyC,QACpD,KACA,MACA,CAACx9G,EAAkBkzG,KAA6B,CAC9ClzG,mBACAkzG,+BAQSuK,GAAkD,QAC7D,KACA,MACA,CAACxJ,EAAuB3lC,KAA4B,CAClD2lC,wBACA3lC,8BAOSovC,GAAwC,QACnD,KACA,MACA,CAACpvC,EAAyBpuE,KAAS,CACjCouE,0BACApuE,WAUSy9G,GAA6C,QACxD,KACA,KACA,KACA,KACA,KACA,CAACz3G,EAA2BmtG,EAAwBnzG,EAAM4nB,EAAU/kB,KAAiB,CACnFmD,4BACAmtG,yBACAnzG,OACA4nB,WACA/kB,mBAQSmB,GAA6B,QACxC,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,MACA,CACEud,EACAI,EACA9Q,EACAG,EACAF,EACAqqD,EACAuiD,EACApiD,EACApqD,EACAC,EACAwsG,EACA7qG,EACAqD,EACAD,EACAwR,EACAk2F,EACAh4F,EACAM,EACAJ,EACAE,EACA6E,EACA5b,EACA6F,EACA+oG,EACAvpG,EACA5S,EACAwT,EACAC,EACAE,KAGA,MAAMrsB,EAAa,IAAIsb,gBAGjBw5G,EAAgB,CAAC5hI,EAAKtH,KACtBA,GAAmB,MAAVA,GACXoU,EAAW6U,OAAO3hB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","sources":["webpack:///./scripts/components/checkbox/index.js","webpack:///./scripts/components/panel/panel.js","webpack:///./scripts/components/select/index.js","webpack:///./scripts/constants/RecommendedType.js","webpack:///./scripts/constants/googleAnalyticsCustomDimension.js","webpack:///./scripts/constants/housingProductType.js","webpack:///./scripts/constants/routes.js","webpack:///./scripts/constants/svg-assets.b1.js","webpack:///./scripts/dataTransferObjects/googleAnalyticsEvent.js","webpack:///./scripts/enums/googleAnalytics4EventType.js","webpack:///./scripts/enums/loadingStatus.js","webpack:///./scripts/enums/marketingStatus.js","webpack:///./scripts/enums/pageType.js","webpack:///./scripts/enums/typeaheadLocationType.js","webpack:///./scripts/features/googleAds/index.js","webpack:///./scripts/features/googleAds/redux/actions.js","webpack:///./scripts/enums/googleAdsEventType.js","webpack:///./scripts/dataTransferObjects/googleAdsEvent.js","webpack:///./scripts/services/googleAdsBuilder.js","webpack:///./scripts/features/googleAds/redux/beaconMiddleware.js","webpack:///./scripts/features/googleAnalytics4/index.js","webpack:///./scripts/features/googleAnalytics4/redux/actions.js","webpack:///./scripts/features/googleAnalytics4/redux/beaconMiddleware.js","webpack:///./scripts/features/searchResultsFacets/enums/thankScreenVariation.js","webpack:///./scripts/features/leadGenerators/components/detailsAnchor.js","webpack:///./scripts/features/leadGenerators/components/schedulerAnchor.js","webpack:///./scripts/features/leadGenerators/components/phoneAnchor.js","webpack:///./scripts/features/leadGenerators/components/phoneAnchorCallTracking.js","webpack:///./scripts/features/leadGenerators/components/createAccountAnchor.js","webpack:///./scripts/features/leadGenerators/components/returnToSearchAnchor.js","webpack:///./scripts/features/leadGenerators/services/anchorConstructor.js","webpack:///./scripts/features/leadGenerators/constants/sharedHtml.b1.js","webpack:///./scripts/features/leadGenerators/models/communityInformationLead.js","webpack:///./scripts/features/leadGenerators/models/planInformationLead.js","webpack:///./scripts/features/leadGenerators/models/recommendedBrochureLead.js","webpack:///./scripts/features/leadGenerators/models/specInformationLead.js","webpack:///./scripts/features/leadGenerators/services/leadConstructor.js","webpack:///./scripts/features/leadGenerators/models/buildablePlanBrochureLead.js","webpack:///./scripts/features/leadGenerators/models/communityBrochureLead.js","webpack:///./scripts/features/leadGenerators/models/planBrochureLead.js","webpack:///./scripts/features/leadGenerators/models/specBrochureLead.js","webpack:///./scripts/features/leadGenerators/models/buildablePlanInformationLead.js","webpack:///./scripts/features/leadGenerators/models/communityTourLead.js","webpack:///./scripts/features/leadGenerators/models/planTourLead.js","webpack:///./scripts/features/leadGenerators/models/specTourLead.js","webpack:///./scripts/features/leadGenerators/models/planInformationLeadBasic.js","webpack:///./scripts/features/leadGenerators/models/specInformationLeadBasic.js","webpack:///./scripts/features/leadGenerators/models/communityInformationLeadBasic.js","webpack:///./scripts/features/leadGenerators/models/basicListingInformationLeadBasic.js","webpack:///./scripts/enums/googleAnalyticsEventAction.js","webpack:///./scripts/enums/googleAnalyticsEventCategory.js","webpack:///./scripts/features/leadGenerators/analytics/eventTrackingTdvEventsMixin.js","webpack:///./scripts/features/leadGenerators/analytics/basicLeadTrackingEvent.js","webpack:///./scripts/features/leadGenerators/analytics/eventTrackingNonDirectLeadsMixin.js","webpack:///./scripts/features/leadGenerators/analytics/eventTrackingRealTimeEventsMixin.js","webpack:///./scripts/features/leadGenerators/analytics/eventTrackingTdvMetricsMixin.js","webpack:///./scripts/features/leadGenerators/analytics/brochureTrackingEvent.js","webpack:///./scripts/features/leadGenerators/analytics/informationTracking.js","webpack:///./scripts/features/leadGenerators/analytics/tourTrackingEvent.js","webpack:///./scripts/features/leadGenerators/analytics/askQuestionTrackingEvent.js","webpack:///./scripts/features/leadGenerators/services/taskFlow.js","webpack:///./scripts/features/leadGenerators/components/brochureButton.js","webpack:///./scripts/features/leadGenerators/components/commentsTextArea.js","webpack:///./scripts/features/leadGenerators/components/emailInput.js","webpack:///./scripts/features/leadGenerators/components/nameInput.js","webpack:///./scripts/features/leadGenerators/components/phoneInput.js","webpack:///./scripts/features/leadGenerators/components/recommendedCheckbox.js","webpack:///./scripts/features/leadGenerators/components/zipInput.js","webpack:///./scripts/features/leadGenerators/components/realtorDropdown.js","webpack:///./scripts/features/leadGenerators/components/brochureFormPaid.js","webpack:///./scripts/features/leadGenerators/enums/basicContactVendor.js","webpack:///./scripts/features/leadGenerators/services/basicPrivacyPolicyParagraph.b1.js","webpack:///./scripts/features/leadGenerators/components/informationButtonBasic.js","webpack:///./scripts/features/leadGenerators/components/informationFormBasic.js","webpack:///./scripts/features/leadGenerators/components/informationButton.js","webpack:///./scripts/features/leadGenerators/components/informationFormPaid.js","webpack:///./scripts/features/leadGenerators/components/contactRadioGroup.js","webpack:///./scripts/features/leadGenerators/components/dateInput.js","webpack:///./scripts/features/leadGenerators/components/requestButton.js","webpack:///./scripts/features/leadGenerators/components/tourRadioOptions.js","webpack:///./scripts/features/leadGenerators/components/requestTourForm.js","webpack:///./scripts/features/leadGenerators/components/brochureFormLimitedAvailability.js","webpack:///./scripts/features/leadGenerators/components/askQuestionButton.js","webpack:///./scripts/features/leadGenerators/components/askQuestionFormPaid.js","webpack:///./scripts/features/leadGenerators/components/manufacturedBrochureFormPaid.js","webpack:///./scripts/features/leadGenerators/services/leadGeneratorConstructor.js","webpack:///./scripts/features/leadGenerators/components/recommendedButton.js","webpack:///./scripts/features/leadGenerators/components/skipButton.js","webpack:///./scripts/features/leadGenerators/constants/svgIcons.b1.js","webpack:///./scripts/features/leadGenerators/components/recommendedScreen.js","webpack:///./scripts/features/leadGenerators/components/recommendedButtonBasic.js","webpack:///./scripts/features/leadGenerators/components/recommendedScreenBasic.js","webpack:///./scripts/features/leadGenerators/components/thankScreenAskQuestion.js","webpack:///./scripts/features/leadGenerators/components/thankScreenBasic.js","webpack:///./scripts/features/leadGenerators/components/thankScreenBrochure.js","webpack:///./scripts/features/leadGenerators/components/thankScreenComingSoon.js","webpack:///./scripts/features/leadGenerators/components/thankScreenLimitedAvailability.js","webpack:///./scripts/features/leadGenerators/components/thankScreenTour.js","webpack:///./scripts/features/leadGenerators/components/wrapper.js","webpack:///./scripts/features/leadGenerators/enums/leadFormType.js","webpack:///./scripts/features/leadGenerators/apis/recommendedCommunities.js","webpack:///./scripts/features/leadGenerators/apis/postBrochure.js","webpack:///./scripts/features/leadGenerators/redux/epics.js","webpack:///./scripts/features/leadGenerators/index.js","webpack:///./scripts/features/leadGenerators/apis/postBrochureBasic.js","webpack:///./scripts/apis/getBreadcrumbContent.js","webpack:///./scripts/features/locationContent/components/breadcrumbContentHandler.b1.js","webpack:///./scripts/features/locationContent/components/housingProductLocationContentHandler.js","webpack:///./scripts/apis/getHousingProductSnippetContent.js","webpack:///./scripts/features/locationContent/components/snippetContentHandler.js","webpack:///./scripts/features/locationContent/commands/housingProductLocationContentCommand.js","webpack:///./scripts/features/locationContent/services/commands.js","webpack:///./scripts/features/locationContent/apis/getHousingProductLocationContent.js","webpack:///./scripts/features/locationContent/redux/epics.js","webpack:///./scripts/features/locationContent/index.js","webpack:///./scripts/features/locationContent/redux/selectors.js","webpack:///./scripts/features/locationContent/redux/initialState.js","webpack:///./scripts/features/locationContent/redux/slice.js","webpack:///./scripts/features/popularSearches/enums/popularPillsType.b1.js","webpack:///./scripts/features/routing/components/pageLinkHandler.js","webpack:///./scripts/features/routing/redux/epics.js","webpack:///./scripts/features/routing/index.js","webpack:///./scripts/features/routing/redux/listeners.js","webpack:///./scripts/features/routing/redux/selectors.js","webpack:///./scripts/features/routing/redux/initialState.js","webpack:///./scripts/features/routing/redux/slices.js","webpack:///./scripts/features/routing/services/urlBuilder.js","webpack:///./scripts/features/searchResultsExtendedCard/components/miniCardSlider.js","webpack:///./scripts/features/searchResultsExtendedCard/components/readMore.js","webpack:///./scripts/features/searchResultsExtendedCard/components/extendedCard.js","webpack:///./scripts/features/searchResultsExtendedCard/apis/getExtendedCard.js","webpack:///./scripts/features/searchResultsExtendedCard/redux/epics.js","webpack:///./scripts/features/searchResultsExtendedCard/index.js","webpack:///./scripts/features/searchResultsFacets/enums/activeAdultType.js","webpack:///./scripts/features/searchResultsFacets/components/adultCommunities.js","webpack:///./scripts/features/searchResultsFacets/components/advancedClearButton.b1.js","webpack:///./scripts/features/searchResultsFacets/components/advancedFiltersPanel.b1.js","webpack:///./scripts/features/searchResultsFacets/components/builders.js","webpack:///./scripts/features/searchResultsFacets/components/clearButton.js","webpack:///./scripts/features/searchResultsFacets/components/clearFilters.js","webpack:///./scripts/features/searchResultsFacets/components/communityAmenities.js","webpack:///./scripts/features/searchResultsFacets/components/communityStatus.b1.js","webpack:///./scripts/features/searchResultsFacets/components/garages.js","webpack:///./scripts/features/searchResultsFacets/enums/housingType.js","webpack:///./scripts/features/searchResultsFacets/services/housingTypeConstructor.js","webpack:///./scripts/features/searchResultsFacets/components/singleFamilyHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/customHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/luxuryHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/condosAndTownHomesHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/manufacturedHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/modelHomeHousingType.js","webpack:///./scripts/features/searchResultsFacets/components/defaultHousingType.js","webpack:///./scripts/features/searchResultsFacets/services/housingTypeService.js","webpack:///./scripts/features/searchResultsFacets/components/housingTypeSelect.js","webpack:///./scripts/features/searchResultsFacets/components/livingAreas.js","webpack:///./scripts/features/searchResultsFacets/components/otherFilters.js","webpack:///./scripts/features/searchResultsFacets/components/priceDualRangeSlider.b1.js","webpack:///./scripts/features/searchResultsFacets/components/primaryBedroom.js","webpack:///./scripts/features/searchResultsFacets/components/rvGarage.js","webpack:///./scripts/features/searchResultsFacets/components/schools.b1.js","webpack:///./scripts/features/searchResultsFacets/components/stories.js","webpack:///./scripts/features/searchResultsFacets/enums/locationType.js","webpack:///./scripts/features/searchResultsFacets/enums/moveInDate.js","webpack:///./scripts/features/searchResultsFacets/enums/otherFiltersType.js","webpack:///./scripts/features/searchResultsFacets/enums/planStatus.js","webpack:///./scripts/features/searchResultsFacets/enums/productType.js","webpack:///./scripts/features/searchResultsFacets/enums/resultType.js","webpack:///./scripts/features/searchResultsFacets/enums/sortType.js","webpack:///./scripts/features/searchResultsFacets/enums/specStatus.js","webpack:///./scripts/features/searchResultsFacets/constants/actionTypeGroupsConstants.js","webpack:///./scripts/features/searchResultsFacets/apis/getCounts.js","webpack:///./scripts/features/searchResultsFacets/apis/getBrandsAndSchoolDistricts.js","webpack:///./scripts/features/searchResultsFacets/enums/fetchRequest.js","webpack:///./scripts/features/searchResultsFacets/services/fetchingValidator.js","webpack:///./scripts/features/searchResultsFacets/redux/epics.js","webpack:///./scripts/features/searchResultsFacets/components/priceFilterLabel.b1.js","webpack:///./scripts/features/searchResultsFacets/components/selectMoveInDate.b1.js","webpack:///./scripts/components/radioButton/index.js","webpack:///./scripts/features/searchResultsFacets/components/bedroom.js","webpack:///./scripts/features/searchResultsFacets/components/bathroom.js","webpack:///./scripts/features/searchResultsFacets/components/bedroomAndBathroomFilterLabel.b1.js","webpack:///./scripts/features/searchResultsFacets/index.js","webpack:///./scripts/features/searchResultsFacets/redux/listeners.js","webpack:///./scripts/features/searchResultsFacets/redux/selectors.js","webpack:///./scripts/features/searchResultsFacets/redux/initialState.js","webpack:///./scripts/features/searchResultsFacets/redux/slices.js","webpack:///./scripts/features/searchResultsFacets/services/homeStatusValidator.js","webpack:///./scripts/features/searchResultsFacets/services/moveInDateService.js","webpack:///./scripts/features/searchResultsFacets/services/productTypeService.js","webpack:///./scripts/features/searchResultsFacets/services/resultTypeService.js","webpack:///./scripts/features/searchResultsMap/analytics/searchWithinMap.js","webpack:///./scripts/features/searchResultsMap/apis/getCommunitySummaryCard.js","webpack:///./scripts/features/searchResultsMap/components/boundaries.js","webpack:///./scripts/features/searchResultsMap/apis/getCommunityInteractiveSitePlans.js","webpack:///./scripts/features/searchResultsMap/services/interactiveSitePlan.js","webpack:///./scripts/features/searchResultsMap/components/interactiveSitePlansHandler.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/paidInteractiveSitePlanCommunityCard.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/paidInteractiveSitePlanHousingUnitCard.js","webpack:///./scripts/features/searchResultsMap/components/lotSummaryCard.js","webpack:///./scripts/features/searchResultsMap/components/map.js","webpack:///./scripts/features/searchResultsMap/components/marker.b1.js","webpack:///./scripts/features/searchResultsMap/components/markerSessionHandler.js","webpack:///./scripts/features/searchResultsMap/components/nearbyListingsCarousel.b1.js","webpack:///./scripts/features/searchResultsMap/components/sitePlansHandler.js","webpack:///./scripts/features/searchResultsMap/components/skeletons/summaryCardSkeleton.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/communityLabel.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/homeLabel.b1.js","webpack:///./scripts/features/searchResultsMap/constants/searchParametersConstants.js","webpack:///./scripts/features/searchResultsMap/constants/sitePlansConstants.js","webpack:///./scripts/features/searchResultsMap/constants/svgIcons.b1.js","webpack:///./scripts/features/searchResultsMap/enums/lotPolygonType.js","webpack:///./scripts/features/searchResultsMap/enums/lotStatus.js","webpack:///./scripts/features/searchResultsMap/enums/markerType.js","webpack:///./scripts/features/searchResultsMap/enums/sitePlanLayer.js","webpack:///./scripts/features/searchResultsMap/apis/getMarkers.js","webpack:///./scripts/features/searchResultsMap/services/markersEndpointSelector.js","webpack:///./scripts/features/searchResultsMap/apis/getCommunityNearbyListings.js","webpack:///./scripts/features/searchResultsMap/apis/getBuildablePlanNearbyListings.js","webpack:///./scripts/features/searchResultsMap/apis/getPlanNearbyListings.js","webpack:///./scripts/features/searchResultsMap/apis/getSpecNearbyListings.js","webpack:///./scripts/utils/degressToradians.js","webpack:///./scripts/utils/getDistanceBetweenCoordinates.js","webpack:///./scripts/features/searchResultsMap/services/geoLocationService.js","webpack:///./scripts/utils/parsePriceString.js","webpack:///./scripts/features/searchResultsMap/apis/getHousingUnitSummaryCard.js","webpack:///./scripts/features/searchResultsMap/redux/epics.js","webpack:///./scripts/features/searchResultsMap/index.js","webpack:///./scripts/features/searchResultsMap/redux/observables.js","webpack:///./scripts/features/searchResultsMap/redux/selectors.js","webpack:///./scripts/features/searchResultsMap/redux/initialState.js","webpack:///./scripts/features/searchResultsMap/models/housingDevelopmentMarker.b1.js","webpack:///./scripts/features/searchResultsMap/models/buildablePlanMarker.b1.js","webpack:///./scripts/features/searchResultsMap/models/planUnitMarker.b1.js","webpack:///./scripts/features/searchResultsMap/models/specUnitMarker.b1.js","webpack:///./scripts/features/searchResultsMap/services/processMarkers.js","webpack:///./scripts/features/searchResultsMap/redux/slices.js","webpack:///./scripts/features/searchResultsMap/services/markerSessionService.js","webpack:///./scripts/constants/regexExpressions.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/basicCommunityCard.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/basicPlanCard.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/basicSpecCard.b1.js","webpack:///./scripts/enums/communityType.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/paidCommunityCard.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/paidPlanCard.b1.js","webpack:///./scripts/features/searchResultsMap/components/summaryCard/paidSpecCard.b1.js","webpack:///./scripts/features/searchResultsMap/services/processSummaryCard.js","webpack:///./scripts/utils/base64Transformations.js","webpack:///./scripts/features/searchResultsMap/apis/searchCommunitySitePlans.js","webpack:///./scripts/features/searchResultsMap/models/sitePlanTooltip.js","webpack:///./scripts/features/searchResultsMap/services/sitePlan.js","webpack:///./scripts/features/searchResultsMap/services/unitMarkerService.js","webpack:///./scripts/libraries/segmentAnalyticsLibrary.js","webpack:///./scripts/features/segment/index.js","webpack:///./scripts/features/segment/redux/actions.js","webpack:///./scripts/enums/segmentEventType.js","webpack:///./scripts/middlewares/segment/services/segment.js","webpack:///./scripts/middlewares/segment/services/eventDefinition.js","webpack:///./scripts/dataTransferObjects/segmentEvent.js","webpack:///./scripts/dataTransferObjects/segmentIdentifyEvent.js","webpack:///./scripts/utils/dateExtensions.js","webpack:///./scripts/dataTransferObjects/segmentPageEvent.js","webpack:///./scripts/services/segmentEventBuilder.js","webpack:///./scripts/features/segment/redux/beaconMiddleware.js","webpack:///./scripts/features/speedcurve/redux/slices.js","webpack:///./scripts/features/speedcurve/index.js","webpack:///./scripts/features/speedcurve/redux/actions.js","webpack:///./scripts/middlewares/speedcurveRum/services/speedcurveRum.js","webpack:///./scripts/dataTransferObjects/speedcurveConversion.js","webpack:///./scripts/dataTransferObjects/speedcurveMarkEnd.js","webpack:///./scripts/dataTransferObjects/speedcurveMarkStart.js","webpack:///./scripts/dataTransferObjects/speedcurveTimingMetric.js","webpack:///./scripts/enums/speedcurveEvent.js","webpack:///./scripts/services/speedcurveBuilder.js","webpack:///./scripts/middlewares/speedcurveRum/services/eventsDefinition.js","webpack:///./scripts/features/speedcurve/redux/beaconMiddleware.js","webpack:///./scripts/features/speedcurve/redux/selectors.js","webpack:///./scripts/features/totalDeliveryValue/services/processEvents.js","webpack:///./scripts/features/totalDeliveryValue/redux/slices.js","webpack:///./scripts/features/totalDeliveryValue/components/trackOnDemand.js","webpack:///./scripts/features/totalDeliveryValue/apis/postEvents.js","webpack:///./scripts/features/totalDeliveryValue/redux/epics.js","webpack:///./scripts/features/totalDeliveryValue/index.js","webpack:///./scripts/constants/partner.js","webpack:///./scripts/modules/deviceCapabilities.js","webpack:///./scripts/features/trackingProperties/redux/selectors.js","webpack:///./scripts/features/trackingProperties/index.js","webpack:///./scripts/features/userProfile/services/getListingInformationForPendingSave.js","webpack:///./scripts/features/userProfile/components/favorites.js","webpack:///./scripts/libraries/googleOneTapLibrary.js","webpack:///./scripts/features/userProfile/apis/loginWithGoogleOneTap.js","webpack:///./scripts/features/userProfile/services/parseJsonWebToken.js","webpack:///./scripts/features/userProfile/components/googleOneTapAuthentication.js","webpack:///./scripts/features/userProfile/components/signUpValidator.js","webpack:///./scripts/features/userProfile/components/auth0BaseConfiguration.js","webpack:///./scripts/features/userProfile/components/mainAuthentication.js","webpack:///./scripts/features/userProfile/components/modal.js","webpack:///./scripts/features/userProfile/components/neustarListener.js","webpack:///./scripts/modules/cookieManager.js","webpack:///./scripts/features/userProfile/components/sessionAliveInteraction.js","webpack:///./scripts/features/userProfile/components/userMenu.b1.js","webpack:///./scripts/features/userProfile/constants/auth0Constants.js","webpack:///./scripts/features/userProfile/constants/sessionStorageConstants.js","webpack:///./scripts/features/userProfile/enums/favoriteType.js","webpack:///./scripts/features/userProfile/index.js","webpack:///./scripts/features/userProfile/redux/listeners.js","webpack:///./scripts/features/userProfile/redux/selectors.js","webpack:///./scripts/features/userProfile/redux/initialState.js","webpack:///./scripts/features/userProfile/redux/slices.js","webpack:///./scripts/features/utm/redux/selectors.js","webpack:///./scripts/layout/components/dataLayer.js","webpack:///./scripts/layout/constants/pageLayoutNames.js","webpack:///./scripts/layout/constants/resultPresentationType.js","webpack:///./scripts/layout/enums/layoutBreakpoint.js","webpack:///./scripts/layout/redux/selectors.js","webpack:///./scripts/layout/services/resultsPresentationService.js","webpack:///./scripts/layout/redux/uiStateSlice.js","webpack:///./scripts/layout/services/messageService.js","webpack:///./scripts/layout/services/modalService.js","webpack:///./scripts/libraries/appNexus.b1.js","webpack:///./scripts/libraries/authLibrary.js","webpack:///./scripts/libraries/mapLibrary.b1.js","webpack:///./scripts/middlewares/googleTagManager/services/googleTagManager.js","webpack:///./scripts/middlewares/googleTagManager/index.js","webpack:///./scripts/pages/searchResults/analytics/analyticsDimensions.js","webpack:///./scripts/pages/searchResults/analytics/facets.js","webpack:///./scripts/pages/searchResults/analytics/favorites.js","webpack:///./scripts/pages/searchResults/analytics/leads.js","webpack:///./scripts/pages/searchResults/analytics/pagination.js","webpack:///./scripts/pages/searchResults/analytics/phoneEventListener.js","webpack:///./scripts/pages/searchResults/analytics/schedulerEventListener.js","webpack:///./scripts/pages/searchResults/analytics/thankYouEventListener.js","webpack:///./scripts/pages/searchResults/analytics/uiUpdates.js","webpack:///./scripts/pages/searchResults/components/backForwardHandler.js","webpack:///./scripts/pages/searchResults/components/backToTopHandler.js","webpack:///./scripts/pages/searchResults/components/builderDirectory/builderBrandCard.js","webpack:///./scripts/pages/searchResults/components/containerUiUpdater.b1.js","webpack:///./scripts/pages/searchResults/components/eventTracking/googleAdsEventsHandler.js","webpack:///./scripts/pages/searchResults/services/eventTracking.js","webpack:///./scripts/pages/searchResults/components/eventTracking/googleAnalytics4EventsHandler.js","webpack:///./scripts/utils/impressionEventObserver.js","webpack:///./scripts/pages/searchResults/components/eventTracking/segmentEventsHandler.js","webpack:///./scripts/pages/searchResults/components/eventTracking/speedcurveEventsHandler.js","webpack:///./scripts/pages/searchResults/components/facets/index.js","webpack:///./scripts/pages/searchResults/components/facets/pageSize.js","webpack:///./scripts/pages/searchResults/components/facets/panels.js","webpack:///./scripts/pages/searchResults/components/facets/searchWithinMap.js","webpack:///./scripts/pages/searchResults/components/facets/sort.js","webpack:///./scripts/pages/searchResults/components/filterPanel.js","webpack:///./scripts/pages/searchResults/components/formCertifier.js","webpack:///./scripts/pages/searchResults/components/geoProximityHandler.js","webpack:///./scripts/components/hamburgerMenu/hamburgerMenu.b1.js","webpack:///./scripts/pages/searchResults/components/header/hamburgerMenu.js","webpack:///./scripts/pages/searchResults/components/images/handlerErrorImages.js","webpack:///./scripts/utils/randomNumber.js","webpack:///./scripts/features/searchResultsFacets/apis/getResults.js","webpack:///./scripts/pages/searchResults/components/eventTracking/totalDeliveryValue.js","webpack:///./scripts/pages/searchResults/components/noResults/handlerNoResultsSection.b1.js","webpack:///./scripts/pages/searchResults/components/listViewHandler.js","webpack:///./scripts/pages/searchResults/components/nativeAdsLoader.b1.js","webpack:///./scripts/pages/searchResults/components/noResults/hintsSection.js","webpack:///./scripts/pages/searchResults/components/noResults/noResultsClearButton.js","webpack:///./scripts/features/popularSearches/services/popularSearchesService.js","webpack:///./scripts/features/popularSearches/components/pill.b1.js","webpack:///./scripts/features/popularSearches/components/pillsSection.b1.js","webpack:///./scripts/pages/searchResults/components/popularSearchesPillsHandler.js","webpack:///./scripts/pages/searchResults/components/priceHighLink.js","webpack:///./scripts/pages/searchResults/components/resultTabs/resultTab.b1.js","webpack:///./scripts/pages/searchResults/components/resultTabs/communitiesTab.b1.js","webpack:///./scripts/pages/searchResults/components/resultTabs/buildersTab.js","webpack:///./scripts/pages/searchResults/components/resultTabs/buildOnYourLotLocationsTab.js","webpack:///./scripts/pages/searchResults/components/resultTabs/customHomesTab.js","webpack:///./scripts/pages/searchResults/components/resultTabs/manufacturedHomesTab.js","webpack:///./scripts/pages/searchResults/components/resultTabs/manufacturedLocationsTab.js","webpack:///./scripts/pages/searchResults/services/resultTabConfiguration.js","webpack:///./scripts/pages/searchResults/components/resultTabs/homesTab.b1.js","webpack:///./scripts/pages/searchResults/analytics/eventTabConfiguration.js","webpack:///./scripts/pages/searchResults/components/resultTypeTabs.b1.js","webpack:///./scripts/pages/searchResults/components/resultsLazyLoader.js","webpack:///./scripts/pages/searchResults/components/skeletonHandler.js","webpack:///./scripts/components/skeletons/cardSkeleton.js","webpack:///./scripts/pages/searchResults/services/getHousingCard.js","webpack:///./scripts/pages/searchResults/models/specCard.js","webpack:///./scripts/pages/searchResults/models/planCard.js","webpack:///./scripts/pages/searchResults/models/communityCard.js","webpack:///./scripts/pages/searchResults/models/basicListing.js","webpack:///./scripts/pages/searchResults/components/standardCard.b1.js","webpack:///./scripts/apis/getTypeaheadOptions.js","webpack:///./scripts/components/typeahead/typeaheadKeyboardHandler.b1.js","webpack:///./scripts/components/typeahead/geoLocationtypeahead.b1.js","webpack:///./scripts/pages/searchResults/components/typeahead/typeahead.b1.js","webpack:///./scripts/pages/searchResults/components/viewToggler.b1.js","webpack:///./scripts/pages/searchResults/enums/urlSubdirectoryTypes.js","webpack:///./scripts/pages/searchResults/redux/actions.js","webpack:///./scripts/pages/searchResults/redux/listeners.js","webpack:///./scripts/pages/searchResults/redux/observables.js","webpack:///./scripts/pages/searchResults/redux/selectors.js","webpack:///./scripts/pages/searchResults/routing/builderName.js","webpack:///./scripts/pages/searchResults/routing/index.js","webpack:///./scripts/pages/searchResults/routing/locations.js","webpack:///./scripts/pages/searchResults/routing/mapCoordinatesUrl.js","webpack:///./scripts/pages/searchResults/routing/pageUrls.js","webpack:///./scripts/pages/searchResults/routing/paging.js","webpack:///./scripts/pages/searchResults/routing/queryString.js","webpack:///./scripts/pages/searchResults/routing/subdirectory.js","webpack:///./scripts/pages/searchResults/components/pagination/pager.js","webpack:///./scripts/pages/searchResults/components/pagination/paginationNumberLink.b1.js","webpack:///./scripts/pages/searchResults/components/pagination/paginationBar.b1.js","webpack:///./scripts/pages/searchResults/searchResults.js","webpack:///./scripts/pages/searchResults/services/contentTemplateTypeHandler.js","webpack:///./scripts/pages/searchResults/services/pageUrlBuilder.js","webpack:///./scripts/features/userProfile/apis/getUserProfile.js","webpack:///./scripts/features/userProfile/apis/getUserFavorites.js","webpack:///./scripts/features/userProfile/apis/saveFavorite.js","webpack:///./scripts/features/userProfile/apis/deleteFavorite.js","webpack:///./scripts/features/userProfile/services/getHousingProductType.js","webpack:///./scripts/features/userProfile/models/specProductType.js","webpack:///./scripts/features/userProfile/models/planProductType.js","webpack:///./scripts/features/userProfile/models/communityProductType.js","webpack:///./scripts/features/userProfile/redux/epics.js","webpack:///./scripts/redux/rootEpics.js","webpack:///./scripts/features/userProfile/services/getFavoriteFromState.js","webpack:///./scripts/redux/store.js","webpack:///./scripts/services/googleAnalytics.js","webpack:///./scripts/dataTransferObjects/googleAnalytics4Event.js","webpack:///./scripts/modules/getCentralStandardTime.js","webpack:///./scripts/services/googleAnalytics4EventBuilder.js","webpack:///./scripts/services/marketingStatusValidator.js","webpack:///./scripts/utils/camelCase.js","webpack:///./scripts/utils/cleanObject/cleanObject.js","webpack:///./scripts/utils/createPictureImageSources.js","webpack:///./scripts/utils/equals.js","webpack:///./scripts/utils/getLifestyleImage.js","webpack:///./scripts/utils/stringExtensions.js","webpack:///./scripts/utils/urlExtension.js","webpack:///./images/icons/dynamic/callForPriceCommunityActiveIcon.svg","webpack:///./images/icons/dynamic/callForPriceCommunityIcon.b1.svg","webpack:///./images/icons/dynamic/callForPriceHomeActiveIcon.svg","webpack:///./images/icons/dynamic/callForPriceHomeIcon.b1.svg","webpack:///./images/icons/dynamic/close-small-16.svg","webpack:///./images/icons/dynamic/location.svg","webpack:///./images/icons/dynamic/priceReducedIcon.svg","webpack:///./images/icons/dynamic/ratingStarIcon.svg","webpack:///./images/icons/dynamic/triangle-marker-hover.svg","webpack:///./images/icons/dynamic/triangle-marker.svg"],"sourcesContent":["import { fromEvent, map, filter, distinctUntilChanged } from \"rxjs\";\r\nimport { store$ } from \"@redux/store\";\r\n\r\nconst hasValue = (value) => !!value;\r\nclass CheckboxGroup {\r\n constructor(element){\r\n this.element = element;\r\n this.checkbox$ = fromEvent(element, 'change').pipe(\r\n map((event) => event.target),\r\n map((target) => target.closest('[data-group]')),\r\n map((parent) => Array.from(parent?.querySelectorAll(':checked'))?.map(option => option.value)))\r\n }\r\n \r\n setSelector(selector){\r\n // if we provide a selector in the constructor, we will use it to sync the checkboxes with the store's value.\r\n if(selector){\r\n const onStoreChange$ = store$.pipe(map(selector), filter(hasValue), distinctUntilChanged());\r\n onStoreChange$.subscribe(checkboxes => {\r\n // get all the checkboxes in the group\r\n this.element?.querySelectorAll('[type=\"checkbox\"]').forEach((checkbox) => {\r\n const value = checkbox.value;\r\n checkbox.checked = Boolean(checkboxes[value])\r\n });\r\n });\r\n }\r\n }\r\n\r\n getObservable(){\r\n return this.checkbox$;\r\n }\r\n}\r\n\r\nexport default CheckboxGroup;","class Panel {\r\n /**\r\n * closePanel: Closes this panel.\r\n */\r\n closePanel() {\r\n this.panelToggle.checked = false;\r\n }\r\n\r\n setUpPanelEvents() {\r\n // needed to do this since .bind creates a new reference every time,\r\n // and we need to remove be able to remove the event listener once it's closed\r\n const handler = this.handleClickOutsideofElement.bind(this);\r\n document.removeEventListener('click', handler);\r\n\r\n const applyButton = this.container.querySelector('[data-apply]');\r\n this.panelToggle = this.container.querySelector('[data-panel-toggle]');\r\n\r\n applyButton?.addEventListener('click', this.closePanel.bind(this));\r\n document.addEventListener('click', handler);\r\n }\r\n\r\n /**\r\n * closes the panel if the click is outside the panel\r\n */\r\n handleClickOutsideofElement(event) {\r\n if (this.container.contains(event.target)) {\r\n return;\r\n }\r\n\r\n this.closePanel();\r\n }\r\n\r\n constructor(configuration) {\r\n this.container = configuration.container;\r\n\r\n this.container.addEventListener('click', this.setUpPanelEvents.bind(this), {once: true});\r\n }\r\n}\r\n\r\nexport default Panel;","import { fromEvent, map } from \"rxjs\";\r\n\r\nclass Select {\r\n constructor(element){\r\n this.select$ = fromEvent(element, 'change').pipe(\r\n map((event) => event.target.value)\r\n );\r\n }\r\n\r\n getObservable(){\r\n return this.select$;\r\n }\r\n}\r\n\r\nexport default Select;","export default class RecommendedType {\r\n\r\n static RecommendedPaid() {\r\n return new RecommendedType('recommendedScreen');\r\n }\r\n\r\n static RecommendedBasic() {\r\n return new RecommendedType('recommendedScreenBasic');\r\n }\r\n\r\n constructor(type) {\r\n this.type = type;\r\n }\r\n\r\n getName() {\r\n return this.type;\r\n }\r\n}\r\n","export default class GoogleAnalyticsCustomDimensions {\r\n static MarketId() {\r\n return new GoogleAnalyticsCustomDimensions('marketId');\r\n }\r\n\r\n static PartnerName() {\r\n return new GoogleAnalyticsCustomDimensions('partnerName');\r\n }\r\n\r\n static BuilderCorporation() {\r\n return new GoogleAnalyticsCustomDimensions('builderCorp');\r\n }\r\n\r\n static CommunityName() {\r\n return new GoogleAnalyticsCustomDimensions('communityName');\r\n }\r\n\r\n static City() {\r\n return new GoogleAnalyticsCustomDimensions('city');\r\n }\r\n\r\n static PageType() {\r\n return new GoogleAnalyticsCustomDimensions('pageType');\r\n }\r\n\r\n static PartnerId() {\r\n return new GoogleAnalyticsCustomDimensions('partnerId');\r\n }\r\n\r\n static MarketName() {\r\n return new GoogleAnalyticsCustomDimensions('marketName');\r\n }\r\n\r\n static CommunityId() {\r\n return new GoogleAnalyticsCustomDimensions('communityId');\r\n }\r\n\r\n static UserId() {\r\n return new GoogleAnalyticsCustomDimensions('i_uid');\r\n }\r\n\r\n static CurrentPageNumber() {\r\n return new GoogleAnalyticsCustomDimensions('currentPageNumber');\r\n }\r\n\r\n static NeustarResponse() {\r\n return new GoogleAnalyticsCustomDimensions('n_response');\r\n }\r\n\r\n static OffMarket() {\r\n return new GoogleAnalyticsCustomDimensions('OffMarket');\r\n }\r\n\r\n static BuilderId() {\r\n return new GoogleAnalyticsCustomDimensions('builderId');\r\n }\r\n\r\n static BrandName() {\r\n return new GoogleAnalyticsCustomDimensions('brandName');\r\n }\r\n\r\n static PlanId() {\r\n return new GoogleAnalyticsCustomDimensions('planId');\r\n }\r\n\r\n static SpecId() {\r\n return new GoogleAnalyticsCustomDimensions('specId');\r\n }\r\n\r\n static IsPaid() {\r\n return new GoogleAnalyticsCustomDimensions('IsPaid');\r\n }\r\n\r\n static MatchingResults() {\r\n return new GoogleAnalyticsCustomDimensions('matchingResults');\r\n }\r\n\r\n static Counties() {\r\n return new GoogleAnalyticsCustomDimensions('counties');\r\n }\r\n\r\n static Location() {\r\n return new GoogleAnalyticsCustomDimensions('location');\r\n }\r\n\r\n static PriceReduction() {\r\n return new GoogleAnalyticsCustomDimensions('priceReduction');\r\n }\r\n\r\n static SearchWithinMapActivated() {\r\n return new GoogleAnalyticsCustomDimensions('searchWithinMapActivated');\r\n }\r\n\r\n constructor(dimension) {\r\n this.dimension = dimension;\r\n }\r\n\r\n getName() {\r\n return this.dimension;\r\n }\r\n}\r\n","export default class HousingProductType {\r\n\r\n static Spec() {\r\n return new HousingProductType('spec');\r\n }\r\n\r\n static Plan() {\r\n return new HousingProductType('plan');\r\n }\r\n\r\n static Community() {\r\n return new HousingProductType('community');\r\n }\r\n\r\n static BasicListing() {\r\n return new HousingProductType('basicListing');\r\n }\r\n\r\n constructor(type) {\r\n this.type = type;\r\n }\r\n\r\n getName() {\r\n return this.type;\r\n }\r\n}\r\n","/**\r\n * The idea for this filter is to have a centralized list of all routes used in the front-end,\r\n * Using destructuring assignment and tree-shaking, we can only load those routes that we need\r\n * making sure that if the routes change in the future, we can easily update them in the front-end\r\n * without requiring changes in multiple places\r\n *\r\n * an example of how to load routes can be seen below:\r\n *\r\n * import { getTypeaheadOptions } from 'constants/routes'\r\n */\r\n\r\n/*\r\n * Gets the value of the `href` attribute of the `base` element in the HTML document.\r\n * If the `base` element does not exist or does not have an `href` attribute, `baseElementUrl` will be `undefined`.\r\n *\r\n * Using document.querySelector('base').href could induce error in the code if the base element does not exist\r\n * or the href attribute is undefined, as it fallbacks to the document's fallback base URL, which is the current\r\n * Document's URL.\r\n */\r\nconst baseElementUrl = document.querySelector('base')?.attributes?.href?.value;\r\n\r\n/*\r\n * Object that contains properties that can be useful for configuring the API requests\r\n * or other network requests in the application.\r\n */\r\nconst configuration = {\r\n baseUrl: baseElementUrl || window.location.origin,\r\n};\r\n\r\nexport const getAdConfiguration = `${configuration.baseUrl}/ajax/getadconfiguration`;\r\nexport const getBreadcrumbContent = `${configuration.baseUrl}/ajax/getonpagebreadcrumb`;\r\nexport const getCommunitiesResults = `${configuration.baseUrl}/ajax/getResults`;\r\nexport const getHousingProductSnippetContent = `${configuration.baseUrl}/ajax/gethousingproductsnippetscontent`;\r\nexport const getListingCounts = `${configuration.baseUrl}/ajax/getResultCounts`;\r\nexport const getOnPageContent = `${configuration.baseUrl}/ajax/gethousingproductlocationcontentajax`;\r\nexport const getResultFacets = `${configuration.baseUrl}/ajax/getResultFacets`;\r\nexport const getTypeaheadOptions = `${configuration.baseUrl}/gettypeaheadoptions`;\r\nexport const leadsBasicCommunitySubmission = `${configuration.baseUrl}/ajax/leads/basiccommunitysubmission/`;\r\nexport const leadsBasicPlanSubmission = `${configuration.baseUrl}/ajax/leads/basicplansubmission/`;\r\nexport const leadsBasicSpecSubmission = `${configuration.baseUrl}/ajax/leads/basicspecsubmission/`;\r\nexport const leadsBasicListingSubmission = `${configuration.baseUrl}/ajax/leads/basiclistingsubmission/`;\r\nexport const leadsGetRecommendedCommunities = `${configuration.baseUrl}/ajax/leads/getrecommendedcommunities/`;\r\nexport const leadsPaidCommunitySubmission = `${configuration.baseUrl}/ajax/leads/paidcommunitysubmission/`;\r\nexport const leadsPaidPlanSubmission = `${configuration.baseUrl}/ajax/leads/paidplansubmission/`;\r\nexport const leadsPaidSpecSubmission = `${configuration.baseUrl}/ajax/leads/paidspecsubmission/`;\r\nexport const leadsRecommendedCommunitySubmission = `${configuration.baseUrl}/ajax/leads/recommendedcommunitysubmission/`;\r\nexport const mapGetCommunitiesPoints = `${configuration.baseUrl}/ajax/communities/getcommunitypoints`;\r\nexport const mapGetHomesPoints = `${configuration.baseUrl}/ajax/homes/gethomepoints`;\r\nexport const totalDeliveryValueCommunityLogger = `${configuration.baseUrl}/communitylogger`;\r\nexport const totalDeliveryValuePlanLogger = `${configuration.baseUrl}/planlogger`;\r\nexport const totalDeliveryValueSpecLogger = `${configuration.baseUrl}/speclogger`;\r\nexport const userDeleteFavorite = `${configuration.baseUrl}/user/deleteFavorite`;\r\nexport const userGetProfile = `${configuration.baseUrl}/getUserProfile`;\r\nexport const userProfileGetFavorites = `${configuration.baseUrl}/getUserFavorites`;\r\nexport const userSaveFavorite = `${configuration.baseUrl}/user/saveFavorite`;\r\nexport const marketingcampaignUnsubscribe = `${configuration.baseUrl}/marketingcampaign/unsubscribemarketingcampaign`;\r\nexport const marketingcampaignUnsubscribeFeedback = `${configuration.baseUrl}/marketingcampaign/unsubscribefeedback`;\r\nexport const googleOneTapLogin = `${configuration.baseUrl}/ajax/googleOneTapLogin`;\r\nexport const getCommunityNearbyListingsInfo = `${configuration.baseUrl}/ajax/getcommunitynearbylistings`;\r\nexport const getBuildablePlanNearbylistingsInfo = `${configuration.baseUrl}/ajax/getbuildableplannearbylistings`;\r\nexport const getPlanNearbyListingsInfo = `${configuration.baseUrl}/ajax/getplannearbylistings`;\r\nexport const getSpecNearbyListingsInfo = `${configuration.baseUrl}/ajax/getspecnearbylistings`;\r\nexport const listingCounts = `${configuration.baseUrl}/learn/dynamic/getlistingcounts`;\r\nexport const getArticleSuggestions = `${configuration.baseUrl}/learn/dynamic/getarticlesuggestions`;\r\nexport const getCommunitiesForYou = `${configuration.baseUrl}/learn/dynamic/getcommunitiesforyou`;\r\nexport const getHomesForYou = `${configuration.baseUrl}/learn/dynamic/gethomesforyou`;\r\nexport const getMetroSpecificArticles = `${configuration.baseUrl}/learn/dynamic/getmetroarearelatedarticles`;\r\nexport const getMostRecentArticles = `${configuration.baseUrl}/learn/dynamic/getmostrecentarticles`\r\nexport const blogRequestAccessToCacheManager = `${configuration.baseUrl}/util/blogcachemanager/requestaccess`;\r\nexport const deleteItemInAllServers = `${configuration.baseUrl}/util/cachemanager/deleteiteminallservers`;\r\nexport const purgeCdnCache = `${configuration.baseUrl}/util/purge-cdn-cache`;\r\nexport const learningCenter = `${configuration.baseUrl}/learn/`;\r\nexport const getArticleSearchResults = `${configuration.baseUrl}/learn/dynamic/getresults/`;\r\nexport const getArticleCountResults = `${configuration.baseUrl}/learn/dynamic/getcountsresults/`;\r\nexport const searchCommunitySitePlans = `${configuration.baseUrl}/ajax/searchcommunitysiteplans`;\r\nexport const getCommunityInteractiveSitePlanMarkers = `${configuration.baseUrl}/ajax/getcommunityinteractivesiteplanmarkers`;\r\nexport const getCommunitySummaryCard = `${configuration.baseUrl}/ajax/getcommunitysummarycard`;\r\nexport const getHousingUnitSummaryCard = `${configuration.baseUrl}/ajax/gethousingunitsummarycard`;","import backArrowIcon from '@icons/backArrow';\r\nimport closeIcon from '@icons/closeIcon';\r\nimport closeModalIcon from '@icons/closeModal';\r\nimport priceReducedIcon from '@icons/dynamic/priceReducedIcon';\r\nimport callForPriceCommunityIcon from '@icons/dynamic/callForPriceCommunityIcon';\r\nimport callForPriceCommunityActiveIcon from '@icons/dynamic/callForPriceCommunityActiveIcon';\r\nimport callForPriceHomeIcon from '@icons/dynamic/callForPriceHomeIcon';\r\nimport callForPriceHomeActiveIcon from '@icons/dynamic/callForPriceHomeActiveIcon';\r\nimport ratingStarIcon from '@icons/dynamic/ratingStarIcon';\r\nimport markerArrowIcon from '@icons/dynamic/triangle-marker';\r\nimport markerArrowHoverIcon from '@icons/dynamic/triangle-marker-hover';\r\nimport closeSmallIcon from '@icons/dynamic/close-small-16';\r\nimport thanksContentIcon from '@icons/thanksContent';\r\nimport locationIcon from '@icons/dynamic/location';\r\nimport interactiveSitePlanIcon from '@icons/interactiveSitePlan.svg';\r\n\r\n// modal icons\r\nimport thankYouHeart from '@icons/modal/thankYouHeart';\r\nimport thankYouEmail from '@icons/modal/thankYouEmail';\r\nimport thankYouPhone from '@icons/modal/thankYouPhone';\r\nimport thankYouSuccess from '@icons/modal/thankYouSuccess';\r\n\r\n// toast icons\r\nimport circleCheck from '@icons/circleCheck';\r\nimport circleWarning from '@icons/circleWarning';\r\n\r\n// these are static icons, webpack will return the path to the file instead of the icon itself\r\nexport const backArrowSvg = ``;\r\nexport const closeIconSvg = ``;\r\nexport const closeModalIconSvg = ``;\r\nexport const thanksContentIconSvg = ``;\r\nexport const interactiveSitePlanSvg = ``;\r\n\r\nexport const thankYouHeartSvg = ``;\r\nexport const thankYouEmailSvg = ``;\r\nexport const thankYouPhoneSvg = ``;\r\nexport const thankYouSuccessSvg = ``;\r\n\r\n// These are dynamic icons, these are served as svg-in-js and are included in the .js bundle\r\n// you should only consider using dynamic icons if you need to change the color or any other\r\n// attribute of the icon itself.\r\nexport const callForPriceCommunityIconSvg = callForPriceCommunityIcon;\r\nexport const callForPriceCommunityActiveIconSvg = callForPriceCommunityActiveIcon;\r\nexport const callForPriceHomeIconSvg = callForPriceHomeIcon;\r\nexport const callForPriceHomeActiveIconSvg = callForPriceHomeActiveIcon;\r\nexport const priceReducedIconSvg = priceReducedIcon;\r\nexport const ratingStartIconSvg = ratingStarIcon;\r\nexport const locationIconSvg = locationIcon;\r\nexport const markerArrowIconSvg = markerArrowIcon;\r\nexport const markerArrowHoverIconSvg = markerArrowHoverIcon;\r\nexport const closeSmallIconSvg = closeSmallIcon;\r\n\r\nexport const circleCheckSvg = ``;\r\nexport const circleWarningSvg = ``;\r\n","class GoogleAnalyticsEvent {\r\n constructor(category, action, label, customDimensions = {}) {\r\n this.eventCategory = category;\r\n this.eventAction = action;\r\n this.eventLabel = label;\r\n this.event = 'GAEvent';\r\n\r\n // Use this property to add custom dimensions that are part of the\r\n // event you are tracking. These properties will be pushed to the data layer.\r\n Object.assign(this, customDimensions);\r\n }\r\n}\r\n\r\nexport default GoogleAnalyticsEvent;","export default class GoogleAnalytics4EventType {\r\n /**\r\n * This is a static method that returns an instance of the \"Event\" class.\r\n * @returns The `Event` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Event'` as an argument.\r\n */\r\n static get Event() {\r\n return this.getInstance('Event');\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n Event: GoogleAnalytics4EventType.Event,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * Gets an instance of a GoogleAnalytics4EventType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the GoogleAnalytics4EventType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the GoogleAnalytics4EventType class that is being created.\r\n *\r\n * @returns an instance of `GoogleAnalytics4EventType` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new GoogleAnalytics4EventType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(GoogleAnalytics4EventType, 'instances', { value: {} });\r\n","/* \r\n Defines a LoadingStatus object with four static properties: failed, idle, loading, and succeeded.\r\n The statuses indicates the state of an asynchronous operation.\r\n\r\n It provides the methods for creating and retrieving instances of the object.\r\n*/\r\nexport default class LoadingStatus {\r\n /**\r\n * This is a static getter function that returns an instance of the \"Failed\" loading status.\r\n * This status indicates the asynchronous operation has finished but returned an error.\r\n *\r\n * @returns it returns the instance of the class with the name `'failed'`.\r\n */\r\n static get Failed() {\r\n return this.getInstance('failed');\r\n }\r\n\r\n /**\r\n * This is a static getter function that returns an instance of the \"Idle\" loading status.\r\n * This status indicates the asynchronous operation is not started.\r\n *\r\n * @returns it returns the instance of the class with the name `'idle'`.\r\n */\r\n static get Idle() {\r\n return this.getInstance('idle');\r\n }\r\n\r\n /**\r\n * This is a static getter function that returns an instance of the \"Loading\" loading status.\r\n * This status indicates the asynchronous operation has started but it hasn't finished.\r\n *\r\n * @returns it returns the instance of the class with the name `'loading'`.\r\n */\r\n static get Loading() {\r\n return this.getInstance('loading');\r\n }\r\n\r\n /**\r\n * This is a static getter function that returns an instance of the \"Succeeded\" loading status.\r\n * This status indicates the asynchronous operation has finished without errors.\r\n *\r\n * @returns it returns the instance of the class with the name `'succeeded'`.\r\n */\r\n static get Succeeded() {\r\n return this.getInstance('succeeded');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n failed: LoadingStatus.Failed,\r\n idle: LoadingStatus.Idle,\r\n loading: LoadingStatus.Loading,\r\n succeeded: LoadingStatus.Succeeded,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * This function returns an instance of the LoadingStatus class based on a given key, creating a new\r\n * instance if one does not already exist.\r\n *\r\n * @param key - a unique identifier used to create and retrieve instances of the LoadingStatus class.\r\n * It is used to ensure that only one instance of the LoadingStatus class is created for each unique key value.\r\n *\r\n * @returns returns an instance of the `LoadingStatus` class with the specified `key`.\r\n * If an instance with the specified `key` already exists, it returns that instance instead of creating a new one.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new LoadingStatus(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(LoadingStatus, 'instances', { value: {} });\r\n","/**\r\n * @classdesc The `MarketingStatus` class serves as the source of truth for current marketing statuses and their codes.\r\n */\r\nexport default class MarketingStatus {\r\n /**\r\n * Gets the instance for the ComingSoon marketing status.\r\n * @returns {MarketingStatus} The instance for the ComingSoon status.\r\n */\r\n static get ComingSoon() {\r\n return this.getInstance('C');\r\n }\r\n\r\n /**\r\n * Gets the instance for the Active marketing status.\r\n * @returns {MarketingStatus} The instance for the Active status.\r\n */\r\n static get Active() {\r\n return this.getInstance('N');\r\n }\r\n\r\n /**\r\n * Gets the instance for the GrandOpening marketing status.\r\n * @returns {MarketingStatus} The instance for the GrandOpening status.\r\n */\r\n static get GrandOpening() {\r\n return this.getInstance('G');\r\n }\r\n\r\n /**\r\n * Gets the instance for the CloseOut marketing status.\r\n * @returns {MarketingStatus} The instance for the CloseOut status.\r\n */\r\n static get CloseOut() {\r\n return this.getInstance('X');\r\n }\r\n\r\n /**\r\n * Gets the instance for the ComingSoonGrandOpening marketing status.\r\n * @returns {MarketingStatus} The instance for the ComingSoonGrandOpening status.\r\n */\r\n static get ComingSoonGrandOpening() {\r\n return this.getInstance('CG');\r\n }\r\n\r\n /**\r\n * Converts a key to the corresponding marketing status instance.\r\n * @param {string} key The key representing a marketing status.\r\n * @returns {MarketingStatus|null} The marketing status instance or null if not found.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n C: MarketingStatus.ComingSoon,\r\n N: MarketingStatus.Active,\r\n G: MarketingStatus.GrandOpening,\r\n X: MarketingStatus.CloseOut,\r\n CG: MarketingStatus.ComingSoonGrandOpening,\r\n };\r\n return statusMap[key] || null;\r\n }\r\n\r\n /**\r\n * Gets or creates an instance of the `MarketingStatus` class based on the provided key.\r\n * @param {string} key The key representing a marketing status.\r\n * @returns {MarketingStatus} The marketing status instance.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new MarketingStatus(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * Creates a new instance of the `MarketingStatus` class.\r\n * @param {string} name The name of the marketing status.\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Returns the name of the marketing status as a string.\r\n * @returns {string} The name of the marketing status.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(MarketingStatus, 'instances', { value: {} });\r\n","import { UrlSubdirectoryTypes } from \"features/searchResultsFacets\";\r\n\r\nexport default class PageType {\r\n /**\r\n * The static get Homes function returns an instance of the 'Home_Results' class.\r\n * @returns The method is returning an instance of the 'Home_Results' class.\r\n */\r\n static get Homes() {\r\n return this.getInstance('Home_Results');\r\n }\r\n\r\n /**\r\n * The function returns an instance of the 'Community_Results' class.\r\n * @returns The method `get Communities()` is returning the result of calling the `getInstance`\r\n * method with the argument `'Community_Results'`.\r\n */\r\n static get Communities() {\r\n return this.getInstance('Community_Results');\r\n }\r\n\r\n /**\r\n * The function returns an instance of the 'Builder_Results' class.\r\n * @returns The method `get Builders()` is returning the result of calling the `getInstance`\r\n * method with the argument `'Builder_Results'`.\r\n */\r\n static get Builders() {\r\n return this.getInstance('Builder_Results');\r\n }\r\n\r\n /**\r\n * The function returns an instance of the 'boylresults' class.\r\n * @returns The method `get BuildOnYorLotLocations()` is returning the result of calling the `getInstance`\r\n * method with the argument `'boylresults'`.\r\n */\r\n static get BuildOnYorLotLocations() {\r\n return this.getInstance('boylresults');\r\n }\r\n \r\n /**\r\n * The function returns an instance of the 'Custom_Homes' class.\r\n * @returns The method `get CustomHomes()` is returning the result of calling the `getInstance`\r\n * method with the argument `'Custom_Homes'`.\r\n */\r\n static get CustomHomes() {\r\n return this.getInstance('Custom_Homes');\r\n }\r\n \r\n /**\r\n * The function returns an instance of the 'Manufactured_Homes' class.\r\n * @returns The method `get ManufacturedHomes()` is returning the result of calling the `getInstance`\r\n * method with the argument `'Manufactured_Homes'`.\r\n */\r\n static get ManufacturedHomes() {\r\n return this.getInstance('Manufactured_Homes');\r\n }\r\n \r\n /**\r\n * The function returns an instance of the 'Manufactured_Results' class.\r\n * @returns The method `get Manufactured()` is returning the result of calling the `getInstance`\r\n * method with the argument `'Manufactured_Results'`.\r\n */\r\n static get Manufactured() {\r\n return this.getInstance('Manufactured_Results');\r\n }\r\n\r\n static get LearningCenter() {\r\n return this.getInstance('Learning Center');\r\n }\r\n \r\n /**\r\n * The function \"fromKey\" takes a key as input and returns the corresponding value from a\r\n * predefined map.\r\n * @param key - The `key` parameter is a string that represents a key in the `statusMap` object.\r\n * It should be formatted like {product type}-{result type}.\r\n * @returns The value associated with the given key in the statusMap object is being returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n [UrlSubdirectoryTypes.Communities.toString()]: PageType.Communities,\r\n [UrlSubdirectoryTypes.Homes.toString()]: PageType.Homes,\r\n [UrlSubdirectoryTypes.Builders.toString()]: PageType.Builders,\r\n [UrlSubdirectoryTypes.CondoDevelopment.toString()]: PageType.Communities,\r\n [UrlSubdirectoryTypes.CondosAndTownHomes.toString()]: PageType.Homes,\r\n [UrlSubdirectoryTypes.SingleFamilyHomes.toString()]: PageType.Homes,\r\n [UrlSubdirectoryTypes.SingleFamilyCommunities.toString()]: PageType.Communities,\r\n [UrlSubdirectoryTypes.CustomHomes.toString()]: PageType.CustomHomes,\r\n [UrlSubdirectoryTypes.OnYourLot.toString()]: PageType.BuildOnYorLotLocations,\r\n [UrlSubdirectoryTypes.ManufacturedHomes.toString()]: PageType.ManufacturedHomes,\r\n [UrlSubdirectoryTypes.ManufacturedLocations.toString()]: PageType.Manufactured,\r\n [UrlSubdirectoryTypes.FloorPlans.toString()]: PageType.Homes,\r\n [UrlSubdirectoryTypes.ModelHomes.toString()]: PageType.Homes,\r\n [UrlSubdirectoryTypes.LearningCenter.toString()]: PageType.LearningCenter,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * Gets an instance of a PageType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the PageType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the PageType class that is being created.\r\n *\r\n * @returns an instance of `PageType` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new PageType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(PageType, 'instances', { value: {} });\r\n","export default class TypeaheadLocationType {\r\n\r\n // TODO: review the rest of the search types in the typehead.\r\n /**\r\n * This is a static method that returns a new instance of the LocationType class with the type\r\n * 'city'.\r\n * @returns A new instance of the `LocationType` class with the value of `'city'` as its parameter.\r\n */\r\n static get City() {\r\n return new TypeaheadLocationType('city');\r\n }\r\n\r\n /**\r\n * The above code defines a static getter function that returns a new instance of a LocationType object\r\n * with the type 'market'.\r\n * @returns A new instance of the `LocationType` class with the type `market` is being returned.\r\n */\r\n static get Market() {\r\n return new TypeaheadLocationType('market');\r\n }\r\n\r\n /**\r\n * This is a static method that returns a new instance of the LocationType class with the type\r\n * 'community'.\r\n * @returns A new instance of the `LocationType` class with the value of `'community'` as its parameter.\r\n */\r\n static get Community() {\r\n return new TypeaheadLocationType('community');\r\n }\r\n\r\n /**\r\n * This is a static method that returns a new instance of the LocationType class with the type\r\n * 'masterPlannedCommunity'.\r\n * @returns A new instance of the `LocationType` class with the value of `'masterPlannedCommunity'` as its parameter.\r\n */\r\n static get MasterPlannedCommunity() {\r\n return new TypeaheadLocationType('masterPlannedCommunity');\r\n }\r\n\r\n /**\r\n * The function returns a new LocationType object with the type 'zip'.\r\n * @returns A new instance of the `LocationType` class with the argument `'zip'`.\r\n */\r\n static get Zip() {\r\n return new TypeaheadLocationType('zip');\r\n }\r\n\r\n /**\r\n * The function returns a new instance of a LocationType object with the type 'synthetic'.\r\n * @returns A new instance of the LocationType class with the type 'synthetic'.\r\n */\r\n static get Synthetic() {\r\n return new TypeaheadLocationType('syntheticGeo');\r\n }\r\n\r\n /**\r\n * The function returns a new instance of a LocationType object with the type 'county'.\r\n * @returns A new instance of the LocationType class with the type 'county'.\r\n */\r\n static get County() {\r\n return new TypeaheadLocationType('county');\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * This is a toString() method in JavaScript that returns the name property of an object as a string.\r\n * @returns The `toString()` method is returning the value of the `name` property of the object.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}","import googleAdsEvent from './redux/actions';\r\n\r\nrequire('./redux/beaconMiddleware');\r\n\r\nexport default googleAdsEvent;\r\n","import { createAction } from '@reduxjs/toolkit';\r\n\r\n// Event Action of type Track\r\n/* `const googleAdsEvent = createAction('googleAds/event');` is creating an action creator \r\nfunction using the `createAction` function from the `@reduxjs/toolkit` library. This action creator function will\r\nreturn an action object with a `type` property set to `'googleAds/event'` when it is called. This\r\naction can then be dispatched to the Redux store to trigger a state update or other side effects. */\r\nconst googleAdsEvent = createAction('googleAds/event');\r\n\r\nexport default googleAdsEvent;\r\n","export default class GoogleAdsEventType {\r\n /**\r\n * This is a static method that returns an instance of the \"Event\" class.\r\n * @returns The `Event` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Event'` as an argument.\r\n */\r\n static get Event() {\r\n return this.getInstance('Event');\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n Event: GoogleAdsEventType.Event,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * Gets an instance of a GoogleAdsEventType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the GoogleAdsEventType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the GoogleAdsEventType class that is being created.\r\n *\r\n * @returns an instance of `GoogleAdsEventType` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new GoogleAdsEventType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(GoogleAdsEventType, 'instances', { value: {} });\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched the google ads event.\r\n */\r\nclass GoogleAdsEvent {\r\n constructor(eventName, enhancedConversionData = {}) {\r\n this.event = 'googleAdsEvent';\r\n this.eventName = eventName;\r\n this.ecData = enhancedConversionData;\r\n }\r\n\r\n /**\r\n * The function returns the value of the eventName property.\r\n * @returns The value of the variable `eventName`.\r\n */\r\n getEvent() {\r\n return this.event;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"ecData\" property.\r\n * @returns The `ecData` property is being returned.\r\n */\r\n getEnhancedConversionData() {\r\n return this.ecData;\r\n }\r\n}\r\n\r\nexport default GoogleAdsEvent;\r\n","import { store } from '@redux/store';\r\nimport GoogleAdsEvent from 'dataTransferObjects/googleAdsEvent';\r\nimport GoogleAdsEventType from 'enums/googleAdsEventType';\r\nimport getTrackingCommonProperties from 'features/trackingProperties';\r\n\r\n/**\r\n * The function to get the enhanced conversion properties to Google ads event.\r\n * Read more at https://support.google.com/google-ads/answer/9888656?hl=en\r\n * @returns object containing the common properties for enhanced conversion.\r\n */\r\nconst getEnhancedConversionProperties = () => {\r\n const state = store.getState();\r\n const commonProperties = getTrackingCommonProperties(state);\r\n\r\n const enhancedConversionProperties = {\r\n email: commonProperties.email,\r\n phone_number: commonProperties.phone,\r\n };\r\n\r\n return enhancedConversionProperties;\r\n};\r\n\r\nconst createTrackEvent = (eventName) => {\r\n const data = getEnhancedConversionProperties();\r\n\r\n return () => new GoogleAdsEvent(eventName, data);\r\n};\r\n\r\n/**\r\n * The getGoogleAdsEvent function returns a GoogleAdsEvent object.\r\n *\r\n * @return An GoogleAnalytics4Event object\r\n */\r\nconst getGoogleAdsEvent = (eventType, eventName) => {\r\n if (eventType === GoogleAdsEventType.Event) {\r\n return createTrackEvent(eventName);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport default getGoogleAdsEvent;\r\n","import { createMiddleware } from 'redux-beacon';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport GoogleAdsEventType from 'enums/googleAdsEventType';\r\nimport getGoogleAdsEvent from 'services/googleAdsBuilder';\r\nimport googleAdsEvent from './actions';\r\n\r\n/**\r\n * The eventsMap function is a mapping of Redux actions to google ads events.\r\n * It returns an array of GoogleAdsEvent events\r\n * @param action Determine which event to return\r\n *\r\n * @return An array of events\r\n */\r\nconst eventsMap = (action) => {\r\n const payload = action.payload;\r\n if (action.type === googleAdsEvent.type) {\r\n const event = debounceEvent(100, getGoogleAdsEvent(GoogleAdsEventType.Event, payload.eventName));\r\n return event;\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMap, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);\r\n","import googleAnalytics4Event from './redux/actions';\r\n\r\nrequire('./redux/beaconMiddleware');\r\n\r\nexport default googleAnalytics4Event;\r\n","import { createAction } from '@reduxjs/toolkit';\r\n\r\n// Event Action of type Track\r\n/* `const googleAnalytics4Event = createAction('googleAnalytics4/event');` is creating an action creator function using\r\nthe `createAction` function from the `@reduxjs/toolkit` library. This action creator function will\r\nreturn an action object with a `type` property set to `'googleAnalytics4/event'` when it is called. This\r\naction can then be dispatched to the Redux store to trigger a state update or other side effects. */\r\nconst googleAnalytics4Event = createAction('googleAnalytics4/event');\r\n\r\nexport default googleAnalytics4Event;\r\n","import { createMiddleware } from 'redux-beacon';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport GoogleAnalytics4EventType from 'enums/googleAnalytics4EventType';\r\nimport { getGoogleAnalytics4Event } from 'services/googleAnalytics4EventBuilder';\r\nimport googleAnalytics4Event from './actions';\r\n\r\n/**\r\n * The eventsMap function is a mapping of Redux actions to GoogleAnalytics4 events.\r\n * It returns an array of GoogleAnalytics4 events, which are objects with the following shape:\r\n * {\r\n * eventType: string, // The name of the event (e.g., 'track')\r\n * fieldsObj: object, // An object containing all properties for this event type (e.g., {eventName})\r\n * }\r\n *\r\n * @param action Determine which event to return\r\n *\r\n * @return An array of events\r\n */\r\nconst eventsMap = (action) => {\r\n if (action.type === googleAnalytics4Event.type) {\r\n const payload = action.payload;\r\n const event = debounceEvent(\r\n 100,\r\n getGoogleAnalytics4Event(GoogleAnalytics4EventType.Event, payload.eventName, payload.customProperties)\r\n );\r\n return event;\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMap, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);\r\n","export default class ThankScreenVariation {\r\n static get ComingSoon() {\r\n return this.getInstance('comingSoon');\r\n }\r\n\r\n static get AskQuestion() {\r\n return this.getInstance('askQuestion');\r\n }\r\n\r\n static get Brochure() {\r\n return this.getInstance('brochure');\r\n }\r\n\r\n static get Tour() {\r\n return this.getInstance('tour');\r\n }\r\n\r\n static get LimitedAvailability() {\r\n return this.getInstance('limitedAvailability');\r\n }\r\n\r\n static get Basic() {\r\n return this.getInstance('basic');\r\n }\r\n\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n comingSoon: ThankScreenVariation.ComingSoon,\r\n askQuestion: ThankScreenVariation.AskQuestion,\r\n brochure: ThankScreenVariation.Brochure,\r\n tour: ThankScreenVariation.Tour,\r\n limitedAvailability: ThankScreenVariation.LimitedAvailability,\r\n basic: ThankScreenVariation.Basic\r\n };\r\n\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new ThankScreenVariation(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(ThankScreenVariation, 'instances', { value: {} });\r\n","/**\r\n * Represents a DetailsAnchor component that generates an HTML anchor element with a URL and an ID.\r\n * @class\r\n */\r\nexport default class DetailsAnchor {\r\n /**\r\n * Creates a new instance of DetailsAnchor.\r\n * @constructor\r\n * @param {string} url - The URL to be used in the anchor element.\r\n */\r\n constructor() {\r\n this.anchorId = 'detailPageAnchor';\r\n }\r\n\r\n /**\r\n * Sets the binding required for the anchor details.\r\n */\r\n bindEvents() {\r\n this.getAnchor().addEventListener('click', this.onClickEvent.bind(this));\r\n }\r\n\r\n /**\r\n * Dispatches a custom event named 'detailAnchorClicked' with details of the lisitng clicked\r\n */\r\n onClickEvent() {\r\n document.body.dispatchEvent(\r\n new CustomEvent('detailAnchorClicked', {\r\n detail: {\r\n listingId: this.listingId,\r\n listingType: this.listingType,\r\n },\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Sets the URL for the details anchor.\r\n * @param {string} url - The URL to set.\r\n */\r\n setUrl(url) {\r\n this.url = url;\r\n }\r\n\r\n /**\r\n * Sets the listing id for the details anchor.\r\n * @param {number} id - The id of the listing.\r\n */\r\n setListingId(id) {\r\n this.listingId = id;\r\n }\r\n\r\n /**\r\n * Sets the listing type for the details anchor.\r\n * @param {number} id - The type of the listing.\r\n */\r\n setListingType(type) {\r\n this.listingType = type;\r\n }\r\n\r\n /**\r\n * Gets the HTML anchor element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getAnchor() {\r\n return document.getElementById(this.anchorId);\r\n }\r\n\r\n /**\r\n * Gets the HTML code for the anchor element.\r\n * @returns {string} The HTML code for the anchor element.\r\n */\r\n getHtml() {\r\n return this.url\r\n ? `\r\n \r\n More Details\r\n `\r\n : ``;\r\n }\r\n}\r\n","/**\r\n * Represents a Scheduler Anchor component.\r\n * @class\r\n */\r\nexport default class SchedulerAnchor {\r\n /**\r\n * Creates a new instance of SchedulerAnchor.\r\n * @constructor\r\n * @param {string} url - The URL to schedule a tour.\r\n */\r\n constructor() {\r\n this.anchorId = 'schedulerAnchor';\r\n }\r\n\r\n /**\r\n * Sets the URL for the scheduler anchor.\r\n * @param {string} url - The URL to set.\r\n */\r\n setUrl(url) {\r\n this.url = url;\r\n }\r\n\r\n /**\r\n * Binds events to the SchedulerAnchor component.\r\n * @function bindEvents\r\n * @memberof SchedulerAnchor\r\n * @instance\r\n */\r\n bindEvents() {\r\n const anchor = this.getAnchor();\r\n anchor?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('schedulerAnchorClick')));\r\n }\r\n\r\n /**\r\n * Gets the anchor element by ID.\r\n * @returns {HTMLElement} The anchor element.\r\n */\r\n getAnchor() {\r\n return document.getElementById(this.anchorId);\r\n }\r\n\r\n /**\r\n * Gets the HTML for the scheduler anchor.\r\n * @returns {string} The HTML for the scheduler anchor.\r\n */\r\n getHtml() {\r\n return this.url\r\n ? `\r\n \r\n Don’t Miss Out!
Schedule a Tour Now\r\n
`\r\n : ``;\r\n}\r\n}\r\n ","/**\r\n * Represents a phone anchor component that displays a phone number and allows the user to call it.\r\n */\r\nexport default class PhoneAnchor {\r\n /**\r\n * Creates a new instance of the PhoneAnchor class.\r\n * @param {string} phoneNumber - The phone number to display.\r\n */\r\n constructor() {\r\n this.anchorId = 'nhs_phoneAnchor';\r\n this.buttonId = 'nhs_phoneButton';\r\n }\r\n\r\n /**\r\n * Sets the phone number and removes any dashes.\r\n * @param {string} phoneNumber - The phone number to set.\r\n */\r\n setPhoneNumber(phoneNumber) {\r\n this.phoneNumber = phoneNumber?.replaceAll('-', '');\r\n this.userFriendlyPhone = phoneNumber;\r\n }\r\n\r\n /**\r\n * Reveals the phone number by hiding the button and showing the anchor.\r\n */\r\n revealPhone() {\r\n const anchor = this.getPhoneAnchor();\r\n const button = this.getPhoneButton();\r\n\r\n button.setAttribute('hidden', 'true');\r\n anchor.removeAttribute('hidden');\r\n }\r\n\r\n /**\r\n * Binds the click event to the phone button.\r\n */\r\n bindEvents() {\r\n const button = this.getPhoneButton();\r\n button?.addEventListener('click', this.revealPhone.bind(this));\r\n\r\n const anchor = this.getAnchor();\r\n anchor?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('phoneAnchorClick')));\r\n }\r\n\r\n /**\r\n * Gets the phone button element.\r\n * @returns {HTMLElement} The phone button element.\r\n */\r\n getPhoneButton() {\r\n return document.getElementById(this.buttonId);\r\n }\r\n\r\n /**\r\n * Gets the phone anchor element.\r\n * @returns {HTMLElement} The phone anchor element.\r\n */\r\n getPhoneAnchor() {\r\n return document.getElementById(this.anchorId);\r\n }\r\n\r\n /**\r\n * Returns the phone anchor.\r\n * @returns {string} The phone anchor.\r\n */\r\n getAnchor() {\r\n return this.getPhoneAnchor();\r\n }\r\n\r\n /**\r\n * Gets the HTML for the phone anchor component.\r\n * @returns {string} The HTML for the phone anchor component.\r\n */\r\n getHtml() {\r\n if (!this.phoneNumber) {\r\n return '';\r\n }\r\n\r\n return `\r\n \r\n \r\n `;\r\n }\r\n}\r\n","/**\r\n * Represents a phone anchor for call tracking.\r\n */\r\nexport default class PhoneAnchorCallTracking {\r\n /**\r\n * Creates a new instance of PhoneAnchorCallTracking.\r\n */\r\n constructor() {\r\n this.anchorId = 'nhs_phoneCallTrackingAnchor';\r\n }\r\n\r\n /**\r\n * Sets the phone number for the anchor.\r\n * @param {string} phoneNumber - The phone number to set.\r\n */\r\n setPhoneNumber(phoneNumber) {\r\n this.phoneNumber = phoneNumber.replaceAll('-', '');\r\n this.userFriendlyPhone = phoneNumber;\r\n }\r\n\r\n /**\r\n * Binds events to the PhoneAnchorCallTracking component.\r\n * @function bindEvents\r\n * @memberof PhoneAnchorCallTracking\r\n * @instance\r\n */\r\n bindEvents() {\r\n const anchor = this.getAnchor();\r\n anchor?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('phoneAnchorTrackingClick')));\r\n }\r\n \r\n /**\r\n * Gets the phone anchor element.\r\n * @returns {HTMLElement} - The phone anchor element.\r\n */\r\n getPhoneAnchor() {\r\n return document.getElementById(this.anchorId);\r\n }\r\n\r\n /**\r\n * Returns the phone anchor.\r\n * @returns {string} The phone anchor.\r\n */\r\n getAnchor() {\r\n return this.getPhoneAnchor();\r\n }\r\n\r\n /**\r\n * Gets the HTML for the phone anchor.\r\n * @returns {string} - The HTML for the phone anchor.\r\n */\r\n getHtml() {\r\n if (!this.phoneNumber) {\r\n return '';\r\n }\r\n\r\n return `\r\n \r\n Don’t Miss Out!
${this.userFriendlyPhone}\r\n
`;\r\n }\r\n}\r\n","/**\r\n * Represents a create account component.\r\n */\r\nexport default class CreateAccountAnchor {\r\n /**\r\n * Creates a new instance of CreateAccountAnchor.\r\n * @constructor\r\n */\r\n constructor() {\r\n this.buttonId = 'createAccountBtn';\r\n }\r\n\r\n /**\r\n * Binds events to the CreateAccountAnchor component.\r\n * @function bindEvents\r\n * @memberof CreateAccountAnchor\r\n * @instance\r\n */\r\n bindEvents() {\r\n const anchor = this.getAnchor();\r\n anchor?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('createAccountAnchorClick')));\r\n }\r\n\r\n /**\r\n * Gets the anchor element by ID.\r\n * @returns {HTMLElement} The anchor element.\r\n */\r\n getAnchor() {\r\n return document.getElementById(this.buttonId);\r\n }\r\n\r\n /**\r\n * Gets the HTML for the create account anchor component.\r\n * @returns {string} The HTML for the create account anchor component.\r\n */\r\n getHtml() {\r\n return `\r\n `;\r\n }\r\n}","/**\r\n * Represents a return to search component.\r\n */\r\nexport default class ReturnToSearchAnchor {\r\n /**\r\n * Creates a new instance of ReturnToSearchAnchor.\r\n * @constructor\r\n */\r\n constructor() {\r\n this.buttonId = 'returnToSearchBtn';\r\n }\r\n\r\n /**\r\n * Gets the anchor element by ID.\r\n * @returns {HTMLElement} The anchor element.\r\n */\r\n getAnchor() {\r\n return document.getElementById(this.buttonId);\r\n }\r\n\r\n /**\r\n * Gets the HTML for the return to search anchor component.\r\n * @returns {string} The HTML for the return to search anchor component.\r\n */\r\n getHtml() {\r\n return `\r\n `;\r\n }\r\n}","import DetailsAnchor from '../components/detailsAnchor';\r\nimport SchedulerAnchor from '../components/schedulerAnchor';\r\nimport PhoneAnchor from '../components/phoneAnchor';\r\nimport PhoneAnchorCallTracking from '../components/phoneAnchorCallTracking';\r\nimport CreateAccountAnchor from '../components/createAccountAnchor';\r\nimport ReturnToSearchAnchor from '../components/returnToSearchAnchor';\r\n\r\n/**\r\n * Returns a contact builder anchor element based on the modal information and listing information provided.\r\n * @param {Object} modalInformation - The modal information object.\r\n * @param {string} modalInformation.url - The URL for the listing's detail page.\r\n * @param {Object} modalInformation.listingInformation - The listing information object.\r\n * @param {string} modalInformation.listingInformation.schedulerUrl -The scheduler URL.\r\n * @param {string} modalInformation.listingInformation.phoneNumber The phone number.\r\n * @param {boolean} modalInformation.listingInformation.hasCallTracking if the phone number has call tracking.\r\n * @returns {Object} - The anchor element.\r\n */\r\nfunction getContactBuilderAnchor(modalInformation) {\r\n const { url, listingInformation } = modalInformation;\r\n const { schedulerUrl, phoneNumber, hasCallTracking } = listingInformation;\r\n const anchors = [];\r\n\r\n // instantiate all the possible anchor elements and add them to the anchors list\r\n if (schedulerUrl) {\r\n const schedulerAnchor = new SchedulerAnchor();\r\n schedulerAnchor.setUrl(schedulerUrl);\r\n anchors.push({ anchor: schedulerAnchor, condition: true });\r\n }\r\n\r\n if (phoneNumber && hasCallTracking === 'True') {\r\n const phoneCallTrackingAnchor = new PhoneAnchorCallTracking();\r\n phoneCallTrackingAnchor.setPhoneNumber(phoneNumber);\r\n anchors.push({ anchor: phoneCallTrackingAnchor, condition: true });\r\n }\r\n\r\n if (phoneNumber) {\r\n const phoneAnchor = new PhoneAnchor();\r\n phoneAnchor.setPhoneNumber(phoneNumber);\r\n anchors.push({ anchor: phoneAnchor, condition: true });\r\n }\r\n\r\n // always instantiate the details anchor.\r\n const detailAnchor = new DetailsAnchor();\r\n detailAnchor.setUrl(url);\r\n detailAnchor.setListingId(listingInformation.id);\r\n detailAnchor.setListingType(listingInformation.type);\r\n anchors.push({ anchor: detailAnchor, condition: true });\r\n\r\n // Find the first anchor that has a true condition.\r\n return anchors.find(({ condition }) => condition)?.anchor;\r\n}\r\n\r\n/**\r\n * Returns an anchor element based on the user logged status.\r\n * @param {boolean} isLoggedIn if the user is logged in.\r\n * @returns {Object} - The anchor element.\r\n */\r\nfunction getInternalBrowsingAnchor(isLoggedIn) {\r\n if (isLoggedIn) {\r\n return new ReturnToSearchAnchor();\r\n }\r\n return new CreateAccountAnchor();\r\n}\r\n\r\nexport { getContactBuilderAnchor, getInternalBrowsingAnchor };\r\n","import { backArrowSvg, closeIconSvg } from 'constants/svg-assets';\r\n\r\nexport const backButton = ``;\r\n\r\nexport const privacyPolicyParagraph = `
By providing your name and contact information and clicking the {0} button, you consent and agree to receive marketing communications from NewHomeSource and {1} selected above, including emails, calls or text messages using an automatic telephone dialing system or an artificial or prerecorded voice. Your agreement is not a condition to purchasing any property, goods or services, and you may call us instead of submitting the information online. You also acknowledge and agree that you can revoke your authorization at any time. Your consent herein also applies to any future registration on national or state Do-No-Call lists. For mobile phones, standard message and data charges apply. Consult our Privacy Policy for additional information, including unsubscribe options. You also agree \r\nto our Privacy Policy, including TCPA Policy and Terms of Use.
`;\r\n\r\nexport const closeButton = ``;\r\n\r\nexport const recommendedPolicyParagraph = `
By providing your name and contact information and clicking the\r\n{0} button, you consent and agree to receive marketing communications from NewHomeSource and the builder(s) selected above,\r\nincluding emails, calls or text messages using an automatic telephone dialing system or an artificial or prerecorded voice. Your agreement is not a\r\ncondition to purchasing any property, goods or services, and you may call us instead of submitting the information online. You also acknowledge and\r\nagree that you can revoke your authorization at any time. Your consent herein also applies to any future registration on national or state Do-No-Call\r\nlists. For mobile phones, standard message and data charges apply. Consult our Privacy Policy for additional information, including unsubscribe options.\r\nYou also agree to our Privacy Policy, including TCPA Policy and Terms of Use.
`;","/* This class represents a lead of type More Information for a community. */\r\nexport default class CommunityInformationLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postCommunityBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n }\r\n }\r\n ","/* This class represents a lead of type Information for a plan. */\r\nexport default class PlanInformationLead {\r\n constructor(formData) {\r\n this.planId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postPlanBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n }\r\n ","/* This class represents a lead of type Free Brochure for recommended communities. */\r\n\r\nexport default class RecommendedBrochureLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.type = 'postRecommendedBrochure';\r\n this.recoComms = RecommendedBrochureLead.getRecommendedCommunities(formData);\r\n this.email = formData.email;\r\n this.zip = formData.postalCode;\r\n this.international = formData.livesOutside;\r\n this.phone = formData.phone;\r\n this.firstName = formData.firstName;\r\n this.lastName = formData.lastName;\r\n this.marketId = formData.marketId;\r\n this.builderId = formData.builderId;\r\n this.fromPage = formData.fromPage;\r\n }\r\n\r\n /**\r\n * Gets an array with the recommended communities information selected by the user.\r\n * @param {Object} formData with the form inputs to be submited. \r\n */\r\n static getRecommendedCommunities(formData) {\r\n const recommendations = [];\r\n const recommendationsKeys = Object.keys(formData).filter((key) => key.includes('RecoComms'));\r\n recommendationsKeys.forEach((key) => recommendations.push(JSON.parse(formData[key])));\r\n\r\n return recommendations;\r\n };\r\n}\r\n","/* This class represents a lead of type More Information for a spec. */\r\nexport default class SpecInformationLead {\r\n constructor(formData) {\r\n this.specId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postSpecBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n }\r\n ","import BuildablePlanBrochureLead from '../models/buildablePlanBrochureLead';\r\nimport BuildablePlanInformationLead from '../models/buildablePlanInformationLead';\r\nimport CommunityInformationLeadBasic from '../models/communityInformationLeadBasic';\r\nimport CommunityBrochureLead from '../models/communityBrochureLead';\r\nimport CommunityInformationLead from '../models/communityInformationLead';\r\nimport CommunityTourLead from '../models/communityTourLead';\r\nimport PlanBrochureLead from '../models/planBrochureLead';\r\nimport PlanInformationLead from '../models/planInformationLead';\r\nimport PlanInformationLeadBasic from '../models/planInformationLeadBasic';\r\nimport PlanTourLead from '../models/planTourLead';\r\nimport RecommendedBrochureLead from '../models/recommendedBrochureLead';\r\nimport SpecBrochureLead from '../models/specBrochureLead';\r\nimport SpecInformationLead from '../models/specInformationLead';\r\nimport SpecInformationLeadBasic from '../models/specInformationLeadBasic';\r\nimport SpecTourLead from '../models/specTourLead';\r\nimport BasicListingInformationLeadBasic from '../models/basicListingInformationLeadBasic';\r\n\r\nconst leadConstructor = new Map();\r\n\r\nleadConstructor.set('buildeablePlan-brochure', BuildablePlanBrochureLead);\r\nleadConstructor.set('community-brochure', CommunityBrochureLead);\r\nleadConstructor.set('plan-brochure', PlanBrochureLead);\r\nleadConstructor.set('spec-brochure', SpecBrochureLead);\r\nleadConstructor.set('recommended', RecommendedBrochureLead);\r\nleadConstructor.set('buildeablePlan-information', BuildablePlanInformationLead);\r\nleadConstructor.set('community-information', CommunityInformationLead);\r\nleadConstructor.set('plan-information', PlanInformationLead);\r\nleadConstructor.set('spec-information', SpecInformationLead);\r\nleadConstructor.set('community-tour', CommunityTourLead);\r\nleadConstructor.set('plan-tour', PlanTourLead);\r\nleadConstructor.set('spec-tour', SpecTourLead);\r\nleadConstructor.set('plan-information-basic', PlanInformationLeadBasic);\r\nleadConstructor.set('spec-information-basic', SpecInformationLeadBasic);\r\nleadConstructor.set('community-information-basic', CommunityInformationLeadBasic);\r\nleadConstructor.set('basicListing-information-basic', BasicListingInformationLeadBasic);\r\n\r\n\r\n/**\r\n * Returns the class constructor to create a lead generator.\r\n *\r\n * @param data - The information to build the lead for the housing product or service.\r\n */\r\nexport default (data) => {\r\n const generator = leadConstructor.get(data.type);\r\n\r\n if (!generator) {\r\n return null;\r\n }\r\n\r\n return new generator.prototype.constructor(data);\r\n};\r\n","/* This class represents a lead of type Free Brochure for a Buildable Plan. */\r\nexport default class BuildablePlanBrochureLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postBuildeablePlanBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n\r\n // Represents Free Brochure.\r\n this.leadAction = 'fb';\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n\r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n \r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n }\r\n}\r\n","/* This class represents a lead of type Free Brochure for a community. */\r\nexport default class CommunityBrochureLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postCommunityBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n\r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n }\r\n}\r\n","/* This class represents a lead of type Free Brochure for a plan. */\r\nexport default class PlanBrochureLead {\r\n constructor(formData) {\r\n this.planId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postPlanBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n\r\n // Represents Free Brochure.\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n\r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n}\r\n","/* This class represents a lead of type Free Brochure for a spec. */\r\nexport default class SpecBrochureLead {\r\n constructor(formData) {\r\n this.specId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postSpecBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.realtorQuestionAnswerId = formData.realtorQuestion;\r\n\r\n // Represents Free Brochure.\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n\r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n}\r\n","/* This class represents a lead of type More Information for a Buildable Plan. */\r\nexport default class BuildablePlanInformationLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postBuildeablePlanBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = 'ri';\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n }\r\n }\r\n ","/* This class represents a lead of type Tour Lead for a community. */\r\nexport default class CommunityTourLead {\r\n constructor(formData) {\r\n this.communityId = formData.id;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postCommunityBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n this.date = formData.date;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n \r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n }\r\n }\r\n ","/* This class represents a lead of type Tour Lead for a plan. */\r\nexport default class PlanTourLead {\r\n constructor(formData) {\r\n this.planId = formData.id;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postPlanBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n this.date = formData.date;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n \r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n }\r\n ","/* This class represents a lead of type Tour Lead for a spec. */\r\nexport default class SpecTourLead {\r\n constructor(formData) {\r\n this.specId = formData.id;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.type = 'postSpecBrochure';\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.preferredContactMethod = formData.preferredContactMethod;\r\n this.date = formData.date;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n this.builderName = properties.brandName;\r\n this.communityName = properties.communityName;\r\n this.communityId = properties.communityId;\r\n }\r\n }\r\n ","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport PlanInformationLead from \"./planInformationLead\";\r\n\r\n/* This class represents a lead of type More Information for a basic plan. */\r\nexport default class PlanInformationLeadBasic extends PlanInformationLead {\r\n constructor(formData) {\r\n super(formData);\r\n this.type = 'postPlanBrochureBasic';\r\n this.xxTrustedFormCertUrl = formData.xxTrustedFormCertUrl;\r\n }\r\n\r\n static getLeadSubmitedAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\"TDV Events\", \"Direct Leads\", \"Search-CTA-Learn-More\")\r\n }\r\n }\r\n ","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport SpecInformationLead from \"./specInformationLead\";\r\n\r\n/* This class represents a lead of type More Information for a basic spec. */\r\nexport default class SpecInformationLeadBasic extends SpecInformationLead {\r\n constructor(formData) {\r\n super(formData);\r\n this.type = 'postSpecBrochureBasic';\r\n this.xxTrustedFormCertUrl = formData.xxTrustedFormCertUrl;\r\n }\r\n\r\n static getLeadSubmitedAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\"TDV Events\", \"Direct Leads\", \"Search-CTA-Learn-More\")\r\n }\r\n }","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport CommunityInformationLead from \"./communityInformationLead\";\r\n\r\n/* This class represents a lead of type More Information for a basic community. */\r\nexport default class CommunityInformationLeadBasic extends CommunityInformationLead {\r\n constructor(formData) {\r\n super(formData);\r\n this.type = 'postCommunityBrochureBasic';\r\n this.xxTrustedFormCertUrl = formData.xxTrustedFormCertUrl;\r\n }\r\n\r\n static getLeadSubmitedAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\"TDV Events\", \"Direct Leads\", \"Search-CTA-Learn-More\")\r\n }\r\n }\r\n ","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\n\r\n/* This class represents a lead of type More Information for a basic listing. */\r\nexport default class BasicListingInformationLeadBasic {\r\n constructor(formData) {\r\n this.type = 'postBasicListingBrochureBasic';\r\n this.xxTrustedFormCertUrl = formData.xxTrustedFormCertUrl;\r\n this.listingId = formData.id;\r\n this.comments = formData.comments;\r\n this.includeRecommendations = formData.includeRecommended;\r\n this.mailAddress = formData.email;\r\n this.name = formData.name;\r\n this.userPhoneNumber = formData.phone;\r\n this.leadAction = formData.leadAction;\r\n this.fromPage = formData.fromPage;\r\n this.excludeRecommendations = formData.excludeRecommendations;\r\n \r\n if (formData.postalCode) {\r\n this.userPostalCode = formData.postalCode;\r\n } else {\r\n this.livesOutside = true;\r\n }\r\n }\r\n\r\n setHousingInformation(properties) {\r\n this.marketId = properties.marketId;\r\n this.marketName = properties.marketName;\r\n }\r\n\r\n static getLeadSubmitedAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\"TDV Events\", \"Direct Leads\", \"Search-CTA-Learn-More\")\r\n }\r\n }","export default class GoogleAnalyticsEventAction {\r\n static get DirectLeads() {\r\n return this.getInstance('Direct Leads');\r\n }\r\n\r\n static get NonDirectLeads() {\r\n return this.getInstance('RCL NonDirect leads');\r\n }\r\n\r\n static get Leads() {\r\n return this.getInstance('Leads');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n R: GoogleAnalyticsEventAction.DirectLeads,\r\n A: GoogleAnalyticsEventAction.Leads,\r\n 'RCL NonDirect leads': GoogleAnalyticsEventAction.NonDirectLeads,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new GoogleAnalyticsEventAction(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(GoogleAnalyticsEventAction, 'instances', { value: {} });\r\n","export default class GoogleAnalyticsEventCategory {\r\n static get TdvMetrics() {\r\n return this.getInstance('TDV Metrics');\r\n }\r\n\r\n static get TdvEvents() {\r\n return this.getInstance('TDV Events');\r\n }\r\n\r\n static get RealtimeEvents() {\r\n return this.getInstance('Realtime Events');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n 'TDV Metrics': GoogleAnalyticsEventCategory.TdvMetrics,\r\n 'TDV Events': GoogleAnalyticsEventCategory.TdvEvents,\r\n 'Realtime Events': GoogleAnalyticsEventCategory.RealtimeEvents,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new GoogleAnalyticsEventCategory(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(GoogleAnalyticsEventCategory, 'instances', { value: {} });\r\n","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport GoogleAnalyticsEventAction from \"enums/googleAnalyticsEventAction\";\r\nimport GoogleAnalyticsEventCategory from \"enums/googleAnalyticsEventCategory\";\r\n\r\n/* Creates a new instance of a Google Analytics Tdv Event Mixin to track users events when the user subimits a lead. */\r\nexport default class EventTrackingTdvEventsMixin {\r\n constructor(model) {\r\n Object.assign(this, model);\r\n }\r\n \r\n getGoogleAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\r\n GoogleAnalyticsEventCategory.TdvEvents.toString(), \r\n GoogleAnalyticsEventAction.DirectLeads.toString(), \r\n this.eventLabel);\r\n }\r\n }","import EventTrackingTdvEventsMixin from \"./eventTrackingTdvEventsMixin\";\r\n\r\n\r\n/* Creates a new instance of a basic lead Tracking Event to track users events when the user subimits a lead.\r\n this class contains all the events that needs be to be done.\r\n*/\r\nexport default class BasicLeadTrackingEvents {\r\n constructor(model) { \r\n const data = {...model, eventLabel: 'Search-CTA-Learn-More'}\r\n this.events = {};\r\n this.events.googleAnalytics = [\r\n new EventTrackingTdvEventsMixin(data)];\r\n }\r\n }","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsEventAction from 'enums/googleAnalyticsEventAction';\r\nimport GoogleAnalyticsEventCategory from 'enums/googleAnalyticsEventCategory';\r\n\r\n/* Creates a new instance of a Google Analytics Tdv Events Mixin to track user's events when the user submits a lead. */\r\nexport default class EventTrackingNonDirectLeadsMixin {\r\n constructor(model) {\r\n Object.assign(this, model);\r\n }\r\n\r\n getGoogleAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\r\n GoogleAnalyticsEventCategory.TdvEvents.toString(),\r\n GoogleAnalyticsEventAction.NonDirectLeads.toString(),\r\n this.eventLabel\r\n );\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport GoogleAnalyticsEventAction from \"enums/googleAnalyticsEventAction\";\r\nimport GoogleAnalyticsEventCategory from \"enums/googleAnalyticsEventCategory\";\r\n\r\n/* Creates a new instance of a Google Analytics Tdv metric Mixin to track users events when the user subimits a lead. */\r\nexport default class EventTrackingRealTimeEventsMixin {\r\n constructor(model) {\r\n Object.assign(this, model);\r\n }\r\n \r\n getGoogleAnalyticsData() {\r\n return new GoogleAnalyticsEvent(\r\n GoogleAnalyticsEventCategory.RealtimeEvents.toString(),\r\n GoogleAnalyticsEventAction.DirectLeads.toString(),\r\n this.marketId);\r\n }\r\n }","import GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport GoogleAnalyticsEventAction from \"enums/googleAnalyticsEventAction\";\r\nimport GoogleAnalyticsEventCategory from \"enums/googleAnalyticsEventCategory\";\r\n\r\n/* Creates a new instance of a Google Analytics Tdv metric Mixin to track users events when the user subimits a lead. */\r\nexport default class EventTrackingTdvMetricsMixin {\r\n constructor(model) {\r\n Object.assign(this, model);\r\n }\r\n \r\n getGoogleAnalyticsData() { \r\n const eventLabel = `MN: ${this.marketName} | BN: ${this.builderName} | CN: ${this.communityName} | CI: ${this.communityId}`;\r\n return new GoogleAnalyticsEvent(\r\n GoogleAnalyticsEventCategory.TdvMetrics.toString(),\r\n GoogleAnalyticsEventAction.Leads.toString(),\r\n eventLabel);\r\n }\r\n }","import EventTrackingNonDirectLeadsMixin from './eventTrackingNonDirectLeadsMixin';\r\nimport EventTrackingRealTimeEventsMixin from './eventTrackingRealTimeEventsMixin';\r\nimport EventTrackingTdvEventsMixin from './eventTrackingTdvEventsMixin';\r\nimport EventTrackingTdvMetricsMixin from './eventTrackingTdvMetricsMixin';\r\n\r\n/* Creates a new instance of a Brochure Tracking Event to track users events when the user submits a lead.\r\n this class contains all the events that needs be to be done.\r\n*/\r\nexport default class BrochureTrackingEvents {\r\n constructor(model) {\r\n const data = { ...model, eventLabel: 'Search-CTA-Free-Brochure' };\r\n this.events = {};\r\n this.events.googleAnalytics = [\r\n new EventTrackingTdvEventsMixin(data),\r\n new EventTrackingTdvMetricsMixin(data),\r\n new EventTrackingRealTimeEventsMixin(data),\r\n ];\r\n\r\n /* This \"condition\" is where we take control of the new Event, without it, this is always fired.\r\n So, if the \"include communities\" checkbox is checked, push the instance into the googleAnalytics \r\n array and the event is fired. Otherwise, the event is omitted */\r\n if (data.includeRecommendations === 'True') {\r\n this.events.googleAnalytics.push(\r\n new EventTrackingNonDirectLeadsMixin(data)\r\n );\r\n }\r\n }\r\n}\r\n","import EventTrackingRealTimeEventsMixin from \"./eventTrackingRealTimeEventsMixin\";\r\nimport EventTrackingTdvEventsMixin from \"./eventTrackingTdvEventsMixin\";\r\nimport EventTrackingTdvMetricsMixin from \"./eventTrackingTdvMetricsMixin\";\r\n\r\n\r\n/* Creates a new instance of a Brochure Tracking Event to track users events when the user subimits a lead.\r\n this class contains all the events that needs be to be done.\r\n*/\r\nexport default class InformationTrackingEvents {\r\n constructor(model) { \r\n const data = {...model, eventLabel: 'Search-CTA-Free-Brochure'}\r\n this.events = {};\r\n this.events.googleAnalytics = [\r\n new EventTrackingTdvEventsMixin(data),\r\n new EventTrackingTdvMetricsMixin(data),\r\n new EventTrackingRealTimeEventsMixin(data)];\r\n }\r\n }","import EventTrackingTdvEventsMixin from \"./eventTrackingTdvEventsMixin\";\r\n\r\n\r\n/* Creates a new instance of a Brochure Tracking Event to track users events when the user subimits a lead.\r\n this class contains all the events that needs be to be done.\r\n*/\r\nexport default class TourTrackingEvents {\r\n constructor(model) { \r\n const data = {...model, eventLabel: 'Search-Results-Request-Tour'}\r\n this.events = {};\r\n this.events.googleAnalytics = [\r\n new EventTrackingTdvEventsMixin(data)];\r\n }\r\n }","import EventTrackingNonDirectLeadsMixin from './eventTrackingNonDirectLeadsMixin';\r\nimport EventTrackingRealTimeEventsMixin from './eventTrackingRealTimeEventsMixin';\r\nimport EventTrackingTdvEventsMixin from './eventTrackingTdvEventsMixin';\r\nimport EventTrackingTdvMetricsMixin from './eventTrackingTdvMetricsMixin';\r\n\r\n/* Creates a new instance of a Ask Question Tracking Event to track users events when the user submits a lead.\r\n this class contains all the events that needs be to be done.\r\n*/\r\nexport default class AskQuestionTrackingEvent {\r\n constructor(model) {\r\n const data = { ...model, eventLabel: 'Search-CTA-Ask-Question' };\r\n this.events = {};\r\n this.events.googleAnalytics = [\r\n new EventTrackingTdvEventsMixin(data),\r\n new EventTrackingTdvMetricsMixin(data),\r\n new EventTrackingRealTimeEventsMixin(data),\r\n ];\r\n\r\n /* This \"condition\" is where we take control of the new Event, without it, this is always fired.\r\n So, if the \"include communities\" checkbox is checked, push the instance into the googleAnalytics \r\n array and the event is fired. Otherwise, the event is omitted */\r\n if (data.includeRecommendations === 'True') {\r\n this.events.googleAnalytics.push(new EventTrackingNonDirectLeadsMixin(data));\r\n }\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport BasicLeadTrackingEvents from '../analytics/basicLeadTrackingEvent';\r\nimport BrochureTrackingEvents from '../analytics/brochureTrackingEvent';\r\nimport InformationTrackingEvents from '../analytics/informationTracking';\r\nimport TourTrackingEvents from '../analytics/tourTrackingEvent';\r\nimport AskQuestionTrackingEvents from '../analytics/askQuestionTrackingEvent';\r\n\r\n/**\r\n * Gets the current state of the modalInformation object, and dispatch an action to update the modalInformation\r\n * object to reflect the lead generator flow.\r\n *\r\n * @returns The initial value from modalInformation object.\r\n */\r\nexport const initialState = (properties, getGoogleAnalyticsDTOCallback) => {\r\n const modalInformation = store.getState().uiState.modalInformation;\r\n const { listingInformation } = properties;\r\n const googleAnalyticsDTO = getGoogleAnalyticsDTOCallback ? getGoogleAnalyticsDTOCallback(listingInformation) : '';\r\n const newState = {\r\n id: modalInformation.id,\r\n type: modalInformation.type,\r\n name: 'leadGenerator',\r\n ...properties,\r\n googleAnalyticsDTO,\r\n };\r\n\r\n store.dispatch(uiStateSlice.actions.modalInformation(newState));\r\n\r\n return modalInformation;\r\n};\r\n\r\nexport const postRecommendedLeadForm = (leadInformation) => {\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n })\r\n );\r\n};\r\n\r\nexport const postLeadBrochureForm = (leadInformation) => {\r\n const eventTracking = new BrochureTrackingEvents(Object.assign({}, leadInformation));\r\n const googleAnalyticsDTO = eventTracking.events.googleAnalytics.map((event) => event.getGoogleAnalyticsData());\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n googleAnalyticsDTO,\r\n })\r\n );\r\n};\r\n\r\nexport const postLeadInformationForm = (leadInformation) => {\r\n const eventTracking = new InformationTrackingEvents(Object.assign({}, leadInformation));\r\n const googleAnalyticsDTO = eventTracking.events.googleAnalytics.map((event) => event.getGoogleAnalyticsData());\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n googleAnalyticsDTO,\r\n })\r\n );\r\n};\r\n\r\nexport const postLeadTourForm = (leadInformation) => {\r\n const eventTracking = new TourTrackingEvents(Object.assign({}, leadInformation));\r\n const googleAnalyticsDTO = eventTracking.events.googleAnalytics.map((event) => event.getGoogleAnalyticsData());\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n googleAnalyticsDTO,\r\n })\r\n );\r\n};\r\n\r\nexport const postLeadInformationFormBasic = (leadInformation) => {\r\n const eventTracking = new BasicLeadTrackingEvents(Object.assign({}, leadInformation));\r\n const googleAnalyticsDTO = eventTracking.events.googleAnalytics.map((event) => event.getGoogleAnalyticsData());\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n googleAnalyticsDTO,\r\n })\r\n );\r\n};\r\n\r\n\r\nexport const postLeadAskQuestionForm = (leadInformation) => {\r\n const eventTracking = new AskQuestionTrackingEvents(Object.assign({}, leadInformation));\r\n const googleAnalyticsDTO = eventTracking.events.googleAnalytics.map((event) => event.getGoogleAnalyticsData());\r\n store.dispatch(\r\n uiStateSlice.actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: leadInformation,\r\n googleAnalyticsDTO,\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * This function takes in a modalInformation object and dispatches it to the reducer.\r\n * @param modalInformation - object with the id, type, and name to identify the modal.\r\n */\r\nexport const updateModalProgress = (modalInformation) => {\r\n store.dispatch(uiStateSlice.actions.modalInformation(modalInformation));\r\n};\r\n","export default class BrochureButton {\r\n constructor() {\r\n this.id = 'getBrochureButton';\r\n }\r\n\r\n getHtml() {\r\n const styles = 'class=\"btn btn--yellow btn--width-100 btn--48-lg loading\"';\r\n return ``;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n}\r\n","export default class CommentsTextArea {\r\n constructor() {\r\n this.input = ``;\r\n this.label = ``;\r\n }\r\n\r\n getHtml() {\r\n return `${this.label}${this.input}`;\r\n }\r\n}\r\n","import { fromEvent, map } from \"rxjs\";\r\n\r\nexport default class EmailInput {\r\n constructor() {\r\n this.valueInput = '';\r\n this.errorMessageId = 'nhs_ErrorForEmail';\r\n this.id = 'MailAddress';\r\n this.errorCssClass = 'error';\r\n this.errorMessage = ``;\r\n this.label = ``;\r\n this.matchingPattern =\r\n /^(([^<>()\\\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue || '';\r\n }\r\n\r\n get value(){\r\n return this.valueInput;\r\n }\r\n\r\n getHtml() {\r\n return `${this.label}${this.errorMessage}`;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On input change map its value to the storage property.\r\n */\r\n getOnChangeEvent() {\r\n return fromEvent(this.getNode(), 'change').pipe(\r\n map((event) => ({email: event.target.value}))\r\n );\r\n }\r\n\r\n setInvalidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n setValidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n validate() {\r\n const node = this.getNode();\r\n\r\n /* NHS20-1684: we verify that the value taken from the input it's clean,\r\n in case of spaces before and after the text, also is updated in the UI. */\r\n const cleanedValue = node.value.trim().replace(/\\s+/g, ' ');\r\n node.value = cleanedValue;\r\n const isValid = this.matchingPattern.test(node.value);\r\n\r\n if (isValid) {\r\n this.setValidState(node);\r\n } else {\r\n this.setInvalidState(node);\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { fromEvent, map } from \"rxjs\";\r\n\r\nexport default class NameInput {\r\n constructor() {\r\n this.valueInput = '';\r\n this.errorMessageId = 'nhs_ErrorForName';\r\n this.id = 'Name';\r\n this.errorCssClass = 'error';\r\n this.errorMessage = ``;\r\n this.label = ``;\r\n this.pattern = `^([A-Za-zà-ü]+(-?'?[A-Za-z+'?-?à-ü]+))(\\\\s([A-Za-zà-ü]+(-?'?[A-Za-z+'?-?à-ü]+)?))+?$`;\r\n this.matchingPattern = new RegExp(this.pattern);\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue || '';\r\n }\r\n\r\n get value(){\r\n return this.valueInput;\r\n }\r\n\r\n getHtml() {\r\n return `${this.label}${this.errorMessage}`;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On input change map its value to the storage property.\r\n */\r\n getOnChangeEvent() {\r\n return fromEvent(this.getNode(), 'change').pipe(\r\n map((event) => ({name: event.target.value}))\r\n );\r\n }\r\n\r\n setInvalidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n setValidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n focus() {\r\n const nameInput = this.getNode();\r\n nameInput.focus();\r\n }\r\n\r\n validate() {\r\n const node = this.getNode();\r\n\r\n /* NHS20-1684: we verify that the value taken from the input it's clean,\r\n in case of spaces before and after the text, also is updated in the UI. */\r\n const cleanedValue = node.value.trim().replace(/\\s+/g, ' ');\r\n node.value = cleanedValue;\r\n const isValid = this.matchingPattern.test(cleanedValue);\r\n\r\n if (isValid) {\r\n this.setValidState(node);\r\n } else {\r\n this.setInvalidState(node);\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { fromEvent, map } from 'rxjs';\r\nimport VMasker from 'vanilla-masker';\r\n\r\nexport default class PhoneInput {\r\n constructor() {\r\n this.valueInput = '';\r\n this.required = false;\r\n this.errorMessageId = 'nhs_ErrorForPhone';\r\n this.id = 'UserPhoneNumber';\r\n this.errorCssClass = 'error';\r\n this.errorMessage = ``;\r\n this.label = ``;\r\n this.pattern = '^\\\\([2-9][0-9]{2}\\\\)\\\\s[0-9]{3}-[0-9]{4}$';\r\n this.matchingPattern = new RegExp(this.pattern);\r\n this.screenReaderMessage = ``;\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue || '';\r\n }\r\n\r\n get value(){\r\n return this.valueInput;\r\n }\r\n\r\n bindEvents() {\r\n const phoneInput = this.getNode();\r\n VMasker(phoneInput).maskPattern('(999) 999-9999');\r\n }\r\n\r\n getHtml() {\r\n return `${this.label}\r\n ${this.errorMessage}${this.screenReaderMessage}`;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On input change map its value to the storage property.\r\n */\r\n getOnChangeEvent() {\r\n return fromEvent(this.getNode(), 'blur').pipe(\r\n map((event) => ({phone: event.target.value}))\r\n );\r\n }\r\n\r\n removeRequired() {\r\n const node = this.getNode();\r\n node.placeholder = \"Phone\";\r\n node.removeAttribute('required');\r\n }\r\n\r\n setInvalidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n setRequired() {\r\n const node = this.getNode();\r\n node.placeholder = \"*Phone\";\r\n node.setAttribute('required', 'true');\r\n }\r\n\r\n setValidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n isValid() {\r\n const node = this.getNode();\r\n const isEmpy = node.value === '';\r\n const isRequired = node.required;\r\n \r\n // If it is empty and is required, the input is not valid\r\n if(isEmpy && isRequired) {\r\n return false;\r\n }\r\n\r\n // If it is empty a is not required, the input is valid\r\n if (isEmpy && !isRequired) {\r\n return true;\r\n }\r\n\r\n // Otherwise the input is not empty and need to match with the regex.\r\n return this.matchingPattern.test(node.value);\r\n }\r\n\r\n validate() {\r\n const node = this.getNode();\r\n const isValid = this.isValid()\r\n\r\n if (isValid) {\r\n this.setValidState(node);\r\n } else {\r\n this.setInvalidState(node);\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { fromEvent, map } from \"rxjs\";\r\n\r\nexport default class RecommendedCheckbox {\r\n constructor() {\r\n this.id = 'includeRecommended';\r\n this.label = ``;\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue;\r\n }\r\n\r\n get value(){\r\n return this.valueInput;\r\n }\r\n\r\n getHtml() {\r\n return `${this.label}`;\r\n }\r\n \r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On input change map its value to the storage property.\r\n */\r\n getOnChangeEvent() {\r\n return fromEvent(this.getNode(), 'change').pipe(\r\n map((event) => ({hasUserOptedIntoRecommendationEmail: event.target.checked}))\r\n );\r\n }\r\n}\r\n","import { combineLatest, fromEvent, map, skip, startWith } from \"rxjs\";\r\n\r\nexport default class ZipInput {\r\n constructor() {\r\n this.valueInput = '';\r\n this.isInternationalInput = false;\r\n this.errorMessageId = 'nhs_ErrorForipCodeReg';\r\n this.idForOutside = 'livesOutside';\r\n this.idForZip = 'postalCode';\r\n this.errorCssClass = 'error';\r\n this.errorMessage = ``;\r\n this.labelForOutside = ``;\r\n this.labelForZipCode = ``;\r\n this.pattern = '^\\\\d{5}(-\\\\d{4})?$';\r\n this.matchingPattern = new RegExp(this.pattern);\r\n }\r\n\r\n set isInternational(newValue){\r\n this.isInternationalInput = !!newValue;\r\n }\r\n\r\n get isInternational(){\r\n return this.isInternationalInput;\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue;\r\n }\r\n\r\n get value(){\r\n return this.valueInput;\r\n }\r\n\r\n bindEvents() {\r\n this.getOutsideUsNode().addEventListener('change', this.onOutsideUsChanged.bind(this));\r\n }\r\n\r\n getHtml() {\r\n return `
\r\n ${this.labelForZipCode}\r\n \r\n ${this.errorMessage}\r\n
\r\n
\r\n \r\n ${this.labelForOutside}\r\n
`;\r\n }\r\n\r\n getOutsideUsNode() {\r\n return document.getElementById(this.idForOutside);\r\n }\r\n\r\n getZipNode() {\r\n return document.getElementById(this.idForZip);\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On inputs change map their values to the storage properties.\r\n */\r\n getOnChangeEvent() {\r\n const outSideNode = this.getOutsideUsNode();\r\n const zipNode = this.getZipNode();\r\n const onOutSideChange$ = fromEvent(outSideNode, 'change').pipe(\r\n map((event) => event.target),\r\n startWith(outSideNode)\r\n );\r\n const onZipChange$ = fromEvent(zipNode, 'change').pipe(\r\n map((event) => event.target),\r\n startWith(zipNode)\r\n );\r\n return combineLatest([onZipChange$, onOutSideChange$]).pipe(\r\n map(([zipInput, livesOutsideInput]) => ({\r\n zip: zipInput.value,\r\n livesOutside: livesOutsideInput.checked,\r\n })),\r\n skip(1)\r\n );\r\n }\r\n\r\n isOutsideUs() {\r\n return this.getOutsideUsNode().checked;\r\n }\r\n\r\n isValidZipCode() {\r\n const node = this.getZipNode();\r\n return this.matchingPattern.test(node.value?.trim());\r\n }\r\n\r\n onOutsideUsChanged(event) {\r\n const node = this.getZipNode();\r\n\r\n if (event.currentTarget.checked) {\r\n node.setAttribute('disabled', true);\r\n node.value = '';\r\n this.setValidState(node);\r\n } else {\r\n node.removeAttribute('disabled', true);\r\n }\r\n }\r\n\r\n setInvalidState() {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n const node = this.getZipNode();\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n setValidState() {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n const node = this.getZipNode();\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n validate() {\r\n const isOutsideUs = this.isOutsideUs();\r\n const isValidZipCode = this.isValidZipCode();\r\n const isValid = isOutsideUs || isValidZipCode;\r\n\r\n if (isValid) {\r\n this.setValidState();\r\n } else {\r\n this.setInvalidState();\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { fromEvent, map } from \"rxjs\";\r\n\r\nexport default class RealtorDropdown {\r\n constructor() {\r\n this.selectedValue = '';\r\n this.required = false;\r\n this.errorMessageId = 'nhs_ErrorForRealtorQuestion';\r\n this.errorCssClass = 'error'\r\n this.id = 'nhs-real-agent';\r\n this.errorMessage = ``;\r\n this.label = ``;\r\n }\r\n\r\n set value(newValue) {\r\n this.selectedValue = newValue || ''; \r\n const realtorDropdown = this.getNode();\r\n if (realtorDropdown) {\r\n realtorDropdown.value = this.selectedValue;\r\n }\r\n }\r\n\r\n get value() {\r\n return this.selectedValue;\r\n }\r\n\r\n getHtml() {\r\n return `${this.label} \r\n
\r\n \r\n ${this.errorMessage}\r\n
`;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n \r\n /**\r\n * setSelectedValue: Finds the correct index based on the selectedValue\r\n * and updates the select element.\r\n */\r\n setSelectedValue() {\r\n const realtorDropdownNode = this.getNode();\r\n if (realtorDropdownNode) {\r\n const optionsArray = Array.from(realtorDropdownNode.options);\r\n realtorDropdownNode.selectedIndex = optionsArray.findIndex(\r\n (option) => option.value === this.selectedValue\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * getOnChangeEvent: On select change map its value to the storage property.\r\n */\r\n getOnChangeEvent() {\r\n return fromEvent(this.getNode(), 'change').pipe(\r\n map((event) => {\r\n this.value = event.target.value;\r\n return { realtorQuestion: this.selectedValue };\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Method to remove the required attribute.\r\n */\r\n\r\n removeRequired() {\r\n const node = this.getNode();\r\n node.removeAttribute('required');\r\n }\r\n\r\n setInvalidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n /**\r\n * Method to set the required attribute.\r\n */\r\n\r\n setRequired() {\r\n const node = this.getNode();\r\n node.setAttribute('required', 'true');\r\n }\r\n\r\n setValidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n isValid() {\r\n const node = this.getNode();\r\n const isEmpty = node.value === '';\r\n const isRequired = node.required;\r\n \r\n // If it is empty and is required, the input is not valid\r\n if(isEmpty && isRequired) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n validate() {\r\n const node = this.getNode();\r\n const isValid = this.isValid();\r\n\r\n if (isValid) {\r\n this.setValidState(node);\r\n } else {\r\n this.setInvalidState(node);\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { closeButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadBrochureForm } from '../services/taskFlow';\r\nimport BrochureButton from './brochureButton';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport EmailInput from './emailInput';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport RecommendedCheckbox from './recommendedCheckbox';\r\nimport ZipInput from './zipInput';\r\nimport RealtorDropdown from './realtorDropdown';\r\n\r\n/* Creates a new instance of a Request Tour Form to allow users making an appointment to tour the selected housing. */\r\nexport default class BrochureFormPaid {\r\n constructor() {\r\n const state = store.getState();\r\n const userProfile = state?.userProfile || {};\r\n this.id = state?.uiState.modalInformation.id;\r\n this.type = state?.uiState.modalInformation.type;\r\n this.fromPage = state?.uiState.modalInformation.fromPage;\r\n this.excludeRecommendations = false;\r\n this.getBrochureButton = new BrochureButton();\r\n this.commentsTextArea = new CommentsTextArea();\r\n this.emailAddressInput = new EmailInput();\r\n this.emailAddressInput.value = userProfile.email;\r\n this.formId = 'brochureFormPaid';\r\n this.fullNameInput = new NameInput();\r\n this.fullNameInput.value = userProfile.name;\r\n this.phoneNumberInput = new PhoneInput();\r\n this.phoneNumberInput.value = userProfile.phone;\r\n this.postalCodeInput = new ZipInput();\r\n this.postalCodeInput.value = userProfile.zip;\r\n this.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.realtorDropdown = new RealtorDropdown();\r\n this.realtorDropdown.value = userProfile.realtorQuestion;\r\n this.recommendedCheckbox = new RecommendedCheckbox();\r\n this.recommendedCheckbox.value = userProfile.hasUserOptedIntoRecommendationEmail;\r\n this.onClickEvent = null;\r\n }\r\n\r\n /**\r\n * validateNode: Check if the field has a value as expected.\r\n * @param {Object} node Input to validate\r\n * @returns A boolean value indicating whether the input is valid or not.\r\n */\r\n static validateNode(node) {\r\n return node.validate();\r\n }\r\n\r\n /**\r\n * getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n * @param {Object} properties Information regarding to the listing.\r\n * @returns The Google Analtic event information.\r\n */\r\n static getFormOpenedAnalyticsData(properties) {\r\n const customDimensions = {};\r\n\r\n if (properties.marketId) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n }\r\n\r\n if (properties.marketName && properties.stateAbbreviation) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n }\r\n\r\n if (properties.city) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n }\r\n\r\n return new GoogleAnalyticsEvent(\r\n \"Lead Events\",\r\n \"Search Results CTA Free Brochure\",\r\n \"Open Form - Free Brochure\",\r\n customDimensions);\r\n }\r\n\r\n /**\r\n * setHousingData: Sets the housing information for the form.\r\n * @param {Object} properties Information regarding to the listing.\r\n */\r\n setHousingData(properties = {}) {\r\n this.housingData = properties;\r\n }\r\n\r\n /**\r\n * submitBrochureForm: Process to validate and submit the form.\r\n * @param {event} event Click event.\r\n */\r\n submitBrochureForm(event) {\r\n event.preventDefault();\r\n\r\n const validationFunctions = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n this.realtorDropdown,\r\n ];\r\n\r\n const result = validationFunctions.map(BrochureFormPaid.validateNode);\r\n\r\n if (result.some((isValid) => !isValid)) {\r\n return;\r\n }\r\n\r\n this.getBrochureButton.getNode().disabled = 'disabled';\r\n const formData = new FormData(this.getForm());\r\n const brochureInformation = Object.fromEntries(formData.entries());\r\n\r\n brochureInformation.id = this.id;\r\n brochureInformation.type = `${this.type}-brochure`;\r\n brochureInformation.excludeRecommendations = this.excludeRecommendations;\r\n brochureInformation.fromPage = this.housingData.fromPage;\r\n brochureInformation.includeRecommended = !!brochureInformation.includeRecommended;\r\n\r\n const brochureLeadObject = leadConstructor(brochureInformation);\r\n brochureLeadObject.setHousingInformation?.(this.housingData.listingInformation);\r\n\r\n postLeadBrochureForm(brochureLeadObject);\r\n }\r\n\r\n /**\r\n * Sets the binding required for the form.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitBrochureForm.bind(this);\r\n this.phoneNumberInput.bindEvents();\r\n this.postalCodeInput.bindEvents();\r\n if (this.fullNameInput.value === '') {\r\n this.fullNameInput.focus();\r\n }\r\n this.realtorDropdown.setSelectedValue();\r\n this.getBrochureButton.getNode().addEventListener('click', this.onClickEvent);\r\n this.bindChangeEvents();\r\n }\r\n\r\n /**\r\n * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n */\r\n bindChangeEvents() {\r\n const changeInputs = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n this.recommendedCheckbox,\r\n this.realtorDropdown,\r\n ];\r\n changeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n store.dispatch(userProfileActions.update(data))));\r\n }\r\n\r\n /**\r\n * Removes the bindings that should not be still using.\r\n */\r\n unbindEvents() {\r\n this.getBrochureButton.getNode().removeEventListener('click', this.onClickEvent);\r\n }\r\n\r\n /**\r\n * getForm: Gets the form container \r\n * @returns A HTML element related to the form container.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * Gets the HTML structure for the brochure form paid.\r\n * @returns The string with the HTML structure.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n ${closeButton}\r\n

Check your email & download the brochure

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n ${this.realtorDropdown.getHtml()}\r\n
\r\n
\r\n ${this.recommendedCheckbox.getHtml()}\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.getBrochureButton.getHtml()}\r\n
\r\n \r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Get Brochure\")\r\n .replace(\"{1}\", this.housingData.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n }\r\n}\r\n","export default class BasicContactVendor {\r\n static get OpCity() {\r\n return this.getInstance('OpCity');\r\n }\r\n\r\n static get PrimeStreet() {\r\n return this.getInstance('PrimeStreet');\r\n }\r\n\r\n static get CoffmanProperties() {\r\n return this.getInstance('Coffman Properties');\r\n }\r\n\r\n static get Dezka() {\r\n return this.getInstance('Dezka');\r\n }\r\n\r\n static get MarketplaceHomes() {\r\n return this.getInstance('Marketplace Homes');\r\n }\r\n\r\n static get NewHomeExpertsDetroit() {\r\n return this.getInstance('New Home Experts - Detroit');\r\n }\r\n\r\n static get NewHomeExpertsLasVegas() {\r\n return this.getInstance('New Home Experts - Las Vegas');\r\n }\r\n\r\n static get NewHomeExpertsSarasota() {\r\n return this.getInstance('New Home Experts - Sarasota');\r\n }\r\n\r\n static get NHSAustin() {\r\n return this.getInstance('NHS Austin');\r\n }\r\n\r\n static fromKey(key) {\r\n const formTypeMap = {\r\n\r\n 'OpCity': BasicContactVendor.OpCity,\r\n 'PrimeStreet': BasicContactVendor.PrimeStreet,\r\n 'Coffman Properties': BasicContactVendor.CoffmanProperties,\r\n 'Dezka': BasicContactVendor.Dezka,\r\n 'Marketplace Homes': BasicContactVendor.MarketplaceHomes,\r\n 'New Home Experts - Detroit': BasicContactVendor.NewHomeExpertsDetroit,\r\n 'New Home Experts - Las Vegas': BasicContactVendor.NewHomeExpertsLasVegas,\r\n 'New Home Experts - Sarasota': BasicContactVendor.NewHomeExpertsSarasota,\r\n 'NHS Austin': BasicContactVendor.NHSAustin,\r\n };\r\n return formTypeMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new BasicContactVendor(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(BasicContactVendor, 'instances', { value: {} });\r\n","import BasicContactVendor from '../enums/basicContactVendor';\r\n\r\nconst opCityPrivacyPolicyParagraph = `
By proceeding, you consent to receive calls and texts at the number you \r\nprovided, including marketing by autodialer and prerecorded and artificial voice, and email, from Realtor.com (Move Sales, Inc.) \r\nabout your inquiry and other home-related matters, but not as a condition of any purchase. You also agree to Realtor.com ’s Terms of Use \r\nand to Realtor.com ’s Privacy Policy regarding information relating to you. Msg/data rates may apply. \r\nThis consent applies even if you are on a corporate, state, or national Do Not Call list.
\r\nBy providing your name and contact information, you consent and agree to receive email marketing communications from NewHomeSource. Your Agreement \r\nis not a condition of purchasing any property, goods, or services, and you may call us instead of submitting your information online. Consult our \r\nPrivacy Policy for additional information, including unsubscribe options. \r\nYou also agree to our Privacy Policy and \r\nTerms of Use.
`;\r\n\r\nconst defaultPrivacyPolicyParagraph = `
By providing your name and contact information and clicking the Learn More button, \r\nyou consent and agree to receive marketing communications from NewHomeSource and {0}, including emails, calls or text messages using an automatic \r\ntelephone dialing system or an artificial or prerecorded voice. You also agree to our Privacy Policy, including TCPA Policy and Terms of Use. Your agreement is not a condition to purchasing any property, \r\ngoods or services, and you may call us instead of submitting the information online. You also acknowledge \r\nand agree that you can revoke your authorization at any time. Your consent herein also applies to any future registration on national or state \r\nDo-No-Call lists. For mobile phones, standard message and data charges apply. Consult our Privacy Policy for additional information, \r\nincluding unsubscribe options.
`;\r\n\r\n/**\r\n * Returns the privacy policy paragraph for basic listings according to the contact vendor name.\r\n * @param {string} contactVendorName the contact vendor name.\r\n * @returns {string} - The privacy policy paragraph.\r\n */\r\nfunction getBasicPrivacyPolicyParagraph(contactVendorName) {\r\n\r\n switch (contactVendorName) {\r\n case BasicContactVendor.OpCity.name:\r\n return opCityPrivacyPolicyParagraph;\r\n default:\r\n return defaultPrivacyPolicyParagraph.replace('{0}', contactVendorName);\r\n }\r\n}\r\n\r\nexport default getBasicPrivacyPolicyParagraph;","export default class InformationButtonBasic {\r\n constructor() {\r\n this.id = 'moreInformationButtonBasic';\r\n }\r\n \r\n getHtml() {\r\n const styles = 'class=\"btn btn--yellow btn--width-100 btn--48-lg loading\"';\r\n return ``;\r\n }\r\n \r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n }\r\n ","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { closeButton } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadInformationFormBasic } from '../services/taskFlow';\r\nimport getBasicPrivacyPolicyParagraph from '../services/basicPrivacyPolicyParagraph';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport EmailInput from './emailInput';\r\nimport InformationButtonBasic from './informationButtonBasic';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport ZipInput from './zipInput';\r\n\r\n/* Creates a new instance of a Get More Information Basic Form to allow users getting in touch with an agent\r\nthat will lead them into the home buying process. */\r\nexport default class InformationFormBasic {\r\n constructor() {\r\n const state = store.getState();\r\n const userProfile = state?.userProfile || {};\r\n this.id = state?.uiState?.modalInformation.id;\r\n this.type = state?.uiState?.modalInformation.type;\r\n this.fromPage = state?.uiState.modalInformation.fromPage;\r\n this.excludeRecommendations = true;\r\n this.moreInformationButton = new InformationButtonBasic();\r\n this.commentsTextArea = new CommentsTextArea();\r\n this.emailAddressInput = new EmailInput();\r\n this.emailAddressInput.value = userProfile.email;\r\n this.formId = 'informationFormBasic';\r\n this.fullNameInput = new NameInput();\r\n this.fullNameInput.value = userProfile.name;\r\n this.phoneNumberInput = new PhoneInput();\r\n this.phoneNumberInput.value = userProfile.phone;\r\n this.postalCodeInput = new ZipInput();\r\n this.postalCodeInput.value = userProfile.zip;\r\n this.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.onClickEvent = null;\r\n }\r\n\r\n /**\r\n * validateNode: Check if the field has a value as expected.\r\n * @param {Object} node Input to validate\r\n * @returns A boolean value indicating whether the input is valid or not.\r\n */\r\n static validateNode(node) {\r\n return node.validate();\r\n }\r\n\r\n /**\r\n * getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n * @param {Object} properties Information regarding to the listing.\r\n * @returns The Google Analtic event information.\r\n */\r\n static getFormOpenedAnalyticsData(properties) {\r\n const customDimensions = {};\r\n\r\n if (properties.marketId) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n }\r\n\r\n if (properties.marketName && properties.stateAbbreviation) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n }\r\n\r\n if (properties.city) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n }\r\n return new GoogleAnalyticsEvent(\r\n 'Lead Events',\r\n 'Search Results CTA Learn More',\r\n 'Open Form - Learn More',\r\n customDimensions);\r\n }\r\n\r\n /**\r\n * setPrivacyPolicyText: Sets the structure related to the privacy policy text for the form.\r\n * @param {string} phoneNumber Builder phone number value.\r\n * @param {string} contactVendorName Contact vendor name value.\r\n */\r\n setPrivacyPolicyText(phoneNumber, contactVendorName) {\r\n const container = document.createElement('div');\r\n const privacyPolicyParagraph = getBasicPrivacyPolicyParagraph(contactVendorName);\r\n container.innerHTML = privacyPolicyParagraph;\r\n\r\n this.basicPrivacyPolicyParagraph = privacyPolicyParagraph;\r\n\r\n if (phoneNumber) {\r\n container.firstChild.innerHTML = `${container.firstChild.innerHTML}`;\r\n this.basicPrivacyPolicyParagraph = container.firstChild.outerHTML;\r\n }\r\n }\r\n\r\n /**\r\n * submitInformationForm: Process to validate and submit the form.\r\n * @param {event} event Click event.\r\n */\r\n submitInformationForm(event) {\r\n event.preventDefault();\r\n\r\n const validationFunctions = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n\r\n const result = validationFunctions.map(InformationFormBasic.validateNode);\r\n\r\n if (result.some((isValid) => !isValid)) {\r\n return;\r\n }\r\n\r\n this.moreInformationButton.getNode().disabled = 'disabled';\r\n const formData = new FormData(this.getForm());\r\n const leadInformation = Object.fromEntries(formData.entries());\r\n\r\n leadInformation.id = this.id;\r\n leadInformation.type = `${this.type}-information-basic`;\r\n leadInformation.excludeRecommendations = this.excludeRecommendations;\r\n leadInformation.fromPage = this.housingData.fromPage;\r\n const leadObject = leadConstructor(leadInformation);\r\n leadObject.setHousingInformation?.(this.housingData);\r\n \r\n postLeadInformationFormBasic(leadObject);\r\n }\r\n\r\n /**\r\n * Sets the binding required for the form.\r\n */\r\n setHousingData(properties={}) {\r\n this.housingData = properties;\r\n }\r\n\r\n /**\r\n * Sets the binding required for the form.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitInformationForm.bind(this);\r\n this.phoneNumberInput.bindEvents();\r\n this.postalCodeInput.bindEvents();\r\n if (this.fullNameInput.value === '') {\r\n this.fullNameInput.focus();\r\n }\r\n this.moreInformationButton.getNode().addEventListener('click', this.onClickEvent);\r\n this.phoneNumberInput.setRequired();\r\n this.bindChangeEvents();\r\n }\r\n\r\n /**\r\n * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n */\r\n bindChangeEvents() {\r\n const changeInputs = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n changeInputs.forEach(input => input.getOnChangeEvent().subscribe(data => \r\n store.dispatch(userProfileActions.update(data))));\r\n }\r\n\r\n /**\r\n * Removes the bindings that should not be still using.\r\n */\r\n unbindEvents() {\r\n this.moreInformationButton.getNode().removeEventListener('click', this.onClickEvent);\r\n }\r\n\r\n /**\r\n * getForm: Gets the form container \r\n * @returns A HTML element related to the form container.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * Gets the HTML structure for the information brochure form basic.\r\n * @returns The string with the HTML structure.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n ${closeButton}\r\n

Connect with a local agent

\r\n

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.moreInformationButton.getHtml()}\r\n
\r\n
\r\n
\r\n ${this.basicPrivacyPolicyParagraph}\r\n
`;\r\n }\r\n}","export default class InformationButton {\r\n constructor() {\r\n this.id = 'moreInformationButton';\r\n }\r\n \r\n getHtml() {\r\n const styles = 'class=\"btn btn--yellow btn--width-100 btn--48-lg loading\"';\r\n return ``;\r\n }\r\n \r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n }\r\n ","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { closeButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadInformationForm } from '../services/taskFlow';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport EmailInput from './emailInput';\r\nimport InformationButton from './informationButton';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport ZipInput from './zipInput';\r\nimport RealtorDropdown from './realtorDropdown';\r\n\r\n/* Creates a new instance of a Get More Information Form to allow users making an \r\nappointment to tour the selected housing. */\r\nexport default class InformationFormPaid {\r\n constructor() {\r\n const state = store.getState();\r\n const userProfile = state?.userProfile || {};\r\n this.id = state?.uiState?.modalInformation.id;\r\n this.type = state?.uiState?.modalInformation.type;\r\n this.excludeRecommendations = true;\r\n this.isPersistent = true;\r\n this.moreInformationButton = new InformationButton();\r\n this.commentsTextArea = new CommentsTextArea();\r\n this.emailAddressInput = new EmailInput();\r\n this.emailAddressInput.value = userProfile.email;\r\n this.formId = 'informationFormPaid';\r\n this.fullNameInput = new NameInput();\r\n this.fullNameInput.value = userProfile.name;\r\n this.phoneNumberInput = new PhoneInput();\r\n this.phoneNumberInput.value = userProfile.phone;\r\n this.postalCodeInput = new ZipInput();\r\n this.postalCodeInput.value = userProfile.zip;\r\n this.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.realtorDropdown = new RealtorDropdown();\r\n this.realtorDropdown.value = userProfile.realtorQuestion;\r\n this.onClickEvent = null;\r\n this.buttonText = state?.uiState?.modalInformation.buttonText;\r\n }\r\n\r\n /**\r\n * validateNode: Check if the field has a value as expected.\r\n * @param {Object} node Input to validate\r\n * @returns A boolean value indicating whether the input is valid or not.\r\n */\r\n static validateNode(node) {\r\n return node.validate();\r\n }\r\n\r\n /**\r\n * getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n * @param {Object} properties Information regarding to the listing.\r\n * @returns The Google Analtic event information.\r\n */\r\n static getFormOpenedAnalyticsData(properties) {\r\n const customDimensions = {};\r\n\r\n if (properties.marketId) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n }\r\n\r\n if (properties.marketName && properties.stateAbbreviation) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n }\r\n\r\n if (properties.city) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n }\r\n\r\n return new GoogleAnalyticsEvent(\r\n 'Lead Events',\r\n 'Search Results CTA Get More Info',\r\n 'Open Form - Get More Info',\r\n customDimensions);\r\n }\r\n\r\n /**\r\n * setHousingData: Sets the housing information for the form.\r\n * @param {Object} properties Information regarding to the listing.\r\n */\r\n setHousingData(properties = {}) {\r\n this.housingData = properties;\r\n }\r\n\r\n /**\r\n * submitBrochureForm: Process to validate and submit the form.\r\n * @param {event} event Click event.\r\n */\r\n submitInformationForm(event) {\r\n event.preventDefault();\r\n\r\n const validationFunctions = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n const result = validationFunctions.map(InformationFormPaid.validateNode);\r\n\r\n if (result.some((isValid) => !isValid)) {\r\n return;\r\n }\r\n\r\n this.moreInformationButton.getNode().disabled = 'disabled';\r\n const formData = new FormData(this.getForm());\r\n const leadInformation = Object.fromEntries(formData.entries());\r\n\r\n leadInformation.id = this.id;\r\n leadInformation.type = `${this.type}-information`;\r\n leadInformation.excludeRecommendations = this.excludeRecommendations;\r\n leadInformation.fromPage = this.housingData.fromPage;\r\n const leadObject = leadConstructor(leadInformation);\r\n leadObject.setHousingInformation?.(this.housingData);\r\n\r\n postLeadInformationForm(leadObject);\r\n }\r\n\r\n /**\r\n * Sets the binding required for the form.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitInformationForm.bind(this);\r\n this.phoneNumberInput.bindEvents();\r\n this.postalCodeInput.bindEvents();\r\n if (this.fullNameInput.value === '') {\r\n this.fullNameInput.focus();\r\n }\r\n this.realtorDropdown.setSelectedValue();\r\n this.moreInformationButton.getNode().addEventListener('click', this.onClickEvent);\r\n this.bindChangeEvents();\r\n }\r\n\r\n /**\r\n * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n */\r\n bindChangeEvents() {\r\n const changeInputs = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n this.realtorDropdown,\r\n ];\r\n changeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n store.dispatch(userProfileActions.update(data))));\r\n }\r\n\r\n /**\r\n * Removes the bindings that should not be still using.\r\n */\r\n unbindEvents() {\r\n this.moreInformationButton.getNode().removeEventListener('click', this.onClickEvent);\r\n }\r\n\r\n /**\r\n * getForm: Gets the form container \r\n * @returns A HTML element related to the form container.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * Gets the HTML structure for the information form paid.\r\n * @returns The string with the HTML structure.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n ${closeButton}\r\n

Get More Information

\r\n

\r\n We will keep you updated in your area of interest, our progress, and much more…\r\n

\r\n

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n ${this.realtorDropdown.getHtml()}\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.moreInformationButton.getHtml()}\r\n
\r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Get More Information\")\r\n .replace(\"{1}\", this.housingData?.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n }\r\n}\r\n","export default class ContactRadioGroup {\r\n constructor() {\r\n this.valueInput = '';\r\n this.idEmail = 'contact-email';\r\n this.idPhone = 'contact-phone';\r\n this.idText = 'contact-text';\r\n this.radioInputSelector = '[name=\"preferredContactMethod\"]';\r\n this.labelEmail = ``;\r\n this.labelPhone = ``;\r\n this.labelText = ``;\r\n }\r\n\r\n set value(newValue){\r\n this.valueInput = newValue || '';\r\n }\r\n \r\n get value(){\r\n return this.valueInput;\r\n }\r\n \r\n getHtml() {\r\n return `
\r\n \r\n ${this.labelEmail}\r\n
\r\n
\r\n \r\n ${this.labelPhone}\r\n
\r\n
\r\n \r\n ${this.labelText}\r\n
`;\r\n }\r\n \r\n onChange(callback) {\r\n document.querySelectorAll(this.radioInputSelector).forEach((node) => node.addEventListener('change', callback));\r\n }\r\n }\r\n ","export default class DateInput {\r\n constructor() {\r\n this.tomorrow = (Date.parse(new Date().toDateString()) + 86400000);\r\n const tomorrowIsoString = new Date(this.tomorrow).toISOString().split(\"T\")[0];\r\n this.id = 'nhs_date';\r\n this.errorMessageId = 'nhs_ErrorForTourDateTime';\r\n this.errorCssClass = 'error';\r\n\r\n this.input = ``;\r\n this.label = ``;\r\n \r\n\r\n this.error = ``;\r\n }\r\n \r\n getHtml() {\r\n return `
\r\n ${this.label}${this.input}\r\n
\r\n ${this.error}`;\r\n }\r\n \r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n setInvalidState() {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n const node = this.getNode();\r\n \r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n \r\n setValidState() {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n const node = this.getNode();\r\n \r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n isValid(node) {\r\n return (+new Date(`${node.value}T00:00`)) >= (+this.tomorrow);\r\n }\r\n\r\n validate() {\r\n const node = this.getNode();\r\n const isValid = this.isValid(node);\r\n \r\n if (isValid) {\r\n this.setValidState(node);\r\n } else {\r\n this.setInvalidState(node);\r\n }\r\n \r\n return isValid;\r\n }\r\n }\r\n ","export default class SubmitRequestButton {\r\n constructor() {\r\n this.id = 'submitRequestButton';\r\n }\r\n \r\n getHtml() {\r\n const styles = 'class=\"btn btn--blue btn--width-100 btn--64-xl loading\"';\r\n return ``;\r\n }\r\n \r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n }\r\n ","export default class TourRadioOptions {\r\n constructor() {\r\n this.errorMessageId = 'nhs_ErrorForTourOption';\r\n this.idContactOneOnOne = 'contact-1-1';\r\n this.errorCssClass = 'error';\r\n this.idVideoChat = 'contact-vid-chat';\r\n this.radioChecked = '[name=\"leadAction\"]:checked';\r\n\r\n this.inputContactOneOne = ``;\r\n this.labelContactOneOne = ``;\r\n \r\n this.inputVideoChat = ``;\r\n this.labelVideoChat = ``;\r\n\r\n this.error = ``;\r\n }\r\n\r\n getHtml() {\r\n return `
\r\n
${this.inputContactOneOne}${this.labelContactOneOne}
\r\n
${this.inputVideoChat}${this.labelVideoChat}
\r\n
${this.error}`;\r\n }\r\n\r\n getCheckedNode() {\r\n return document.querySelector(this.radioChecked);\r\n }\r\n\r\n getVideoChatLabelNode() {\r\n return document.querySelector(`[for=\"${this.idVideoChat}\"]`);\r\n }\r\n\r\n getOneOnOnetLabelNode() {\r\n return document.querySelector(`[for=\"${this.idContactOneOnOne}\"]`);\r\n }\r\n\r\n setInvalidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.setAttribute('aria-invalid', true);\r\n node.classList.add(this.errorCssClass);\r\n errorMessage.removeAttribute('hidden');\r\n }\r\n\r\n setValidState(node) {\r\n const errorMessage = document.getElementById(this.errorMessageId);\r\n\r\n node.removeAttribute('aria-invalid');\r\n node.classList.remove(this.errorCssClass);\r\n errorMessage.setAttribute('hidden', true);\r\n }\r\n\r\n validate() {\r\n const node = this.getCheckedNode();\r\n const isValid = !!node;\r\n const nodeVideoChat = this.getVideoChatLabelNode();\r\n const nodeOneOnOne = this.getOneOnOnetLabelNode();\r\n\r\n if (isValid) {\r\n this.setValidState(nodeVideoChat);\r\n this.setValidState(nodeOneOnOne);\r\n } else {\r\n this.setInvalidState(nodeVideoChat);\r\n this.setInvalidState(nodeOneOnOne);\r\n }\r\n\r\n return isValid;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { backButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadTourForm } from '../services/taskFlow';\r\nimport ContactRadioGroup from './contactRadioGroup';\r\nimport DateInput from './dateInput';\r\nimport EmailInput from './emailInput';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport RequestButton from './requestButton';\r\nimport TourRadioOptions from './tourRadioOptions';\r\nimport ZipInput from './zipInput';\r\n\r\n/* Creates a new instance of a Request Tour Form to allow users making an appointment to tour the selected housing. */\r\nexport default class RequestTourForm {\r\n constructor() {\r\n const userProfile = store.getState()?.userProfile || {};\r\n const state = store.getState();\r\n this.id = state?.uiState?.modalInformation?.id;\r\n this.type = state?.uiState?.modalInformation?.type;\r\n this.excludeRecommendations = true;\r\n this.isPersistent = true;\r\n this.requestButton = new RequestButton();\r\n this.emailAddressInput = new EmailInput();\r\n this.emailAddressInput.value = userProfile.email;\r\n this.formId = 'requestATourPaid';\r\n this.fullNameInput = new NameInput();\r\n this.fullNameInput.value = userProfile.name;\r\n this.phoneNumberInput = new PhoneInput();\r\n this.phoneNumberInput.value = userProfile.phone;\r\n this.postalCodeInput = new ZipInput();\r\n this.postalCodeInput.value = userProfile.zip;\r\n this.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.contactRadioGroup = new ContactRadioGroup();\r\n this.contactRadioGroup.value = userProfile.preferredContactMethod;\r\n this.tourRadioOptions = new TourRadioOptions();\r\n this.dateInput = new DateInput();\r\n this.onClickEvent = null;\r\n }\r\n\r\n static validateNode(node) {\r\n return node.validate();\r\n }\r\n\r\n static getFormOpenedAnalyticsData(properties) {\r\n const customDimensions = {};\r\n\r\n if (properties.marketId) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n }\r\n\r\n if (properties.marketName && properties.stateAbbreviation) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n }\r\n\r\n if (properties.city) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n }\r\n\r\n return new GoogleAnalyticsEvent(\r\n 'Lead_Events',\r\n 'Search_Results_CTA_Request_Tour',\r\n 'Open_Form_Request_Tour',\r\n customDimensions);\r\n }\r\n\r\n setHousingData(properties = {}) {\r\n this.housingData = properties;\r\n }\r\n\r\n submitBrochureForm(event) {\r\n event.preventDefault();\r\n\r\n const validationFunctions = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.dateInput,\r\n this.tourRadioOptions,\r\n this.phoneNumberInput\r\n ];\r\n const result = validationFunctions.map(RequestTourForm.validateNode);\r\n\r\n if (result.some((isValid) => !isValid)) {\r\n return;\r\n }\r\n\r\n this.requestButton.getNode().disabled = 'disabled';\r\n const formData = new FormData(this.getForm());\r\n const brochureInformation = Object.fromEntries(formData.entries());\r\n\r\n brochureInformation.id = this.id;\r\n brochureInformation.type = `${this.type}-tour`;\r\n brochureInformation.excludeRecommendations = this.excludeRecommendations;\r\n\r\n const brochureLeadObject = leadConstructor(brochureInformation);\r\n brochureLeadObject.setHousingInformation?.(this.housingData.listingInformation);\r\n\r\n postLeadTourForm(brochureLeadObject);\r\n }\r\n\r\n bindEvents() {\r\n this.onClickEvent = this.submitBrochureForm.bind(this);\r\n this.phoneNumberInput.bindEvents();\r\n this.postalCodeInput.bindEvents();\r\n this.requestButton.getNode().addEventListener('click', this.onClickEvent);\r\n this.contactRadioGroup.onChange(this.onPreferredContactMethodChange.bind(this));\r\n\r\n const userProfile = store.getState()?.userProfile || {};\r\n this.setRequiredAttributeInPhone(userProfile.preferredContactMethod);\r\n this.bindChangeEvents();\r\n }\r\n\r\n /**\r\n * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n */\r\n bindChangeEvents() {\r\n const changeInputs = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n changeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n store.dispatch(userProfileActions.update(data))));\r\n }\r\n\r\n onPreferredContactMethodChange(event) {\r\n const value = event.target.value;\r\n this.setRequiredAttributeInPhone(value);\r\n }\r\n\r\n setRequiredAttributeInPhone(value) {\r\n if (value === 'Phone' || value === 'Text Message') {\r\n this.phoneNumberInput.setRequired();\r\n return;\r\n }\r\n\r\n this.phoneNumberInput.removeRequired();\r\n }\r\n\r\n unbindEvents() {\r\n this.requestButton.getNode().removeEventListener('click', this.onClickEvent);\r\n }\r\n\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n ${this.isPersistent ? backButton : ``}\r\n

Request A Tour

\r\n
\r\n
\r\n
\r\n Appointment Type\r\n
\r\n ${this.tourRadioOptions.getHtml()}\r\n
\r\n
\r\n ${this.dateInput.getHtml()}\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n Preferred Contact Method\r\n
\r\n ${this.contactRadioGroup.getHtml()}\r\n
\r\n
\r\n
\r\n ${this.requestButton.getHtml()}\r\n
\r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Submit Request\")\r\n .replace(\"{1}\", this.housingData?.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { backButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadBrochureForm } from '../services/taskFlow';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport ContactRadioGroup from './contactRadioGroup';\r\nimport EmailInput from './emailInput';\r\nimport InformationButton from './informationButton';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport ZipInput from './zipInput';\r\n\r\n/* Creates a new instance of a Limited Availability Form to allow users to get more information on a lisiting. */\r\nexport default class BrochureFormLimitedAvailability {\r\n constructor() {\r\n const state = store.getState();\r\n const userProfile = state?.userProfile || {};\r\n this.id = state?.uiState.modalInformation.id;\r\n this.type = state?.uiState.modalInformation.type;\r\n this.excludeRecommendations = false;\r\n this.isPersistent = true;\r\n this.moreInformationButton = new InformationButton();\r\n this.commentsTextArea = new CommentsTextArea();\r\n this.emailAddressInput = new EmailInput();\r\n this.emailAddressInput.value = userProfile.email;\r\n this.formId = 'limitedAvailabilityForm';\r\n this.fullNameInput = new NameInput();\r\n this.fullNameInput.value = userProfile.name;\r\n this.contactRadioGroup = new ContactRadioGroup();\r\n this.contactRadioGroup.value = userProfile.preferredContactMethod;\r\n this.postalCodeInput = new ZipInput();\r\n this.postalCodeInput.value = userProfile.zip;\r\n this.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.phoneNumberInput = new PhoneInput();\r\n this.phoneNumberInput.value = userProfile.phone;\r\n this.onClickEvent = null;\r\n }\r\n\r\n /**\r\n * validateNode: Check if the field has a value as expected.\r\n * @param {Object} node Input to validate\r\n * @returns A boolean value indicating whether the input is valid or not.\r\n */\r\n static validateNode(node) {\r\n return node.validate();\r\n }\r\n\r\n /**\r\n * getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n * @param {Object} properties Information regarding to the listing.\r\n * @returns The Google Analtic event information.\r\n */\r\n static getFormOpenedAnalyticsData(properties) {\r\n const customDimensions = {};\r\n\r\n if (properties.marketId) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n }\r\n\r\n if (properties.marketName && properties.stateAbbreviation) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n }\r\n\r\n if (properties.city) {\r\n customDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n }\r\n return new GoogleAnalyticsEvent(\r\n \"Lead_Events\",\r\n \"Search_Results_CTA_Free_Brochure\",\r\n \"Open_Form_Free_Brochure\",\r\n customDimensions);\r\n }\r\n\r\n /**\r\n * setHousingData: Sets the housing information for the form.\r\n * @param {Object} properties Information regarding to the listing.\r\n */\r\n setHousingData(properties = {}) {\r\n this.housingData = properties;\r\n }\r\n\r\n /**\r\n * submitBrochureForm: Process to validate and submit the form.\r\n * @param {event} event Click event.\r\n */\r\n submitBrochureForm(event) {\r\n event.preventDefault();\r\n\r\n const validationFunctions = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n const result = validationFunctions.map(BrochureFormLimitedAvailability.validateNode);\r\n\r\n if (result.some((isValid) => !isValid)) {\r\n return;\r\n }\r\n\r\n this.moreInformationButton.getNode().disabled = 'disabled';\r\n const formData = new FormData(this.getForm());\r\n const brochureInformation = Object.fromEntries(formData.entries());\r\n\r\n brochureInformation.id = this.id;\r\n brochureInformation.type = `${this.type}-brochure`;\r\n\r\n const brochureLeadObject = leadConstructor(brochureInformation);\r\n brochureLeadObject.setHousingInformation?.(this.housingData.listingInformation);\r\n\r\n postLeadBrochureForm(brochureLeadObject);\r\n }\r\n\r\n /**\r\n * Sets the binding required for the form.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitBrochureForm.bind(this);\r\n this.phoneNumberInput.bindEvents();\r\n this.postalCodeInput.bindEvents();\r\n this.moreInformationButton.getNode().addEventListener('click', this.onClickEvent);\r\n this.contactRadioGroup.onChange(this.onPreferredContactMethodChange.bind(this));\r\n\r\n const userProfile = store.getState()?.userProfile || {};\r\n this.setRequiredAttributeInPhone(userProfile.preferredContactMethod);\r\n this.bindChangeEvents();\r\n }\r\n\r\n /**\r\n * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n */\r\n bindChangeEvents() {\r\n const changeInputs = [\r\n this.emailAddressInput,\r\n this.fullNameInput,\r\n this.postalCodeInput,\r\n this.phoneNumberInput,\r\n ];\r\n changeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n store.dispatch(userProfileActions.update(data))));\r\n }\r\n\r\n /**\r\n * Handles the change contact radio group event.\r\n * @param {event} event Change event.\r\n */\r\n onPreferredContactMethodChange(event) {\r\n const value = event.target.value;\r\n this.setRequiredAttributeInPhone(value);\r\n }\r\n\r\n /**\r\n * Sets the phone number input as required when it applies.\r\n * @param {string} value Contact option selected.\r\n */\r\n setRequiredAttributeInPhone(value) {\r\n if (value === 'Phone' || value === 'Text Message') {\r\n this.phoneNumberInput.setRequired();\r\n return;\r\n }\r\n\r\n this.phoneNumberInput.removeRequired();\r\n }\r\n\r\n /**\r\n * Removes the bindings that should not be still using.\r\n */\r\n unbindEvents() {\r\n this.moreInformationButton.getNode().removeEventListener('click', this.onClickEvent);\r\n }\r\n\r\n /**\r\n * getForm: Gets the form container \r\n * @returns A HTML element related to the form container.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * Gets the HTML structure for the limited availability brochure form paid.\r\n * @returns The string with the HTML structure.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n ${this.isPersistent ? backButton : ``}\r\n

Limited Availability at this Community!

\r\n

\r\n Don't miss out! Get info and updates.\r\n You'll be put on the list for updates, and you can ask other questions about availability.

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n Preferred Contact Method\r\n
\r\n ${this.contactRadioGroup.getHtml()}\r\n
\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.moreInformationButton.getHtml()}\r\n
\r\n \r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Get More Information\")\r\n .replace(\"{1}\", this.housingData?.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n }\r\n}\r\n","export default class AskQuestionButton {\r\n constructor() {\r\n this.id = 'askQuestionButton';\r\n }\r\n\r\n getHtml() {\r\n const styles = 'class=\"btn btn--yellow btn--width-100 btn--48-lg loading\"';\r\n return ``;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { closeButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadAskQuestionForm } from '../services/taskFlow';\r\nimport AskQuestionButton from './askQuestionButton';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport EmailInput from './emailInput';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport ZipInput from './zipInput';\r\nimport RealtorDropdown from './realtorDropdown';\r\n\r\n/* Creates a new instance of a Ask Question Form to allow users asking question about the selected housing unit. */\r\nexport default class AskQuestionFormPaid {\r\n\tconstructor() {\r\n\t\tconst state = store.getState();\r\n\t\tconst userProfile = state?.userProfile || {};\r\n\t\tthis.id = state?.uiState.modalInformation.id;\r\n\t\tthis.type = state?.uiState.modalInformation.type;\r\n\t\tthis.fromPage = state?.uiState.modalInformation.fromPage;\r\n\t\tthis.excludeRecommendations = false;\r\n\t\tthis.getAskQuestionButton = new AskQuestionButton();\r\n\t\tthis.commentsTextArea = new CommentsTextArea();\r\n\t\tthis.emailAddressInput = new EmailInput();\r\n\t\tthis.emailAddressInput.value = userProfile.email;\r\n\t\tthis.formId = 'askQuestionFormPaid';\r\n\t\tthis.fullNameInput = new NameInput();\r\n\t\tthis.fullNameInput.value = userProfile.name;\r\n\t\tthis.phoneNumberInput = new PhoneInput();\r\n\t\tthis.phoneNumberInput.value = userProfile.phone;\r\n\t\tthis.postalCodeInput = new ZipInput();\r\n\t\tthis.postalCodeInput.value = userProfile.zip;\r\n\t\tthis.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.realtorDropdown = new RealtorDropdown();\r\n this.realtorDropdown.value = userProfile.realtorQuestion;\r\n\t\tthis.onClickEvent = null;\r\n\t}\r\n\r\n\t/**\r\n\t\t* validateNode: Check if the field has a value as expected.\r\n\t\t* @param {Object} node Input to validate\r\n\t\t* @returns A boolean value indicating whether the input is valid or not.\r\n\t\t*/\r\n\tstatic validateNode(node) {\r\n\t\treturn node.validate();\r\n\t}\r\n\r\n\t/**\r\n\t\t* getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n\t\t* @param {Object} properties Information regarding to the listing.\r\n\t\t* @returns The Google Analtic event information.\r\n\t\t*/\r\n\tstatic getFormOpenedAnalyticsData(properties) {\r\n\t\tconst customDimensions = {};\r\n\r\n\t\tif (properties.marketId) {\r\n\t\t\tcustomDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n\t\t}\r\n\r\n\t\tif (properties.marketName && properties.stateAbbreviation) {\r\n\t\t\tcustomDimensions[\r\n\t\t\t\t[GoogleAnalyticsCustomDimensions.MarketName().getName()]\r\n\t\t\t] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n\t\t}\r\n\r\n\t\tif (properties.city) {\r\n\t\t\tcustomDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n\t\t}\r\n\r\n\t\treturn new GoogleAnalyticsEvent(\r\n\t\t\t'Lead Events',\r\n\t\t\t'Search Results CTA Ask Question',\r\n\t\t\t'Open Form - Ask Question',\r\n\t\t\tcustomDimensions\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t\t* setHousingData: Sets the housing information for the form.\r\n\t\t* @param {Object} properties Information regarding to the listing.\r\n\t\t*/\r\n\tsetHousingData(properties = {}) {\r\n\t\tthis.housingData = properties;\r\n\t}\r\n\r\n\t/**\r\n\t\t* submitAskQuestionForm: Process to validate and submit the form.\r\n\t\t* @param {event} event Click event.\r\n\t\t*/\r\n\tsubmitAskQuestionForm(event) {\r\n\t\tevent.preventDefault();\r\n\r\n\t\tconst validationFunctions = [\r\n\t\t\tthis.emailAddressInput,\r\n\t\t\tthis.fullNameInput,\r\n\t\t\tthis.postalCodeInput,\r\n\t\t\tthis.phoneNumberInput,\r\n\t\t];\r\n\t\tconst result = validationFunctions.map(AskQuestionFormPaid.validateNode);\r\n\r\n\t\tif (result.some((isValid) => !isValid)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.getAskQuestionButton.getNode().disabled = 'disabled';\r\n\t\tconst formData = new FormData(this.getForm());\r\n\t\tconst formInformation = Object.fromEntries(formData.entries());\r\n\r\n\t\tformInformation.id = this.id;\r\n\t\tformInformation.type = `${this.type}-brochure`;\r\n\t\tformInformation.excludeRecommendations = this.excludeRecommendations;\r\n\t\tformInformation.fromPage = this.housingData.fromPage;\r\n\r\n\t\tconst leadObject = leadConstructor(formInformation);\r\n\t\tleadObject.setHousingInformation?.(this.housingData.listingInformation);\r\n\r\n\t\tpostLeadAskQuestionForm(leadObject);\r\n\t}\r\n\r\n\t/**\r\n\t\t* Sets the binding required for the form.\r\n\t\t*/\r\n\tbindEvents() {\r\n\t\tthis.onClickEvent = this.submitAskQuestionForm.bind(this);\r\n\t\tthis.phoneNumberInput.bindEvents();\r\n\t\tthis.postalCodeInput.bindEvents();\r\n\t\tif (this.fullNameInput.value === '') {\r\n\t\t\tthis.fullNameInput.focus();\r\n\t\t}\r\n this.realtorDropdown.setSelectedValue();\r\n\t\tthis.getAskQuestionButton.getNode().addEventListener('click', this.onClickEvent);\r\n\t\tthis.bindChangeEvents();\r\n\t}\r\n\r\n\t/**\r\n\t\t* bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n\t\t*/\r\n\tbindChangeEvents() {\r\n\t\tconst changeInputs = [\r\n\t\t\tthis.emailAddressInput,\r\n\t\t\tthis.fullNameInput,\r\n\t\t\tthis.postalCodeInput,\r\n\t\t\tthis.phoneNumberInput,\r\n this.realtorDropdown,\r\n\t\t];\r\n\t\tchangeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n\t\t\tstore.dispatch(userProfileActions.update(data))));\r\n\t}\r\n\r\n\t/**\r\n\t\t* Removes the bindings that should not be still using.\r\n\t\t*/\r\n\tunbindEvents() {\r\n\t\tthis.getAskQuestionButton.getNode().removeEventListener('click', this.onClickEvent);\r\n\t}\r\n\r\n\t/**\r\n\t\t* getForm: Gets the form container \r\n\t\t* @returns A HTML element related to the form container.\r\n\t\t*/\r\n\tgetForm() {\r\n\t\treturn document.getElementById(this.formId);\r\n\t}\r\n\r\n\t/**\r\n\t\t* Gets the HTML structure for the ask question form paid.\r\n\t\t* @returns The string with the HTML structure.\r\n\t\t*/\r\n\tgetHtml() {\r\n return `\r\n
\r\n ${closeButton}\r\n

Ask a question

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n ${this.realtorDropdown.getHtml()}\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.getAskQuestionButton.getHtml()}\r\n
\r\n \r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Ask Question\")\r\n .replace(\"{1}\", this.housingData?.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { closeButton, privacyPolicyParagraph } from '../constants/sharedHtml';\r\nimport leadConstructor from '../services/leadConstructor';\r\nimport { postLeadBrochureForm } from '../services/taskFlow';\r\nimport BrochureButton from './brochureButton';\r\nimport CommentsTextArea from './commentsTextArea';\r\nimport EmailInput from './emailInput';\r\nimport NameInput from './nameInput';\r\nimport PhoneInput from './phoneInput';\r\nimport ZipInput from './zipInput';\r\nimport RealtorDropdown from './realtorDropdown';\r\n\r\n/* Creates a new instance of a Brochure form paid version to manage the Manufactured product type listings. */\r\nexport default class ManufacturedBrochureFormPaid {\r\n\tconstructor() {\r\n\t\tconst state = store.getState();\r\n\t\tconst userProfile = state?.userProfile || {};\r\n\t\tthis.id = state?.uiState.modalInformation.id;\r\n\t\tthis.type = state?.uiState.modalInformation.type;\r\n\t\tthis.fromPage = state?.uiState.modalInformation.fromPage;\r\n\t\tthis.excludeRecommendations = true;\r\n\t\tthis.getBrochureButton = new BrochureButton();\r\n\t\tthis.commentsTextArea = new CommentsTextArea();\r\n\t\tthis.emailAddressInput = new EmailInput();\r\n\t\tthis.emailAddressInput.value = userProfile.email;\r\n\t\tthis.formId = 'manufacturedBrochureFormPaid';\r\n\t\tthis.fullNameInput = new NameInput();\r\n\t\tthis.fullNameInput.value = userProfile.name;\r\n\t\tthis.phoneNumberInput = new PhoneInput();\r\n\t\tthis.phoneNumberInput.value = userProfile.phone;\r\n\t\tthis.postalCodeInput = new ZipInput();\r\n\t\tthis.postalCodeInput.value = userProfile.zip;\r\n\t\tthis.postalCodeInput.isInternational = userProfile.livesOutside;\r\n this.realtorDropdown = new RealtorDropdown();\r\n this.realtorDropdown.value = userProfile.realtorQuestion;\r\n\t\tthis.onClickEvent = null;\r\n\t}\r\n\r\n\t/**\r\n\t * validateNode: Check if the field has a value as expected.\r\n\t * @param {Object} node Input to validate\r\n\t * @returns A boolean value indicating whether the input is valid or not.\r\n\t */\r\n\tstatic validateNode(node) {\r\n\t\treturn node.validate();\r\n\t}\r\n\r\n\t/**\r\n\t * getFormOpenedAnalyticsData: Gets the object required for the Google Analytics events on form opened.\r\n\t * @param {Object} properties Information regarding to the listing.\r\n\t * @returns The Google Analtic event information.\r\n\t */\r\n\tstatic getFormOpenedAnalyticsData(properties) {\r\n\t\tconst customDimensions = {};\r\n\r\n\t\tif (properties.marketId) {\r\n\t\t\tcustomDimensions[[GoogleAnalyticsCustomDimensions.MarketId().getName()]] = properties.marketId;\r\n\t\t}\r\n\r\n\t\tif (properties.marketName && properties.stateAbbreviation) {\r\n\t\t\tcustomDimensions[[GoogleAnalyticsCustomDimensions.MarketName().getName()]] = `${properties.marketName}, ${properties.stateAbbreviation}`;\r\n\t\t}\r\n\r\n\t\tif (properties.city) {\r\n\t\t\tcustomDimensions[[GoogleAnalyticsCustomDimensions.City().getName()]] = properties.city;\r\n\t\t}\r\n\r\n\t\treturn new GoogleAnalyticsEvent(\r\n\t\t\t\"Lead Events\",\r\n\t\t\t\"Search Results CTA Free Brochure\",\r\n\t\t\t\"Open Form - Free Brochure\",\r\n\t\t\tcustomDimensions);\r\n\t}\r\n\r\n\t/**\r\n\t * setHousingData: Sets the housing information for the form.\r\n\t * @param {Object} properties Information regarding to the listing.\r\n\t */\r\n\tsetHousingData(properties = {}) {\r\n\t\tthis.housingData = properties;\r\n\t}\r\n\r\n\t/**\r\n\t * submitBrochureForm: Process to validate and submit the form.\r\n\t * @param {event} event Click event.\r\n\t */\r\n\tsubmitBrochureForm(event) {\r\n\t\tevent.preventDefault();\r\n\r\n\t\tconst validationFunctions = [\r\n\t\t\tthis.emailAddressInput,\r\n\t\t\tthis.fullNameInput,\r\n\t\t\tthis.postalCodeInput,\r\n\t\t\tthis.phoneNumberInput,\r\n\t\t];\r\n\t\tconst result = validationFunctions.map(ManufacturedBrochureFormPaid.validateNode);\r\n\t\tconst isSomeInvalidField = result.some((isValid) => !isValid);\r\n\t\tif (isSomeInvalidField) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.getBrochureButton.getNode().disabled = 'disabled';\r\n\t\tconst formData = new FormData(this.getForm());\r\n\t\tconst brochureInformation = Object.fromEntries(formData.entries());\r\n\r\n\t\tbrochureInformation.id = this.id;\r\n\t\tbrochureInformation.type = `${this.type}-brochure`;\r\n\t\tbrochureInformation.excludeRecommendations = this.excludeRecommendations;\r\n\t\tbrochureInformation.fromPage = this.housingData.fromPage;\r\n\r\n\t\tconst brochureLeadObject = leadConstructor(brochureInformation);\r\n\t\tbrochureLeadObject.setHousingInformation?.(this.housingData.listingInformation);\r\n\r\n\t\tpostLeadBrochureForm(brochureLeadObject);\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the binding required for the form.\r\n\t */\r\n\tbindEvents() {\r\n\t\tthis.onClickEvent = this.submitBrochureForm.bind(this);\r\n\t\tthis.phoneNumberInput.bindEvents();\r\n\t\tthis.postalCodeInput.bindEvents();\r\n\t\tif (this.fullNameInput.value === '') {\r\n\t\t\tthis.fullNameInput.focus();\r\n\t\t}\r\n this.realtorDropdown.setSelectedValue();\r\n\t\tthis.getBrochureButton.getNode().addEventListener('click', this.onClickEvent);\r\n\t\tthis.bindChangeEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * bindChangeEvents: Get the form inputs then subscribe each OnChangeEvent to store and persist their values\r\n\t */\r\n\tbindChangeEvents() {\r\n\t\tconst changeInputs = [\r\n\t\t\tthis.emailAddressInput,\r\n\t\t\tthis.fullNameInput,\r\n\t\t\tthis.postalCodeInput,\r\n\t\t\tthis.phoneNumberInput,\r\n this.realtorDropdown,\r\n\t\t];\r\n\t\tchangeInputs.forEach(input => input.getOnChangeEvent().subscribe(data =>\r\n\t\t\tstore.dispatch(userProfileActions.update(data))));\r\n\t}\r\n\r\n\t/**\r\n\t * Removes the bindings that should not be still using.\r\n\t */\r\n\tunbindEvents() {\r\n\t\tthis.getBrochureButton.getNode().removeEventListener('click', this.onClickEvent);\r\n\t}\r\n\r\n\t/**\r\n\t * getForm: Gets the form container \r\n\t * @returns A HTML element related to the form container.\r\n\t */\r\n\tgetForm() {\r\n\t\treturn document.getElementById(this.formId);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the HTML structure for the manufactured brochure form paid.\r\n\t * @returns The string with the HTML structure.\r\n\t */\r\n\tgetHtml() {\r\n\t\treturn `\r\n
\r\n ${closeButton}\r\n

Check your email & download the brochure

\r\n
\r\n
\r\n
\r\n ${this.fullNameInput.getHtml()}\r\n
\r\n
\r\n ${this.emailAddressInput.getHtml()}\r\n
\r\n
\r\n ${this.phoneNumberInput.getHtml()}\r\n
\r\n
\r\n ${this.postalCodeInput.getHtml()}\r\n
\r\n
\r\n ${this.realtorDropdown.getHtml()}\r\n
\r\n
\r\n ${this.commentsTextArea.getHtml()}\r\n
\r\n
\r\n ${this.getBrochureButton.getHtml()}\r\n
\r\n \r\n
\r\n
\r\n ${privacyPolicyParagraph.replace(\"{0}\", \"Get Brochure\")\r\n .replace(\"{1}\", this.housingData?.listingInformation?.brandName ?? \"the builder\")}\r\n
`;\r\n\t}\r\n}\r\n","import BrochureFormPaid from '../components/brochureFormPaid';\r\nimport InformationFormBasic from '../components/informationFormBasic';\r\nimport InformationFormPaid from '../components/informationFormPaid';\r\nimport RequestTourForm from '../components/requestTourForm';\r\nimport BrochureFormLimitedAvailability from '../components/brochureFormLimitedAvailability';\r\nimport LeadFormType from '../enums/leadFormType';\r\nimport AskQuestionFormPaid from '../components/askQuestionFormPaid';\r\nimport ManufacturedBrochureFormPaid from '../components/manufacturedBrochureFormPaid';\r\n\r\nconst leadGeneratorConstructors = new Map();\r\n\r\nleadGeneratorConstructors.set(LeadFormType.BrochureFormPaid.toString(), BrochureFormPaid);\r\nleadGeneratorConstructors.set(LeadFormType.InformationFormPaid.toString(), InformationFormPaid);\r\nleadGeneratorConstructors.set(LeadFormType.RequestTourForm.toString(), RequestTourForm);\r\nleadGeneratorConstructors.set(LeadFormType.BrochureFormLimitedAvailability.toString(), BrochureFormLimitedAvailability);\r\nleadGeneratorConstructors.set(LeadFormType.InformationFormBasic.toString(), InformationFormBasic);\r\nleadGeneratorConstructors.set(LeadFormType.AskQuestionFormPaid.toString(), AskQuestionFormPaid);\r\nleadGeneratorConstructors.set(LeadFormType.ManufacturedBrochureFormPaid.toString(), ManufacturedBrochureFormPaid);\r\n\r\n/**\r\n * Returns the class constructor to create a lead generator.\r\n *\r\n * @param leadGeneratorName - The name of the lead generator requested.\r\n */\r\nexport default (leadGeneratorName, properties) => {\r\n const generator = leadGeneratorConstructors.get(leadGeneratorName);\r\n\r\n if (!generator) {\r\n return null;\r\n }\r\n\r\n return new generator.prototype.constructor(properties);\r\n};\r\n","export default class RecommendedButton {\r\n constructor() {\r\n this.id = 'getRecommendedBrochureButton';\r\n }\r\n\r\n getHtml() {\r\n return ``;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n}\r\n","export default class SkipButton {\r\n constructor() {\r\n this.id = 'skipRecommendation';\r\n }\r\n\r\n getHtml() {\r\n return ``;\r\n }\r\n\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n}\r\n","import {\r\n closeModalIconSvg,\r\n thanksContentIconSvg,\r\n thankYouEmailSvg, \r\n thankYouHeartSvg, \r\n thankYouPhoneSvg, \r\n thankYouSuccessSvg\r\n} from 'constants/svg-assets';\r\n\r\nexport const closeModalSvg = closeModalIconSvg;\r\nexport const thanksContentSvg = thanksContentIconSvg;\r\nexport const thankYouEmail = thankYouEmailSvg;\r\nexport const thankYouHeart = thankYouHeartSvg;\r\nexport const thankYouPhone = thankYouPhoneSvg;\r\nexport const thankYouSuccess = thankYouSuccessSvg;\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport brochureLeadConstructor from '../services/leadConstructor';\r\nimport { postRecommendedLeadForm, updateModalProgress } from '../services/taskFlow';\r\nimport RecommendedButton from './recommendedButton';\r\nimport SkipButton from './skipButton';\r\nimport { closeModalSvg } from '../constants/svgIcons';\r\nimport { recommendedPolicyParagraph } from '../constants/sharedHtml';\r\n\r\nexport default class RecommendedScreen {\r\n constructor(recommendationsHtml) {\r\n this.closeAttribute = '[data-close]';\r\n this.formId = 'get-recommended-communities';\r\n this.getBrochureButton = new RecommendedButton();\r\n this.id = store.getState().uiState.modalInformation.id;\r\n this.onClickEvent = null;\r\n this.onSkipEvent = null;\r\n this.recommendationsHtml = recommendationsHtml;\r\n this.recommendedCheckAttribute = '[data-recommendation-check]';\r\n this.skipButton = new SkipButton();\r\n this.type = 'recommended';\r\n }\r\n\r\n /**\r\n * Submits information for recommended communities selected by the user.\r\n * @param {*} event that triggered this action\r\n */\r\n submitRecommendationsForm(event) {\r\n event.preventDefault();\r\n\r\n const formData = new FormData(this.getForm());\r\n const brochureInformation = Object.fromEntries(formData.entries());\r\n const state = store.getState();\r\n const userProfile = state?.userProfile;\r\n brochureInformation.id = this.id;\r\n brochureInformation.type = this.type;\r\n\r\n // we fill the user information with \r\n // the data captured in the previous form.\r\n brochureInformation.email = userProfile.email;\r\n brochureInformation.postalCode = userProfile.zip;\r\n brochureInformation.international = userProfile.livesOutside;\r\n brochureInformation.phone = userProfile.phone;\r\n\r\n const userName = userProfile.name.split(' ');\r\n brochureInformation.firstName = userName[0];\r\n brochureInformation.lastName = userName.slice(1).join(\" \").trim();\r\n brochureInformation.fromPage = state?.uiState?.modalInformation?.fromPage;\r\n\r\n const brochureLeadObject = brochureLeadConstructor(brochureInformation);\r\n\r\n const modalInformation = this.getThankYouModalInformation(brochureLeadObject.recoComms);\r\n store.dispatch(uiStateSlice.actions.modalInformation(modalInformation));\r\n\r\n postRecommendedLeadForm(brochureLeadObject);\r\n }\r\n\r\n /**\r\n * Binds the events needed so recommended screen can respond to user interactions.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitRecommendationsForm.bind(this);\r\n this.onSkipEvent = this.skipModal.bind(this);\r\n\r\n const getRecoBrochureElement = this.getBrochureButton.getNode();\r\n getRecoBrochureElement?.addEventListener('click', this.onClickEvent);\r\n\r\n const skipElement = this.skipButton.getNode();\r\n skipElement?.addEventListener('click', this.onSkipEvent);\r\n\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', RecommendedScreen.closeModal));\r\n\r\n const recommendedElements = document.querySelectorAll(this.recommendedCheckAttribute);\r\n recommendedElements.forEach((elem) =>\r\n elem?.addEventListener('click', this.onRecommendationChecked.bind(this)));\r\n }\r\n\r\n /**\r\n * Unbinds the events needed so recommended screen can respond to user interactions.\r\n */\r\n unbindEvents() {\r\n this.skipButton.getNode().removeEventListener('click', this.onSkipEvent);\r\n this.getBrochureButton.getNode().removeEventListener('click', this.onClickEvent);\r\n const recommendedElements = document.querySelectorAll(this.recommendedCheckAttribute);\r\n recommendedElements.forEach((elem) => {\r\n elem.click = null\r\n });\r\n }\r\n\r\n /**\r\n * Skips the recommended modal step since the user is not interested in any of the\r\n * recommendations provided.\r\n */\r\n skipModal(event) {\r\n event.preventDefault();\r\n const modalInformation = this.getThankYouModalInformation();\r\n modalInformation.googleAnalyticsDTO =\r\n new GoogleAnalyticsEvent(\"Lead Events\", \"Form Skip\", \"Search - FB - Dir Rec\");\r\n updateModalProgress(modalInformation);\r\n }\r\n\r\n /**\r\n * \r\n * Validates if there's at least 1 recommendation selected. If that's not the case,\r\n * disables the brochure button.\r\n */\r\n onRecommendationChecked() {\r\n const checkedRecos = this.getForm().querySelectorAll(`${this.recommendedCheckAttribute}:checked`);\r\n if (checkedRecos.length === 0) {\r\n this.getBrochureButton.getNode().disabled = true;\r\n return;\r\n }\r\n\r\n this.getBrochureButton.getNode().disabled = false;\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n /**\r\n * \r\n * @returns the DOM element representing the recommendations form.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * \r\n * @returns an object with the information to move to thank you screen\r\n */\r\n getThankYouModalInformation(recommendedCommunities) {\r\n return {\r\n id: this.id,\r\n name: 'thankYouScreen',\r\n selectedRecommendedCommunities: recommendedCommunities,\r\n };\r\n }\r\n\r\n /**\r\n * Returns an array of unique recommended brands from the recommendationsHtml property.\r\n * @returns {string[]} An array of unique recommended brands.\r\n */\r\n getRecommendedBrands() {\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(this.recommendationsHtml, 'text/html');\r\n const brandElements = doc.querySelectorAll('.result__brand');\r\n const brands = [];\r\n brandElements.forEach((el) => {\r\n const brand = el.textContent.trim();\r\n\r\n // Only count unique brands\r\n if (!brands.includes(brand)) {\r\n brands.push(brand);\r\n }\r\n });\r\n return brands;\r\n }\r\n\r\n /**\r\n * \r\n * @returns the HTML that represents the recommendations screen.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n \r\n

Discover More Great Communities

\r\n

Select additional listings for more information

\r\n
\r\n
\r\n
\r\n ${this.recommendationsHtml}\r\n
\r\n
\r\n ${this.skipButton.getHtml()}\r\n ${this.getBrochureButton.getHtml()}\r\n
\r\n
\r\n
\r\n ${recommendedPolicyParagraph.replace(\"{0}\", \"Get More Info\")}\r\n
`;\r\n }\r\n}","export default class RecommendedButtonBasic {\r\n constructor() {\r\n this.id = 'getRecommendedBrochureButton';\r\n }\r\n\r\n /**\r\n * \r\n * @returns the HTML that represents the basic recommendation modal button.\r\n */\r\n getHtml() {\r\n return ``;\r\n }\r\n\r\n /**\r\n * \r\n * @returns the HTML button in the element with the corresponding id.\r\n */\r\n getNode() {\r\n return document.getElementById(this.id);\r\n }\r\n}","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport brochureLeadConstructor from '../services/leadConstructor';\r\nimport { postRecommendedLeadForm, updateModalProgress } from '../services/taskFlow';\r\nimport RecommendedButtonBasic from './recommendedButtonBasic';\r\nimport SkipButton from './skipButton';\r\nimport { closeModalSvg } from '../constants/svgIcons';\r\nimport { recommendedPolicyParagraph } from '../constants/sharedHtml';\r\n\r\nexport default class RecommendedScreenBasic {\r\n constructor(recommendationsHtml) {\r\n this.closeAttribute = '[data-close]';\r\n this.formId = 'get-recommended-communities';\r\n this.getBrochureButtonBasic = new RecommendedButtonBasic();\r\n this.id = store.getState().uiState.modalInformation.id;\r\n this.onClickEvent = null;\r\n this.onSkipEvent = null;\r\n this.recommendationsHtml = recommendationsHtml;\r\n this.recommendedCheckAttribute = '[data-recommendation-check]';\r\n this.skipButton = new SkipButton();\r\n this.type = 'recommended';\r\n }\r\n\r\n /**\r\n * Submits information for recommended communities selected by the user.\r\n * @param {*} event that triggered this action\r\n */\r\n submitRecommendationsForm(event) {\r\n event.preventDefault();\r\n\r\n const formData = new FormData(this.getForm());\r\n const brochureInformation = Object.fromEntries(formData.entries());\r\n const state = store.getState();\r\n const userProfile = state?.userProfile;\r\n brochureInformation.id = this.id;\r\n brochureInformation.type = this.type;\r\n\r\n // we fill the user information with \r\n // the data captured in the previous form.\r\n brochureInformation.email = userProfile.email;\r\n brochureInformation.postalCode = userProfile.zip;\r\n brochureInformation.international = userProfile.livesOutside;\r\n brochureInformation.phone = userProfile.phone;\r\n\r\n const userName = userProfile.name.split(' ');\r\n brochureInformation.firstName = userName[0];\r\n brochureInformation.lastName = userName.slice(1).join(\" \").trim();\r\n brochureInformation.fromPage = state?.uiState?.modalInformation?.fromPage;\r\n\r\n const brochureLeadObject = brochureLeadConstructor(brochureInformation);\r\n\r\n const modalInformation = this.getThankYouModalInformation(brochureLeadObject.recoComms);\r\n store.dispatch(uiStateSlice.actions.modalInformation(modalInformation));\r\n\r\n postRecommendedLeadForm(brochureLeadObject);\r\n }\r\n\r\n /**\r\n * Binds the events needed so recommended screen can respond to user interactions.\r\n */\r\n bindEvents() {\r\n this.onClickEvent = this.submitRecommendationsForm.bind(this);\r\n this.onSkipEvent = this.skipModal.bind(this);\r\n\r\n const getRecoBrochureElement = this.getBrochureButtonBasic.getNode();\r\n getRecoBrochureElement?.addEventListener('click', this.onClickEvent);\r\n\r\n const skipElement = this.skipButton.getNode();\r\n skipElement?.addEventListener('click', this.onSkipEvent);\r\n\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', RecommendedScreenBasic.closeModal));\r\n\r\n const recommendedElements = document.querySelectorAll(this.recommendedCheckAttribute);\r\n recommendedElements.forEach((elem) =>\r\n elem?.addEventListener('click', this.onRecommendationChecked.bind(this)));\r\n }\r\n\r\n /**\r\n * Unbinds the events needed so recommended screen can respond to user interactions.\r\n */\r\n unbindEvents() {\r\n this.skipButton.getNode().removeEventListener('click', this.onSkipEvent);\r\n this.getBrochureButtonBasic.getNode().removeEventListener('click', this.onClickEvent);\r\n const recommendedElements = document.querySelectorAll(this.recommendedCheckAttribute);\r\n recommendedElements.forEach((elem) => {\r\n elem.click = null\r\n });\r\n }\r\n\r\n /**\r\n * Skips the recommended modal step since the user is not interested in any of the\r\n * recommendations provided.\r\n */\r\n skipModal(event) {\r\n event.preventDefault();\r\n const modalInformation = this.getThankYouModalInformation();\r\n modalInformation.googleAnalyticsDTO = new GoogleAnalyticsEvent(\"Lead Events\", \"Form Skip\", \r\n \"Search - LM - Dir Rec\");\r\n updateModalProgress(modalInformation);\r\n }\r\n\r\n /**\r\n * \r\n * Validates if there's at least 1 recommendation selected. If that's not the case,\r\n * disables the brochure button.\r\n */\r\n onRecommendationChecked() {\r\n const checkedRecos = this.getForm().querySelectorAll(`${this.recommendedCheckAttribute}:checked`);\r\n if (checkedRecos.length === 0) {\r\n this.getBrochureButtonBasic.getNode().disabled = true;\r\n return;\r\n }\r\n\r\n this.getBrochureButtonBasic.getNode().disabled = false;\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n /**\r\n * \r\n * @returns the DOM element representing the recommendations form.\r\n */\r\n getForm() {\r\n return document.getElementById(this.formId);\r\n }\r\n\r\n /**\r\n * \r\n * @returns an object with the information to move to thank you screen\r\n */\r\n getThankYouModalInformation(recommendedCommunities) {\r\n return {\r\n id: this.id,\r\n name: 'thankYouScreen',\r\n selectedRecommendedCommunities: recommendedCommunities,\r\n };\r\n }\r\n\r\n /**\r\n * Returns an array of unique recommended brands from the recommendationsHtml property.\r\n * @returns {string[]} An array of unique recommended brands.\r\n */\r\n getRecomendedBrands() {\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(this.recommendationsHtml, 'text/html');\r\n const brandElements = doc.querySelectorAll('.result__brand');\r\n const brands = [];\r\n brandElements.forEach((el) => {\r\n const brand = el.textContent.trim();\r\n\r\n // Only count unique brands\r\n if (!brands.includes(brand)) {\r\n brands.push(brand);\r\n }\r\n });\r\n return brands;\r\n }\r\n\r\n /**\r\n * \r\n * @returns the HTML that represents the recommendations screen.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n \r\n

Discover More Great Communities

\r\n

Select additional listings for more information

\r\n
\r\n
\r\n
\r\n ${this.recommendationsHtml}\r\n
\r\n
\r\n ${this.skipButton.getHtml()}\r\n ${this.getBrochureButtonBasic.getHtml()}\r\n
\r\n
\r\n
\r\n ${recommendedPolicyParagraph.replace(\"{0}\", \"I'm Interested\")}\r\n
`;\r\n }\r\n}","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport { closeModalSvg, thanksContentSvg } from '../constants/svgIcons';\r\nimport DetailsAnchor from './detailsAnchor';\r\n\r\nexport default class ThankScreenAskQuestion {\r\n constructor() {\r\n const state = store.getState();\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const listingInformation = modalInformation?.listingInformation;\r\n this.url = modalInformation?.url;\r\n this.builderName = listingInformation?.brandName ?? 'the builder';\r\n this.marketId = listingInformation?.marketId;\r\n this.closeAttribute = '[data-close]';\r\n this.moreDetailsAnchor = new DetailsAnchor();\r\n this.moreDetailsAnchor.setUrl(this.url);\r\n this.moreDetailsAnchor.setListingId(listingInformation.id);\r\n this.moreDetailsAnchor.setListingType(listingInformation.type);\r\n }\r\n\r\n emitMoreDetailsClickEvent() {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url);\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n }\r\n\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenAskQuestion.closeModal));\r\n\r\n const detailsLink = this.moreDetailsAnchor.getAnchor();\r\n // if the anchor element contains any events, bind them here.\r\n this.moreDetailsAnchor.bindEvents();\r\n detailsLink.addEventListener('click', this.emitMoreDetailsClickEvent.bind(this));\r\n }\r\n\r\n unbindEvents() {\r\n const detailsLink = this.moreDetailsAnchor.getAnchor();\r\n detailsLink.removeEventListener('click', this.emitMoreDetailsClickEvent);\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thanksContentSvg}\r\n

Thank You!

\r\n

${this.builderName} will reach out to you soon with an answer.

\r\n
\r\n
\r\n \r\n ${this.moreDetailsAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport modalService from 'layout/services/modalService';\r\nimport { closeModalSvg, thankYouEmail, thankYouPhone, thankYouSuccess } from '../constants/svgIcons';\r\n\r\nexport default class ThankScreenBasic {\r\n constructor() {\r\n const state = store.getState();\r\n this.url = state?.uiState?.modalInformation?.url;\r\n this.builderName = state?.uiState?.modalInformation?.listingInformation?.brandName ?? 'the builder';\r\n this.closeAttribute = '[data-close]';\r\n this.thankYouSuccess = thankYouSuccess;\r\n this.closeModalSvg = closeModalSvg;\r\n }\r\n\r\n /**\r\n * Sets the internal browsing anchor for the ThankScreenBasic component.\r\n * @param {object} anchor - The anchor to be set (CreateAccountAnchor or ReturnToSearchAnchor).\r\n */\r\n setInternalBrowsingAnchor(anchor) {\r\n this.internalBrowsingAnchor = anchor;\r\n }\r\n\r\n /**\r\n * Binds events to the ThankScreenBasic component.\r\n * @function bindEvents\r\n * @memberof ThankScreenBasic\r\n * @instance\r\n */\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenBasic.closeModal));\r\n\r\n this.internalBrowsingAnchor?.bindEvents?.();\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thankYouSuccess}\r\n

Way to Go!

\r\n

\r\n An agent will be in contact soon!\r\n

\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n ${this.internalBrowsingAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport { closeModalSvg,\r\n thankYouEmail,\r\n thankYouHeart,\r\n thankYouPhone,\r\n thankYouSuccess \r\n} from '../constants/svgIcons';\r\n\r\nexport default class ThankScreenBrochure {\r\n constructor() {\r\n const state = store.getState();\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const listingInformation = modalInformation?.listingInformation;\r\n\r\n this.url = modalInformation?.url;\r\n this.schedulerUrl = listingInformation?.schedulerUrl;\r\n this.hasCallTracking = listingInformation?.hasCallTracking === \"True\";\r\n this.phoneNumber = listingInformation?.phoneNumber;\r\n this.builderName = listingInformation?.brandName ?? 'the builder';\r\n this.marketId = listingInformation?.marketId;\r\n this.closeAttribute = '[data-close]';\r\n this.closeBtnId = 'closeBtn';\r\n }\r\n\r\n emitMoreDetailsClickEvent() {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url);\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n }\r\n\r\n /**\r\n * Sets the contact builder anchor for the ThankScreenBrochure component.\r\n * @param {object} anchor - The anchor to be set (SchedulerAnchor, PhoneAnchorCallTracking or PhoneAnchor).\r\n */\r\n setContactBuilderAnchor(anchor) {\r\n this.contactBuilderAnchor = anchor;\r\n }\r\n\r\n /**\r\n * Sets the internal browsing anchor for the ThankScreenBrochure component.\r\n * @param {object} anchor - The anchor to be set (CreateAccountAnchor or ReturnToSearchAnchor).\r\n */\r\n setInternalBrowsingAnchor(anchor) {\r\n this.internalBrowsingAnchor = anchor;\r\n }\r\n\r\n /**\r\n * Binds events to the ThankScreenBrochure component.\r\n * @function bindEvents\r\n * @memberof ThankScreenBrochure\r\n * @instance\r\n */\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenBrochure.closeModal));\r\n\r\n // if the anchor element contains any events, bind them here.\r\n this.contactBuilderAnchor?.bindEvents?.()\r\n\r\n const detailsLink = this.contactBuilderAnchor?.getAnchor?.();\r\n detailsLink?.addEventListener('click', this.emitMoreDetailsClickEvent.bind(this));\r\n\r\n const closeBtn = this.getCloseBtn();\r\n closeBtn?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('closeAnchorClick')));\r\n\r\n this.internalBrowsingAnchor?.bindEvents?.();\r\n }\r\n\r\n /**\r\n * Removes event listeners from the anchor element.\r\n * @function\r\n */\r\n unbindEvents() {\r\n const detailsLink = this.contactBuilderAnchor?.getAnchor?.();\r\n detailsLink?.removeEventListener('click', this.emitMoreDetailsClickEvent);\r\n }\r\n\r\n /**\r\n * Closes the modal by clearing its HTML content.\r\n */\r\n static closeModal() {\r\n modalService?.clearHtml();\r\n }\r\n\r\n /**\r\n * Gets the close button element by ID.\r\n * @returns {HTMLElement} The button element.\r\n */\r\n getCloseBtn() {\r\n return document.getElementById(this.closeBtnId);\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thankYouSuccess}\r\n

Way to Go!

\r\n

\r\n You're connected with ${this.builderName}.
\r\n The best way to find out more is to visit the community yourself!\r\n

\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n ${this.internalBrowsingAnchor.getHtml()}\r\n ${this.contactBuilderAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport { closeModalSvg, \r\n thankYouEmail,\r\n thankYouHeart,\r\n thankYouPhone,\r\n thankYouSuccess \r\n } from '../constants/svgIcons';\r\n\r\nexport default class ThankScreenComingSoon {\r\n constructor() {\r\n const state = store.getState();\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const listingInformation = modalInformation?.listingInformation;\r\n\r\n this.url = modalInformation?.url;\r\n this.schedulerUrl = listingInformation?.schedulerUrl;\r\n this.hasCallTracking = listingInformation?.hasCallTracking === \"True\";\r\n this.phoneNumber = listingInformation?.phoneNumber;\r\n this.builderName = listingInformation?.brandName ?? 'the builder';\r\n this.marketId = listingInformation?.marketId;\r\n this.closeAttribute = '[data-close]';\r\n this.closeBtnId = 'closeBtn';\r\n }\r\n\r\n emitMoreDetailsClickEvent() {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url);\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n }\r\n\r\n /**\r\n * Sets the contact builder anchor for the ThankScreenBrochure component.\r\n * @param {object} anchor - The anchor to be set (SchedulerAnchor, PhoneAnchorCallTracking or PhoneAnchor).\r\n */\r\n setContactBuilderAnchor(anchor) {\r\n this.contactBuilderAnchor = anchor;\r\n }\r\n\r\n /**\r\n * Sets the internal browsing anchor for the ThankScreenBrochure component.\r\n * @param {object} anchor - The anchor to be set (CreateAccountAnchor or ReturnToSearchAnchor).\r\n */\r\n setInternalBrowsingAnchor(anchor) {\r\n this.internalBrowsingAnchor = anchor;\r\n }\r\n\r\n /**\r\n * Binds events to the ThankScreenBrochure component.\r\n * @function bindEvents\r\n * @memberof ThankScreenBrochure\r\n * @instance\r\n */\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenComingSoon.closeModal));\r\n\r\n // if the anchor element contains any events, bind them here.\r\n this.contactBuilderAnchor?.bindEvents?.()\r\n\r\n const detailsLink = this.contactBuilderAnchor?.getAnchor?.();\r\n detailsLink?.addEventListener('click', this.emitMoreDetailsClickEvent.bind(this));\r\n\r\n const closeBtn = this.getCloseBtn();\r\n closeBtn?.addEventListener('click', ()=> document.body.dispatchEvent(new CustomEvent('closeAnchorClick')));\r\n\r\n this.internalBrowsingAnchor?.bindEvents?.();\r\n }\r\n\r\n /**\r\n * Removes event listeners from the anchor element.\r\n * @function\r\n */\r\n unbindEvents() {\r\n const detailsLink = this.contactBuilderAnchor.getAnchor();\r\n detailsLink?.removeEventListener('click', this.emitMoreDetailsClickEvent);\r\n }\r\n\r\n /**\r\n * Closes the modal by clearing its HTML content.\r\n */\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n /**\r\n * Gets the close button element by ID.\r\n * @returns {HTMLElement} The button element.\r\n */\r\n getCloseBtn() {\r\n return document.getElementById(this.closeBtnId);\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thankYouSuccess}\r\n

Way to Go!

\r\n

\r\n You're connected with ${this.builderName}.
\r\n The best way to find out more is to visit the community yourself!\r\n

\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n ${this.internalBrowsingAnchor.getHtml()}\r\n ${this.contactBuilderAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport modalService from 'layout/services/modalService';\r\nimport DetailsAnchor from './detailsAnchor';\r\nimport { closeModalSvg, thanksContentSvg } from '../constants/svgIcons';\r\n\r\nexport default class ThankScreenLimitedAvailability {\r\n constructor() {\r\n const state = store.getState();\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const listingInformation = modalInformation?.listingInformation;\r\n this.url = modalInformation?.url;\r\n this.builderName = listingInformation?.brandName ?? 'the builder';\r\n this.closeAttribute = '[data-close]';\r\n this.moreDetailsAnchor = new DetailsAnchor();\r\n this.moreDetailsAnchor.setUrl(this.url);\r\n this.moreDetailsAnchor.setListingId(listingInformation.id);\r\n this.moreDetailsAnchor.setListingType(listingInformation.type);\r\n }\r\n\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenLimitedAvailability.closeModal));\r\n this.moreDetailsAnchor.bindEvents();\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thanksContentSvg}\r\n

Thank You!

\r\n

${this.builderName} will reach out to you soon with more information!.

\r\n
\r\n
\r\n \r\n ${this.moreDetailsAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}\r\n","import { store } from '@redux/store';\r\nimport modalService from 'layout/services/modalService';\r\nimport DetailsAnchor from './detailsAnchor';\r\nimport { closeModalSvg, thanksContentSvg } from '../constants/svgIcons';\r\n\r\nexport default class ThankScreenTour {\r\n constructor() {\r\n const state = store.getState();\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const listingInformation = modalInformation?.listingInformation;\r\n this.url = modalInformation?.url;\r\n this.builderName = listingInformation?.brandName ?? 'the builder';\r\n this.closeAttribute = '[data-close]';\r\n this.moreDetailsAnchor = new DetailsAnchor();\r\n this.moreDetailsAnchor.setUrl(this.url);\r\n this.moreDetailsAnchor.setListingId(listingInformation.id);\r\n this.moreDetailsAnchor.setListingType(listingInformation.type);\r\n }\r\n\r\n bindEvents() {\r\n const closeElements = document.querySelectorAll(this.closeAttribute);\r\n closeElements.forEach((element) => element.addEventListener('click', ThankScreenTour.closeModal));\r\n this.moreDetailsAnchor.bindEvents();\r\n }\r\n\r\n static closeModal() {\r\n modalService.clearHtml();\r\n }\r\n\r\n getHtml() {\r\n return `\r\n
\r\n \r\n
\r\n ${thanksContentSvg}\r\n

Thank You!

\r\n

Your request has been sent to ${this.builderName}.

\r\n

They will be in touch with you soon with more information!

\r\n
\r\n
\r\n \r\n ${this.moreDetailsAnchor.getHtml()}\r\n
\r\n
`;\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { selectIsLoggedIn } from 'features/userProfile';\r\nimport messageService from 'layout/services/messageService';\r\nimport modalService from 'layout/services/modalService';\r\nimport { distinctUntilChanged, distinctUntilKeyChanged, filter, map } from 'rxjs';\r\nimport ThankScreenVariation from '../../searchResultsFacets/enums/thankScreenVariation';\r\nimport { getContactBuilderAnchor, getInternalBrowsingAnchor } from '../services/anchorConstructor';\r\nimport createLeadGenerator from '../services/leadGeneratorConstructor';\r\nimport { initialState, updateModalProgress } from '../services/taskFlow';\r\nimport RecommendedScreen from './recommendedScreen';\r\nimport RecommendedScreenBasic from './recommendedScreenBasic';\r\nimport ThankScreenAskQuestion from './thankScreenAskQuestion';\r\nimport ThankScreenBasic from './thankScreenBasic';\r\nimport ThankScreenBrochure from './thankScreenBrochure';\r\nimport ThankScreenComingSoon from './thankScreenComingSoon';\r\nimport ThankScreenLimitedAvailability from './thankScreenLimitedAvailability';\r\nimport ThankScreenTour from './thankScreenTour';\r\n\r\nconst message$ = messageService.getMessage();\r\nconst isThankYouScreen = (state) => state?.uiState?.modalInformation?.name === 'thankYouScreen';\r\nconst isRecommendationsScreen = (state) => state?.uiState?.modalInformation?.name === 'recommendedScreen';\r\nconst isRecommendationsScreenBasic = (state) => state?.uiState?.modalInformation?.name === 'recommendedScreenBasic';\r\nconst hasFinishedLoading = (state) => !state?.uiState?.isFetchingModal;\r\nconst leadGeneratorInstance = {\r\n generator: null,\r\n state: null,\r\n};\r\nconst recommendationsInstance = {\r\n generator: null,\r\n};\r\n\r\n/**\r\n * Returns a Free Brochure Thank You screen.\r\n *\r\n * @param {Object} modalInformation - Information about the modal.\r\n * @returns {ThankScreenBrochure} - The Thank You screen for a free brochure request.\r\n */\r\nfunction getFreeBrochureThankYouScreen(modalInformation, isLoggedIn) {\r\n const brochureThankYouScreen = new ThankScreenBrochure(modalInformation);\r\n const contactBuilderAnchor = getContactBuilderAnchor(modalInformation);\r\n const internalBrowsingAnchor = getInternalBrowsingAnchor(isLoggedIn);\r\n brochureThankYouScreen.setContactBuilderAnchor(contactBuilderAnchor);\r\n brochureThankYouScreen.setInternalBrowsingAnchor(internalBrowsingAnchor);\r\n\r\n return brochureThankYouScreen;\r\n}\r\n\r\n/**\r\n * Returns a Coming Soon Thank You screen.\r\n *\r\n * @param {Object} modalInformation - Information about the modal.\r\n * @returns {ThankScreenBrochure} - The Thank You screen for a coming soon brochure request.\r\n */\r\nfunction getComingSoonThankYouScreen(modalInformation, isLoggedIn) {\r\n const comingSoonThankYouScreen = new ThankScreenComingSoon(modalInformation);\r\n const contactBuilderAnchor = getContactBuilderAnchor(modalInformation);\r\n const internalBrowsingAnchor = getInternalBrowsingAnchor(isLoggedIn);\r\n comingSoonThankYouScreen.setContactBuilderAnchor(contactBuilderAnchor);\r\n comingSoonThankYouScreen.setInternalBrowsingAnchor(internalBrowsingAnchor);\r\n\r\n return comingSoonThankYouScreen;\r\n}\r\n\r\n/**\r\n * Returns a Thank You Basic screen.\r\n *\r\n * @param {Object} modalInformation - Information about the modal.\r\n * @returns {ThankScreenBasic} - The Thank You Basic screen.\r\n */\r\nfunction getThankScreenBasicScreen(modalInformation, isLoggedIn) {\r\n const thankYouScreenBasic = new ThankScreenBasic(modalInformation);\r\n const internalBrowsingAnchor = getInternalBrowsingAnchor(isLoggedIn);\r\n thankYouScreenBasic.setInternalBrowsingAnchor(internalBrowsingAnchor);\r\n\r\n return thankYouScreenBasic;\r\n}\r\n\r\n/**\r\n * Decides which variation of the thank you screen to show and returns an instance of it.\r\n */\r\nconst getThankYouScreen = () => {\r\n const state = store.getState();\r\n const screenVariation = state?.uiState?.modalInformation?.variation;\r\n const modalInformation = state?.uiState?.modalInformation;\r\n const isLoggedIn = selectIsLoggedIn(state);\r\n\r\n switch (screenVariation) {\r\n case ThankScreenVariation.ComingSoon.toString():\r\n return getComingSoonThankYouScreen(modalInformation, isLoggedIn);\r\n case ThankScreenVariation.AskQuestion.toString():\r\n return new ThankScreenAskQuestion();\r\n case ThankScreenVariation.Brochure.toString():\r\n return getFreeBrochureThankYouScreen(modalInformation, isLoggedIn);\r\n case ThankScreenVariation.Tour.toString():\r\n return new ThankScreenTour(modalInformation);\r\n case ThankScreenVariation.LimitedAvailability.toString():\r\n return new ThankScreenLimitedAvailability(modalInformation);\r\n case ThankScreenVariation.Basic.toString():\r\n return getThankScreenBasicScreen(modalInformation, isLoggedIn);\r\n default:\r\n // if no version is provided, we default to the free brochure one.\r\n return getFreeBrochureThankYouScreen(modalInformation, isLoggedIn);\r\n }\r\n};\r\n\r\n/**\r\n * This function takes the user to a \"thank you screen\". This screen is different\r\n * depending on which flow the user is following, so we receive an argument indicating\r\n * the name of the thank you screen to show.\r\n * @param {string} thankYouScreen is the name of the thank you screen to show.\r\n */\r\nconst showThankYouScreen = () => {\r\n const screen = getThankYouScreen();\r\n\r\n modalService.onHtmlRemoved({\r\n name: 'thankYouScreen',\r\n fn: screen.unbindEvents?.bind(screen),\r\n });\r\n\r\n modalService.onHtmlReady({\r\n name: 'thankYouScreen',\r\n fn: screen.bindEvents.bind(screen),\r\n });\r\n\r\n modalService.setHtml({ payload: screen.getHtml() });\r\n}\r\n\r\nconst showRecommendationsScreen = (data) => {\r\n recommendationsInstance.generator = new RecommendedScreen(data?.uiState?.modalInformation?.html);\r\n\r\n modalService.onHtmlReady({\r\n name: 'recommendedScreen',\r\n fn: recommendationsInstance.generator.bindEvents.bind(recommendationsInstance.generator),\r\n });\r\n\r\n modalService.onHtmlRemoved({\r\n name: 'recommendedScreen',\r\n fn: recommendationsInstance.generator.unbindEvents.bind(recommendationsInstance.generator),\r\n });\r\n\r\n modalService.setHtml({ payload: recommendationsInstance.generator.getHtml() });\r\n}\r\n\r\nconst showRecommendationsScreenBasic = (data) => {\r\n recommendationsInstance.generator = new RecommendedScreenBasic(data?.uiState?.modalInformation?.html);\r\n\r\n modalService.onHtmlReady({\r\n name: 'recommendedScreenBasic',\r\n fn: recommendationsInstance.generator.bindEvents.bind(recommendationsInstance.generator),\r\n });\r\n\r\n modalService.onHtmlRemoved({\r\n name: 'recommendedScreenBasic',\r\n fn: recommendationsInstance.generator.unbindEvents.bind(recommendationsInstance.generator),\r\n });\r\n\r\n modalService.setHtml({ payload: recommendationsInstance.generator.getHtml() });\r\n}\r\n\r\ndocument.body.addEventListener('click', (event) => {\r\n const leadGeneratorOpener = event.target.closest('[data-lead-generator-opener]');\r\n const properties = { ...leadGeneratorOpener?.dataset };\r\n const openerKey = properties?.leadGeneratorOpener;\r\n const leadGenerator = createLeadGenerator(openerKey, properties);\r\n\r\n if (!leadGenerator) {\r\n return false;\r\n }\r\n\r\n const cardContainer = event.target.closest('[data-card]');\r\n const listingInformation = cardContainer?.dataset;\r\n // Here we are checking all the values from the data set, and we are going to use the ones that are not empty. \r\n const validListingInformation =\r\n Object.fromEntries(Object.entries(listingInformation).filter(([, value]) => Boolean(value)))\r\n properties.listingInformation = validListingInformation;\r\n const getGoogleAnalyticsEventCallback = leadGenerator.constructor.getFormOpenedAnalyticsData;\r\n leadGenerator.excludeRecommendations = properties?.excludeRecommendations === \"true\";\r\n const contactVendorName = properties?.listingInformation?.contactVendorName ?? '';\r\n leadGenerator.setPrivacyPolicyText?.(properties?.phoneNumber, contactVendorName);\r\n leadGenerator.setHousingData?.(properties);\r\n leadGeneratorInstance.state = initialState(properties, getGoogleAnalyticsEventCallback);\r\n leadGeneratorInstance.generator = leadGenerator;\r\n\r\n modalService.onHtmlReady({\r\n name: 'leadGenerator',\r\n fn: leadGeneratorInstance.generator.bindEvents.bind(leadGeneratorInstance.generator),\r\n });\r\n\r\n modalService.onHtmlRemoved({\r\n name: 'leadGenerator',\r\n fn: leadGeneratorInstance.generator.unbindEvents.bind(leadGeneratorInstance.generator),\r\n });\r\n\r\n modalService.setHtml({ payload: leadGeneratorInstance.generator.getHtml() });\r\n return true;\r\n});\r\n\r\ndocument.body.addEventListener('click', (event) => {\r\n const backButton = event.target.closest('.modal__back');\r\n const closeButton = event.target.closest('#nhs_modalClose');\r\n const overlayElement = event.target.closest('#overlayElement');\r\n\r\n if (backButton && leadGeneratorInstance.state) {\r\n updateModalProgress(leadGeneratorInstance.state);\r\n modalService.setPreviousHtml();\r\n return;\r\n }\r\n\r\n if ((closeButton || overlayElement) && leadGeneratorInstance.state) {\r\n modalService.clearHtml();\r\n }\r\n});\r\n\r\nstore$.pipe(\r\n map(isThankYouScreen),\r\n distinctUntilChanged(),\r\n filter(Boolean))\r\n .subscribe(showThankYouScreen);\r\n\r\nstore$.pipe(\r\n filter(isRecommendationsScreen),\r\n filter(hasFinishedLoading),\r\n distinctUntilKeyChanged('uiState'))\r\n .subscribe(showRecommendationsScreen);\r\n\r\nstore$.pipe(\r\n filter(isRecommendationsScreenBasic),\r\n filter(hasFinishedLoading),\r\n distinctUntilKeyChanged('uiState'))\r\n .subscribe(showRecommendationsScreenBasic);\r\n\r\nmessage$.pipe(\r\n filter((msg) => msg.messageType === 'leadPosted'),\r\n filter((msg) => msg.payload.html !== ''),\r\n filter((message) => !message.isBasic),\r\n map((data) => data.payload))\r\n .subscribe((data) => {\r\n const modalInformation = {\r\n name: 'recommendedScreen',\r\n html: data.html\r\n };\r\n\r\n updateModalProgress(modalInformation);\r\n });\r\n\r\nmessage$.pipe(\r\n filter((msg) => msg.messageType === 'leadPosted'),\r\n filter((msg) => msg.payload.html !== ''),\r\n filter((message) => message.isBasic),\r\n map((data) => data.payload))\r\n .subscribe((data) => {\r\n const modalInformation = {\r\n name: 'recommendedScreenBasic',\r\n html: data.html\r\n };\r\n\r\n updateModalProgress(modalInformation);\r\n });\r\n\r\nmessage$.pipe(\r\n filter((msg) => msg.messageType === 'leadPosted'),\r\n filter((msg) => msg.payload.html === ''))\r\n .subscribe(() => {\r\n const modalInformation = {\r\n name: 'thankYouScreen',\r\n };\r\n\r\n updateModalProgress(modalInformation);\r\n });","export default class LeadFormType {\r\n static get BrochureFormPaid() {\r\n return this.getInstance('get-brochure-paid');\r\n }\r\n\r\n static get InformationFormPaid() {\r\n return this.getInstance('more-information-paid');\r\n }\r\n\r\n static get RequestTourForm() {\r\n return this.getInstance('request-a-tour');\r\n }\r\n\r\n static get BrochureFormLimitedAvailability() {\r\n return this.getInstance('get-information-limited-availability');\r\n }\r\n\r\n static get InformationFormBasic() {\r\n return this.getInstance('get-information-basic');\r\n }\r\n\r\n static get AskQuestionFormPaid() {\r\n return this.getInstance('ask-question-paid');\r\n }\r\n\r\n static get ManufacturedBrochureFormPaid() {\r\n return this.getInstance('get-manufactured-brochure-paid');\r\n }\r\n\r\n static fromKey(key) {\r\n const formTypeMap = {\r\n 'get-brochure-paid': LeadFormType.BrochureFormPaid,\r\n 'more-information-paid': LeadFormType.InformationFormPaid,\r\n 'request-a-tour': LeadFormType.RequestTourForm,\r\n 'get-information-limited-availability': LeadFormType.BrochureFormLimitedAvailability,\r\n 'get-information-basic': LeadFormType.InformationFormBasic,\r\n 'ask-question-paid': LeadFormType.AskQuestionFormPaid,\r\n 'get-manufactured-brochure-paid': LeadFormType.ManufacturedBrochureFormPaid,\r\n };\r\n return formTypeMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new LeadFormType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(LeadFormType, 'instances', { value: {} });\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { leadsRecommendedCommunitySubmission, leadsGetRecommendedCommunities } from 'constants/routes';\r\n\r\nexport const postRecommendedCommunities = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n ...payload,\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsRecommendedCommunitySubmission, requestObject);\r\n};\r\n\r\nexport const getRecommendedCommunities$ = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n return fromFetch(leadsGetRecommendedCommunities, requestObject);\r\n};\r\n","import { leadsPaidCommunitySubmission, leadsPaidPlanSubmission, leadsPaidSpecSubmission } from 'constants/routes';\r\n\r\nexport const postBuildablePlanBrochure$ = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsPaidCommunitySubmission, requestObject);\r\n};\r\n\r\nexport const postCommunityBrochure = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsPaidCommunitySubmission, requestObject);\r\n};\r\n\r\nexport const postPlanBrochure = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsPaidPlanSubmission, requestObject);\r\n};\r\n\r\nexport const postSpecBrochure = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsPaidSpecSubmission, requestObject);\r\n};\r\n","import { catchError, distinctUntilChanged, filter, of, switchMap, tap } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport messageService from 'layout/services/messageService';\r\nimport { postRecommendedCommunities, getRecommendedCommunities$ } from '../apis/recommendedCommunities';\r\nimport { postCommunityBrochure, postPlanBrochure, postSpecBrochure } from '../apis/postBrochure';\r\nimport {\r\n postPlanBrochureBasic,\r\n postSpecBrochureBasic,\r\n postCommunityBrochureBasic,\r\n postBasicListingBrochureBasic\r\n} from '../apis/postBrochureBasic';\r\n\r\nconst actions = uiStateSlice.actions;\r\n\r\nexport const postBuildablePlanBrochureEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postBuildeablePlanBrochure'),\r\n tap((action) => postCommunityBrochure(action.payload.parameters)),\r\n switchMap(() => of(actions.fetchModalFulfilled()))\r\n );\r\n\r\nexport const postCommunityBrochureEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postCommunityBrochure'),\r\n tap((action) => postCommunityBrochure(action.payload.parameters)),\r\n switchMap(() => of(actions.fetchModalFulfilled()))\r\n );\r\n\r\nexport const postPlanBrochureEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postPlanBrochure'),\r\n tap((action) => postPlanBrochure(action.payload.parameters)),\r\n switchMap(() => of(actions.fetchModalFulfilled()))\r\n );\r\n\r\nexport const postSpecBrochureEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postSpecBrochure'),\r\n tap((action) => postSpecBrochure(action.payload.parameters)),\r\n switchMap(() => of(actions.fetchModalFulfilled()))\r\n );\r\n\r\nexport const postRecommendedBrochureEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postRecommendedBrochure'),\r\n distinctUntilChanged(),\r\n tap((action) => postRecommendedCommunities(action.payload.parameters)),\r\n switchMap(() => of(actions.fetchModalFulfilled()))\r\n );\r\n\r\nexport const getRecommendedBrochureEpicPaid = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postSpecBrochure' ||\r\n action.payload.parameters.type === 'postPlanBrochure' ||\r\n action.payload.parameters.type === 'postCommunityBrochure' ||\r\n action.payload.parameters.type === 'postBuildeablePlanBrochure'),\r\n switchMap((action) => {\r\n if (action.payload.parameters.excludeRecommendations) {\r\n messageService.sendMessage({\r\n messageType: 'leadPosted', payload: {\r\n html: '',\r\n }\r\n });\r\n\r\n return of(actions.fetchModalFulfilled());\r\n }\r\n\r\n return getRecommendedCommunities$(action.payload.parameters).pipe(\r\n switchMap((data) => {\r\n messageService.sendMessage({\r\n messageType: 'leadPosted', isBasic: false, payload: {\r\n html: data,\r\n }\r\n });\r\n\r\n return of(actions.fetchModalFulfilled());\r\n }),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n );\r\n }),\r\n );\r\n\r\n\r\nexport const getRecommendedBrochureEpicBasic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postSpecBrochureBasic' ||\r\n action.payload.parameters.type === 'postPlanBrochureBasic' ||\r\n action.payload.parameters.type === 'postCommunityBrochureBasic' ||\r\n action.payload.parameters.type === 'postBasicListingBrochureBasic'),\r\n switchMap((action) => {\r\n if (action.payload.parameters.excludeRecommendations) {\r\n messageService.sendMessage({\r\n messageType: 'leadPosted', payload: {\r\n html: '',\r\n }\r\n });\r\n\r\n return of(actions.fetchModalFulfilled());\r\n }\r\n\r\n return getRecommendedCommunities$(action.payload.parameters).pipe(\r\n switchMap((data) => {\r\n messageService.sendMessage({\r\n messageType: 'leadPosted', isBasic: true, payload: {\r\n html: data,\r\n }\r\n });\r\n\r\n return of(actions.fetchModalFulfilled());\r\n }),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n );\r\n }),\r\n );\r\n\r\nexport const postSpecBrochureBasicEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postSpecBrochureBasic'),\r\n tap((action) => postSpecBrochureBasic(action.payload.parameters)),\r\n switchMap((action) => of(actions.fetchModalFulfilled(action)))\r\n );\r\n\r\nexport const postPlanBrochureBasicEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postPlanBrochureBasic'),\r\n tap((action) => postPlanBrochureBasic(action.payload.parameters)),\r\n switchMap((action) => of(actions.fetchModalFulfilled(action)))\r\n );\r\n\r\nexport const postCommunityBrochureBasicEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postCommunityBrochureBasic'),\r\n tap((action) => postCommunityBrochureBasic(action.payload.parameters)),\r\n switchMap((action) => of(actions.fetchModalFulfilled(action)))\r\n );\r\n\r\nexport const postBasicLisitingBrochureBasicEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'postBasicListingBrochureBasic'),\r\n tap((action) => postBasicListingBrochureBasic(action.payload.parameters)),\r\n switchMap((action) => of(actions.fetchModalFulfilled(action)))\r\n );","import { epic$ } from '@redux/store';\r\nimport {\r\n postBuildablePlanBrochureEpic,\r\n postCommunityBrochureEpic,\r\n postPlanBrochureEpic,\r\n postSpecBrochureEpic,\r\n postRecommendedBrochureEpic,\r\n getRecommendedBrochureEpicPaid,\r\n getRecommendedBrochureEpicBasic,\r\n postSpecBrochureBasicEpic,\r\n postPlanBrochureBasicEpic,\r\n postCommunityBrochureBasicEpic,\r\n postBasicLisitingBrochureBasicEpic\r\n} from './redux/epics';\r\nimport LeadFormType from './enums/leadFormType';\r\n\r\nepic$.next(postBuildablePlanBrochureEpic);\r\nepic$.next(postCommunityBrochureEpic);\r\nepic$.next(postPlanBrochureEpic);\r\nepic$.next(postSpecBrochureEpic);\r\nepic$.next(postRecommendedBrochureEpic);\r\nepic$.next(getRecommendedBrochureEpicPaid);\r\nepic$.next(getRecommendedBrochureEpicBasic);\r\nepic$.next(postSpecBrochureBasicEpic);\r\nepic$.next(postPlanBrochureBasicEpic);\r\nepic$.next(postCommunityBrochureBasicEpic);\r\nepic$.next(postBasicLisitingBrochureBasicEpic);\r\n\r\nrequire('./components/wrapper');\r\n\r\nexport default LeadFormType;","import { \r\n leadsBasicCommunitySubmission, \r\n leadsBasicPlanSubmission, \r\n leadsBasicSpecSubmission, \r\n leadsBasicListingSubmission \r\n} from 'constants/routes';\r\n\r\nexport const postSpecBrochureBasic = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsBasicSpecSubmission, requestObject);\r\n};\r\n\r\nexport const postPlanBrochureBasic = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsBasicPlanSubmission, requestObject);\r\n};\r\n\r\nexport const postCommunityBrochureBasic = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsBasicCommunitySubmission, requestObject);\r\n};\r\n\r\nexport const postBasicListingBrochureBasic = (payload) => {\r\n const requestObject = {\r\n 'credentials': 'include',\r\n method: 'POST',\r\n body: JSON.stringify({\r\n leadCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n selector: (response) => response.text(),\r\n };\r\n\r\n fetch(leadsBasicListingSubmission, requestObject);\r\n};\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { getBreadcrumbContent } from 'constants/routes'\r\n\r\nfunction getBreadcrumbContentRequest$(searchParameters) {\r\nconst requestObject = {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...searchParameters,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n selector: (response) => response.json(),\r\n };\r\n return fromFetch(getBreadcrumbContent, requestObject);\r\n}\r\n\r\nexport default getBreadcrumbContentRequest$;\r\n","import getBreadcrumbContentRequest$ from 'api/getBreadcrumbContent';\r\nimport { store$ } from '@redux/store';\r\nimport { filter, map, distinctUntilChanged, switchMap, catchError, of, shareReplay } from 'rxjs';\r\nimport { searchParametersSelectors, selectResultType } from 'features/searchResultsFacets';\r\nimport objectEquals from 'utils/equals';\r\n\r\nconst { selectLocation, selectProductType } = searchParametersSelectors;\r\nconst breadcrumbListContainer = document.querySelector('[data-breadcrumb-list]');\r\nconst breadcrumbJsonLdMarkupContainer = document.querySelector('[data-breadcrumb-json-ld-markup]');\r\n\r\n/**\r\n * isSameLocation: Checks if the search location has been changed or not.\r\n * @param {Object} previousState Previous store.\r\n * @param {Object} currentState Current store.\r\n * @returns A boolean value related to if the current search has the same location than before.\r\n */\r\nfunction isSameLocation(previousState, currentState) {\r\n const previousLocation = selectLocation(previousState);\r\n const currentLocation = selectLocation(currentState);\r\n\r\n return objectEquals(previousLocation, currentLocation);\r\n}\r\n\r\n/**\r\n * isSameProductType: Checks if the search product type has been changed or not.\r\n * @param {Object} previousState Previous store.\r\n * @param {Object} currentState Current store.\r\n * @returns A boolean value related to if the current search has the same product type than before.\r\n */\r\nfunction isSameProductType(previousState, currentState) {\r\n const previousProductType = selectProductType(previousState);\r\n const currentProductType = selectProductType(currentState);\r\n\r\n return previousProductType === currentProductType;\r\n}\r\n\r\n/**\r\n * isSameResultType: Checks if the search result type has been changed or not.\r\n * @param {Object} previousState Previous store.\r\n * @param {Object} currentState Current store.\r\n * @returns A boolean value related to if the current search has the same result type than before.\r\n */\r\nfunction isSameResultType(previousState, currentState) {\r\n const previousResultType = selectResultType(previousState);\r\n const currentResultType = selectResultType(currentState);\r\n\r\n return previousResultType === currentResultType;\r\n}\r\n\r\n/**\r\n * isSameBreadcrumb: Checks if the search should change the breadcrumb or not.\r\n * @param {Object} previousState Previous store.\r\n * @param {Object} currentState Current store.\r\n * @returns A boolean value related to if the current search should have the same breadcrumb than before.\r\n */\r\nfunction isSameBreadcrumb(previousState, currentState) {\r\n return (\r\n isSameLocation(previousState, currentState) &&\r\n isSameProductType(previousState, currentState) &&\r\n isSameResultType(previousState, currentState)\r\n );\r\n}\r\n\r\nconst onLocationChange$ = store$.pipe(distinctUntilChanged(isSameBreadcrumb));\r\n\r\nconst onSeachWithinMap$ = onLocationChange$.pipe(filter((state) => state?.mapState?.isSearchWithinMap));\r\n\r\nonSeachWithinMap$.subscribe(() => {\r\n // We have to remove the breadcrumb when the Search Within Map is active.\r\n breadcrumbListContainer.innerHTML = '';\r\n});\r\n\r\nconst onBreadcrumbReady$ = onLocationChange$.pipe(\r\n filter((state) => !state?.mapState?.isSearchWithinMap),\r\n switchMap((state) => {\r\n const payload = {\r\n location: state?.searchParameters?.location,\r\n product: state?.searchParameters?.product,\r\n results: state?.searchParameters?.results,\r\n };\r\n return getBreadcrumbContentRequest$(payload).pipe(\r\n catchError(() => of(null)) // catch and ignore any errors\r\n );\r\n }),\r\n shareReplay(1)\r\n);\r\n\r\n/**\r\n * createRootBreadcrumb: Creates the content for the Root Breadcrumb.\r\n * The Root Breadcrumb relates to the parts from the breadcrumb section that can be navitated to.\r\n * For example, 'New Homes' Breadcrumb will always be a Root Breadcrumb and redirects to the homepage.\r\n * @param {Object} breadcrumb Breadcrumb information.\r\n * @returns The content for the Root breadcrumb.\r\n */\r\nfunction createRootBreadcrumb(breadcrumb) {\r\n const anchorElement = document.createElement('a');\r\n anchorElement.classList.add('nhs-c-breadcrumb__link');\r\n anchorElement.href = breadcrumb.Url;\r\n anchorElement.title = breadcrumb.Title;\r\n anchorElement.dataset.breadcrumbRoot = '';\r\n\r\n const spanElement = document.createElement('span');\r\n spanElement.classList.add('nhs-c-breadcrumb__text');\r\n spanElement.innerText = breadcrumb.Name;\r\n\r\n anchorElement.append(spanElement);\r\n return anchorElement;\r\n}\r\n\r\n/**\r\n * createBaseBreadcrumb: Creates the content for the Base Breadcrumb.\r\n * The Base Breadcrumb relates to the parts of the breadcrumb that cannot be navigated to.\r\n * For example, the last breadcrumb part will always be a Base breadcrumb because it does not redirect.\r\n * @param {Object} breadcrumb Breadcrumb information.\r\n * @returns The content for the Base breadcrumb.\r\n */\r\nfunction createBaseBreadcrumb(breadcrumb) {\r\n const spanElement = document.createElement('span');\r\n spanElement.classList.add('nhs-c-breadcrumb__text--active');\r\n spanElement.innerText = breadcrumb.Name;\r\n\r\n return spanElement;\r\n}\r\n\r\n/**\r\n * addBreadcrumbElement: Creates the correct Breadcrumb element with a breadcrumb information.\r\n * @param {Object} breadcrumb Breadcrumb information.\r\n */\r\nfunction createBreadcrumbElement(breadcrumb) {\r\n const liElement = document.createElement('li');\r\n liElement.classList.add('nhs-c-breadcrumb__item');\r\n const createNewBreadcrumbElement = breadcrumb.IsAnchorLink ? createRootBreadcrumb : createBaseBreadcrumb;\r\n const newBreadcrumbElement = createNewBreadcrumbElement(breadcrumb);\r\n liElement.append(newBreadcrumbElement);\r\n\r\n return liElement;\r\n}\r\n\r\n/**\r\n * updateBreadcrumbList: Updates a new entire breadcrumb list section.\r\n * @param {Array} breadcrumbList List of Breadcrumb parts.\r\n */\r\nfunction updateBreadcrumbList(breadcrumbList) {\r\n const currentBreadcrumbElements = breadcrumbListContainer.children;\r\n\r\n // We have to remove the extra breadcrumbs for the actual breadcrumb list.\r\n // For example, the city breadcrumb section has 4 segments and the market breadcrumb has 3 segments.\r\n // So when we move from city to market, we have to remove the extra last breadcrumb segment.\r\n const breadcrumbsToRemove = [...currentBreadcrumbElements].filter(\r\n (breadcrumb, index) => breadcrumbList.length <= index\r\n );\r\n breadcrumbsToRemove.forEach((breadcrumbElement) => breadcrumbElement.remove());\r\n\r\n breadcrumbList.forEach((breadcrumb, index) => {\r\n const newBreadcrumb = createBreadcrumbElement(breadcrumb);\r\n const samePositionBreadcrumb = currentBreadcrumbElements[index];\r\n const isSameBreadcrumbElement = samePositionBreadcrumb && samePositionBreadcrumb.isEqualNode(newBreadcrumb);\r\n\r\n // We only have to modify the breadcrumb segments that are not the same\r\n // to avoid doing changes on DOM that are not necessary.\r\n if (isSameBreadcrumbElement) {\r\n return;\r\n }\r\n\r\n // If there is a breadcrumb on the same position, we have to replace it with the new one to do not affect the order.\r\n // Otherwise, we only add the new one at the end.\r\n if (samePositionBreadcrumb) {\r\n samePositionBreadcrumb.replaceWith(newBreadcrumb);\r\n } else {\r\n breadcrumbListContainer.append(newBreadcrumb);\r\n }\r\n });\r\n}\r\n\r\nonBreadcrumbReady$\r\n .pipe(\r\n map((response) => response.BreadcrumbStack),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(updateBreadcrumbList);\r\n\r\n/**\r\n * updateJsonLdMarkup: Updates the new Json-Ld Markup section of the current breadcrumb.\r\n * @param {string} breadcrumbJsonLdMarkup Json-Ld Markup information for the current breadcrumb.\r\n */\r\nfunction updateJsonLdMarkup(breadcrumbJsonLdMarkup) {\r\n breadcrumbJsonLdMarkupContainer.innerHTML = breadcrumbJsonLdMarkup;\r\n}\r\n\r\nonBreadcrumbReady$\r\n .pipe(\r\n map((response) => response.BreadcrumbJsonLdMarkup),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(updateJsonLdMarkup);\r\n","import { store$, store } from '@redux/store';\r\nimport { combineLatest, debounceTime, distinctUntilChanged, filter, map, merge, skip, tap, withLatestFrom } from 'rxjs';\r\nimport {\r\n isNotCommunityLocationType,\r\n moveInDateSelector,\r\n selectFacts,\r\n selectFeatures,\r\n selectLocation,\r\n selectProduct,\r\n selectResults,\r\n selectResultsModifiers,\r\n} from 'features/searchResultsFacets';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { urlFilterSelector } from 'features/routing';\r\nimport { selectResultsPresentationType } from 'layout/redux/selectors';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport locationContentSlice from '../redux/slice';\r\nimport {\r\n selectCanonical,\r\n selectFetchStatus,\r\n selectFooter,\r\n selectHeading1,\r\n selectHeading2,\r\n selectMetaDescription,\r\n selectMetaRobots,\r\n selectTitle,\r\n} from '../redux/selectors';\r\n\r\nconst h1Element = document.querySelector('[data-heading1]');\r\nconst h2Element = document.querySelector('[data-heading2]');\r\nconst footer = document.querySelector('[data-footer-content]');\r\nconst readMoreButton = document.querySelector('[data-read-more]');\r\nconst metaRobotsElement = document.querySelector('meta[name=\"robots\"]');\r\n\r\nconst fetchLocationContent = () => store.dispatch(locationContentSlice.actions.fetch());\r\nconst isNotFetchingContent = (state) => selectFetchStatus(state) !== LoadingStatus.Loading;\r\n\r\nconst updateMetaRobots = (metaRobots) => {\r\n metaRobotsElement.setAttribute('content', metaRobots);\r\n};\r\n\r\n/**\r\n * Insert the heading 1 when the Ajax request is triggered.\r\n * @param {any} data\r\n */\r\nconst updateH1Text = (heading1) => {\r\n h1Element.innerText = heading1;\r\n};\r\n\r\n/**\r\n * Insert the heading 2 when the Ajax request is triggered.\r\n * @param {any} data\r\n */\r\nconst updateH2Text = (heading2) => {\r\n h2Element.innerText = heading2;\r\n};\r\n\r\n/**\r\n * Update the title when the Ajax request is triggered.\r\n * @param {*} data\r\n */\r\nconst updateTitle = (title) => {\r\n document.title = title;\r\n};\r\n\r\n/**\r\n * Function used to remove the canonical if the move-in date is applied.\r\n */\r\nconst removeCanonicalOnMoveInDateFilterApplied = () => {\r\n const state = store.getState();\r\n const { moveInDateRange } = moveInDateSelector(state);\r\n\r\n const canonical = document.querySelector('link[rel=\"canonical\"]');\r\n\r\n // NHS20-1365: If the move in date range is set, remove the canonical element\r\n if (moveInDateRange) {\r\n canonical?.remove();\r\n }\r\n};\r\n\r\n/**\r\n * Update the canonical when there already exist a tag element in the page.\r\n */\r\nconst updateCurrentCanonicalElement = (canonicalElement, canonicalUrl) => {\r\n canonicalElement.setAttribute('href', canonicalUrl);\r\n};\r\n\r\n/**\r\n * Creates the canonical tag when there is not a tag already in the page.\r\n */\r\nconst createCanonicalElement = (canonicalUrl) => {\r\n const newCanonicalElement = document.createElement('link');\r\n newCanonicalElement.setAttribute('rel', 'canonical');\r\n document.head.appendChild(newCanonicalElement);\r\n newCanonicalElement.setAttribute('href', canonicalUrl);\r\n};\r\n\r\n/**\r\n * Update the canonical when the Ajax request is triggered.\r\n */\r\nconst updateCanonical = (canonicalData) => {\r\n const canonical = document.querySelector('link[rel=\"canonical\"]');\r\n const canonicalUrl = canonicalData;\r\n\r\n // if the canonical element doesn't exist, create it\r\n if (canonical) {\r\n updateCurrentCanonicalElement(canonical, canonicalUrl);\r\n } else {\r\n createCanonicalElement(canonicalUrl);\r\n }\r\n};\r\n\r\n/**\r\n * Insert the Footer container and read more button when the Ajax request is triggered.\r\n * @param {any} data\r\n */\r\nfunction updateFooter(footerData) {\r\n footer.innerHTML = footerData;\r\n\r\n if (footer.innerText.length < 600) {\r\n readMoreButton.style.display = 'none';\r\n } else {\r\n readMoreButton.style.display = 'block';\r\n }\r\n}\r\n\r\nfunction updateMetaDescription(metaDescriptionData) {\r\n const metaDescription = document.querySelector('meta[name=\"description\"]');\r\n\r\n if (metaDescription) {\r\n metaDescription.setAttribute('content', metaDescriptionData);\r\n } else {\r\n const newMetaDescription = document.createElement('meta');\r\n newMetaDescription.setAttribute('name', 'description');\r\n document.head.appendChild(newMetaDescription);\r\n newMetaDescription.setAttribute('content', metaDescriptionData);\r\n }\r\n}\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in results leaf change, fetch the housing product locaction content.\r\n */\r\nconst results$ = store$.pipe(filter(isNotFetchingContent), map(selectResults), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in facts leaf change, fetch the housing product locaction content.\r\n */\r\nconst facts$ = store$.pipe(filter(isNotFetchingContent), map(selectFacts), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in features leaf change, fetch the housing product locaction content.\r\n */\r\nconst features$ = store$.pipe(filter(isNotFetchingContent), map(selectFeatures), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in location leaf change, fetch the housing product locaction content.\r\n */\r\nconst location$ = store$.pipe(\r\n filter(isNotFetchingContent),\r\n filter(isNotCommunityLocationType),\r\n map(selectLocation),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst presentationType$ = store$.pipe(map(selectResultsPresentationType), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in product leaf change, fetch the housing product locaction content.\r\n */\r\nconst product$ = store$.pipe(filter(isNotFetchingContent), map(selectProduct), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in results modifier leaf change, fetch the housing product locaction content.\r\n */\r\nconst resultsModifier$ = store$.pipe(filter(isNotFetchingContent), map(selectResultsModifiers), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When the URL filter change, fetch the housing product locaction content. We need to check if this URL filter change\r\n * beacuse the @HousingProductLocationContentCommand class is using this selector to send the data to the backend\r\n * and if it is updated it we have issues with the canonical.\r\n */\r\nconst onUrlFilterChange$ = store$.pipe(filter(isNotFetchingContent), map(urlFilterSelector), distinctUntilChanged());\r\n\r\ncombineLatest([results$, product$, location$, features$, resultsModifier$, facts$, onUrlFilterChange$])\r\n .pipe(debounceTime(100), skip(1),\r\n withLatestFrom(presentationType$),\r\n filter(([combinedValues, presentationType]) => {\r\n const [results] = combinedValues;\r\n \r\n const isInfiniteScrolling = presentationType === ResultPresentationType.InfiniteScrolling.toString();\r\n \r\n // If presentation type is InfiniteScrolling and page is greater than 1, we don't need to trigger the\r\n // ajax request since the location content was already retrieved for page 1 and won't change.\r\n return !(isInfiniteScrolling && results.paging.page > 1);\r\n })\r\n ).subscribe(fetchLocationContent);\r\n\r\n// We subscribe the methods to handle the html elements.\r\nconst setH1Text$ = store$.pipe(\r\n map(selectHeading1),\r\n distinctUntilChanged(),\r\n filter(() => !!h1Element),\r\n skip(1),\r\n tap(updateH1Text)\r\n);\r\n\r\nconst setH2Text$ = store$.pipe(\r\n map(selectHeading2),\r\n distinctUntilChanged(),\r\n filter(() => !!h2Element),\r\n skip(1),\r\n tap(updateH2Text)\r\n);\r\n\r\nconst setFooter$ = store$.pipe(\r\n map(selectFooter),\r\n distinctUntilChanged(),\r\n filter(() => !!footer && !!readMoreButton),\r\n skip(1),\r\n tap(updateFooter)\r\n);\r\n\r\nconst setTitle$ = store$.pipe(\r\n map(selectTitle),\r\n distinctUntilChanged(),\r\n filter(() => !!document.title),\r\n skip(1),\r\n tap(updateTitle)\r\n);\r\n\r\nconst setCanonical$ = store$.pipe(map(selectCanonical), distinctUntilChanged(), skip(1), tap(updateCanonical));\r\n\r\nconst setMetaRobots$ = store$.pipe(map(selectMetaRobots), distinctUntilChanged(), skip(1), tap(updateMetaRobots));\r\n\r\nconst setMetaDescription$ = store$.pipe(\r\n map(selectMetaDescription),\r\n distinctUntilChanged(),\r\n skip(1),\r\n tap(updateMetaDescription)\r\n);\r\n\r\nmerge(setH1Text$, setH2Text$, setFooter$, setTitle$, setCanonical$, setMetaDescription$, setMetaRobots$).subscribe();\r\nremoveCanonicalOnMoveInDateFilterApplied();\r\n","import { getHousingProductSnippetContent } from 'constants/routes';\r\nimport { fromFetch } from 'rxjs/fetch';\r\n\r\nfunction getHousingProductSnippetContentRequest$(searchParameters) {\r\nconst requestObject = {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...searchParameters,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n selector: (response) => response.json(),\r\n };\r\n return fromFetch(getHousingProductSnippetContent, requestObject);\r\n}\r\n\r\nexport default getHousingProductSnippetContentRequest$;\r\n","import { store$ } from '@redux/store';\r\nimport getHousingProductSnippetContentRequest$ from 'api/getHousingProductSnippetContent';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectSnippetCommand } from 'features/searchResultsFacets';\r\nimport {\r\n catchError,\r\n debounceTime,\r\n distinctUntilChanged,\r\n distinctUntilKeyChanged,\r\n filter,\r\n map,\r\n of,\r\n switchMap,\r\n take,\r\n tap,\r\n} from 'rxjs';\r\n\r\nconst popularSearches = document.querySelector('[data-content-popular-searches]');\r\nconst marketSnapshots = document.querySelector('[data-content-market-snapshots]');\r\nconst geoLocationProximity = document.querySelector('[data-content-geo-location-proximity]');\r\nconst marketSnapshotsContainer = marketSnapshots?.querySelector('[data-market-snapshots-container]');\r\nconst marketSnapshotsTitle = marketSnapshots?.querySelector('[data-market-snapshots-title]');\r\n\r\n/**\r\n * Show the popular search section in the document\r\n */\r\nconst showPopularSearches = () => {\r\n popularSearches.removeAttribute('hidden');\r\n};\r\n\r\n/**\r\n * Show the market snapshot section in the document\r\n */\r\nconst showMarketSnapshot = () => {\r\n marketSnapshots.removeAttribute('hidden');\r\n};\r\n\r\n/**\r\n * Show the geo location proximity section in the document\r\n */\r\nconst showGeoLocationProximity = () => {\r\n geoLocationProximity.removeAttribute('hidden');\r\n};\r\n\r\n/**\r\n * Hide the popular search section in the document\r\n */\r\nconst hidePopularSeaches = () => {\r\n popularSearches.setAttribute('hidden', '');\r\n};\r\n\r\n/**\r\n * Hide the market snapshot section in the document\r\n */\r\nconst hideMarketSnapshot = () => {\r\n marketSnapshots.setAttribute('hidden', '');\r\n};\r\n\r\n/**\r\n * Show the geo location proximity section in the document\r\n */\r\nconst hideGeoLocationProximity = () => {\r\n geoLocationProximity.setAttribute('hidden', '');\r\n};\r\n\r\nconst setPopularSearches = (data) => {\r\n popularSearches.innerHTML = data ?? ``;\r\n};\r\n\r\n/**\r\n * This function takes an array of objects representing the market snapshot snippets,\r\n * where each object has a property called Content.\r\n *\r\n * Then it takes the Content property of each object and joins them together into one string,\r\n * and sets the innerHTML of the marketSnapshotsContainer to the combined string.\r\n *\r\n * @param data - an array of snippets objects.\r\n */\r\nconst setMarketSnapshot = (data) => {\r\n const htmlSnapshots = data?.map((snapShot) => snapShot.Content || '');\r\n const combinedHtml = htmlSnapshots?.join('');\r\n marketSnapshotsContainer.innerHTML = combinedHtml ?? '';\r\n\r\n if (!combinedHtml || combinedHtml?.length === 0) {\r\n marketSnapshotsTitle.setAttribute('hidden', '');\r\n }else{\r\n marketSnapshotsTitle.removeAttribute('hidden');\r\n }\r\n};\r\n\r\nconst setGeoLocationProximity = (data) => {\r\n geoLocationProximity.innerHTML = data ?? ``;\r\n};\r\n\r\n/**\r\n * If there is no snippet information or the listing count is 0, hide the geo location proximity\r\n * snippet. Otherwise, show the geo location proximity snippet.\r\n *\r\n * @param listingCounts - This is the number of listings that are returned from the search.\r\n * @param snippetInformation - This is an object that contains the information for the snippet.\r\n */\r\nconst toggleGeoLocationProximitySnippet = (listingCounts, snippetInformation) => {\r\n if (!snippetInformation || listingCounts === 0) {\r\n hideGeoLocationProximity();\r\n } else {\r\n showGeoLocationProximity();\r\n }\r\n};\r\n\r\n/**\r\n * If there is no snippet information or the listing count is 0, hide the market snapshot snippet.\r\n * Otherwise, show the market snapshot snippet.\r\n *\r\n * @param listingCounts - This is the number of listings that are returned from the search.\r\n * @param snippetInformation - This is an object that contains the information for the snippet.\r\n */\r\nconst toggleMarketSnapshotSnippet = (listingCounts, snippetInformation) => {\r\n if (snippetInformation.length === 0 || listingCounts === 0) {\r\n hideMarketSnapshot();\r\n } else {\r\n showMarketSnapshot();\r\n }\r\n};\r\n\r\n/**\r\n * If there is no snippet information or the listing count is 0, hide the popular searches\r\n * snippet. Otherwise, show the popular searches snippet.\r\n *\r\n * @param listingCounts - This is the number of listings that are returned from the search.\r\n * @param snippetInformation - This is an object that contains the information for the snippet.\r\n */\r\nconst togglePopularSearchesSnippet = (listingCounts, snippetInformation) => {\r\n if (!snippetInformation || listingCounts === 0) {\r\n hidePopularSeaches();\r\n } else {\r\n showPopularSearches();\r\n }\r\n};\r\n\r\n/*\r\n * This is a stream that is subscribing to the store and checking if the state has changed.\r\n */\r\nconst onResultsReady$ = store$.pipe(\r\n map(selectSnippetCommand),\r\n distinctUntilChanged(),\r\n debounceTime(100),\r\n switchMap((snippetCommand) => getHousingProductSnippetContentRequest$(snippetCommand).pipe(\r\n catchError(() => of(null)) // catch and ignore any errors\r\n)),\r\n take(1));\r\n\r\n/*\r\n * Returns the lastest listing count value whether the result count request is Succeeded when the\r\n * 'fetchResultCountsStatus' is triggered and its value is not undefined regardless of \r\n * it is greater or smaller since the snippets depends on that to be re-generated.\r\n */\r\nconst onListingCount$ = store$.pipe(\r\n map((state) => ({\r\n fetchResultCountsStatus: state?.searchParameters?.fetchResultCountsStatus,\r\n total: state?.searchParameters?.counts?.listingCount,\r\n })),\r\n distinctUntilKeyChanged('fetchResultCountsStatus'),\r\n filter(\r\n ({fetchResultCountsStatus, total}) =>\r\n fetchResultCountsStatus === LoadingStatus.Succeeded &&\r\n total !== undefined\r\n ),\r\n);\r\n\r\n/*\r\n * When we apply some filter or navigate in the map several times the listing count process is cancelled\r\n * to avoid doing several request when it has been changed, we linked the onResultsReady$ only when \r\n * the onListingCount$ changed. It can help us to control the request that causes delay to display the\r\n * snippets.\r\n * \r\n * Then, destructure the array into two variables, one for the listing count and one for the response of the fetch\r\n * for the snippet information.\r\n *\r\n * Set the snippet information into the document and then call the toggle functions to show or hide the snippets.\r\n */\r\nonListingCount$\r\n .pipe(\r\n switchMap(\r\n (listingCount) => onResultsReady$\r\n .pipe(\r\n map(response => ([listingCount, response])))),\r\n tap(([listingCount, response]) => {\r\n const geoLocationProximitySnippet = response?.GeoLocationProximitySnippet?.Content;\r\n const marketSnapshotSnippets = response?.MarketSnapshotSnippets;\r\n const popularSearchesSnippet = response?.PopularSearchesSnippet?.Content;\r\n const totalListingCount = listingCount?.total;\r\n\r\n setGeoLocationProximity(geoLocationProximitySnippet);\r\n setMarketSnapshot(marketSnapshotSnippets);\r\n setPopularSearches(popularSearchesSnippet);\r\n toggleGeoLocationProximitySnippet(totalListingCount, geoLocationProximitySnippet);\r\n toggleMarketSnapshotSnippet(totalListingCount, marketSnapshotSnippets);\r\n togglePopularSearchesSnippet(totalListingCount, popularSearchesSnippet);\r\n })\r\n )\r\n .subscribe();\r\n","import { createSelector } from \"@reduxjs/toolkit\";\r\n\r\n/* The HousingProductLocationContentCommand class is a constructor function that returns a selector\r\nfunction used to create a canonical URL and search location command based on input parameters. */\r\nexport default class HousingProductLocationContentCommand {\r\n\r\n/**\r\n * This is a constructor function that takes in three parameters.\r\n * @param selectHousingProductLocationContentContext - This parameter is likely a context or reference\r\n * to the HTML element that contains the housing product location content. It could be used to\r\n * manipulate or retrieve information from that element using JavaScript or other web technologies.\r\n * @param urlQueryStringSelector - It is a string that represents a selector used to extract the query\r\n * string from the URL.\r\n * @param selectSearchCommandContext - It is a context object that is used to select a search command.\r\n * It is likely used in a larger codebase to handle user input and trigger search functionality.\r\n */\r\n constructor(\r\n selectHousingProductLocationContentContext,\r\n urlQueryStringSelector, \r\n selectSearchCommandContext,\r\n selectConstructQueryString) {\r\n this.selectHousingProductLocationContentContext = selectHousingProductLocationContentContext;\r\n this.urlQueryStringSelector = urlQueryStringSelector;\r\n this.selectSearchCommandContext = selectSearchCommandContext;\r\n this.selectConstructQueryString = selectConstructQueryString;\r\n }\r\n\r\n/**\r\n * The function returns a selector that creates a canonical URL and a search location command based on\r\n * various input parameters.\r\n * @returns A selector function is being returned that takes in three arguments:\r\n * `selectHousingProductLocationContentContext`, `urlQueryStringSelector`, and\r\n * `selectSearchCommandContext`. The function returns an object with two properties:\r\n * `createCanonicalUrlCommand` and `searchLocationCommand`. The values of these properties are objects\r\n * that are created by merging the values of the input arguments.\r\n */\r\n selectHousingProduct() {\r\n return createSelector(\r\n this.selectHousingProductLocationContentContext,\r\n this.urlQueryStringSelector,\r\n this.selectSearchCommandContext,\r\n this.selectConstructQueryString,\r\n (locationContentCommand, queryStringSelector, searchParams, queryString) => {\r\n const parameters = new URLSearchParams(queryString);\r\n const queryStrings = Array.from(parameters.keys());\r\n const searchCommand = structuredClone(searchParams);\r\n searchCommand.searchParameters.queryStrings = queryStrings;\r\n return {\r\n createCanonicalUrlCommand: { ...locationContentCommand, ...queryStringSelector },\r\n searchLocationCommand: { ...searchCommand },\r\n }});\r\n } \r\n}","import { urlFilterSelector } from 'features/routing';\r\nimport { selectLocationContentContext, selectSearchCommandContext } from 'features/searchResultsFacets';\r\nimport { selectConstructQueryString } from 'pages/searchResults/redux/selectors';\r\nimport HousingProductLocationContentCommand from '../commands/housingProductLocationContentCommand';\r\n\r\n/**\r\n * This function returns a new instance of the HousingProductLocationContentCommand class with specific\r\n * parameters.\r\n * @returns A function that creates and returns an instance of the\r\n * `HousingProductLocationContentCommand` class with three arguments: `selectLocationContentContext`,\r\n * `urlFilterSelector`, and `selectSearchCommandContext`.\r\n */\r\nconst housingProductLocationContentCommand = () => {\r\n const command = new HousingProductLocationContentCommand(\r\n selectLocationContentContext,\r\n urlFilterSelector,\r\n selectSearchCommandContext,\r\n selectConstructQueryString,\r\n );\r\n\r\n return command;\r\n};\r\n\r\nexport default housingProductLocationContentCommand;\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { getOnPageContent } from 'constants/routes'\r\n\r\n/**\r\n * This function sends a POST request with search parameters to get on-page content and returns a\r\n * response in JSON format.\r\n * @param searchParameters - It is an object that contains the parameters for the location content\r\n * command. The specific parameters depend on the API being used, but they are likely related to\r\n * specifying the location and type of content to retrieve.\r\n * @returns an Observable from the RxJS library, which will make a POST request to the\r\n * `getOnPageContent` endpoint with the provided `searchParameters` as the request body. The response\r\n * will be converted to JSON format using the `selector` function and returned as an Observable.\r\n */\r\nfunction getOnPageContentRequest$(contentCommandParameters) {\r\nconst requestObject = {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n housingProductLocationContentCommand: {\r\n createCanonicalUrlCommand: { ...contentCommandParameters.createCanonicalUrlCommand },\r\n searchCommand : { ...contentCommandParameters.searchLocationCommand.searchParameters },\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n selector: (response) => response.json(),\r\n };\r\n return fromFetch(getOnPageContent, requestObject);\r\n}\r\n\r\nexport default getOnPageContentRequest$;\r\n","import { ofType } from 'redux-observable';\r\nimport { catchError, of, switchMap } from 'rxjs';\r\nimport locationContentSlice from './slice';\r\nimport housingProductLocationContentCommand from '../services/commands';\r\nimport getOnPageContentRequest$ from '../apis/getHousingProductLocationContent';\r\n\r\nconst actions = locationContentSlice.actions;\r\n\r\nconst command = housingProductLocationContentCommand();\r\n\r\n/**\r\n * This is an epic that listens for a fetch action, retrieves data using a payload from the state,\r\n * and dispatches either a fetchFulfilled or fetchError action based on the result.\r\n * @param action$ - parameter is an observable stream of actions dispatched in the\r\n * application. It represents the actions that are being listened to by the epic.\r\n * @param state$ - is an observable stream that emits the current state of the\r\n * application. It is typically used to access the current state values and make decisions based on\r\n * them.\r\n */\r\nconst fetchHousingProductLocationContentEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.fetch.type),\r\n switchMap(() => {\r\n const selectHousingProduct = command.selectHousingProduct();\r\n const payload = selectHousingProduct(state$.value);\r\n return getOnPageContentRequest$(payload).pipe(\r\n switchMap((data) => of(actions.fetchFulfilled(data))),\r\n catchError((error) => of(actions.fetchError(error)))\r\n );\r\n })\r\n );\r\n\r\nexport default fetchHousingProductLocationContentEpic;\r\n","import { epic$, store } from '@redux/store';\r\nimport housingProductLocationContentSlice from './redux/slice';\r\nimport fetchHousingProductLocationContentEpic from './redux/epics';\r\nimport { selectFetchStatus, selectRequestStatus } from './redux/selectors';\r\n\r\nconst { actions: housingProductLocationContentActions, reducer } = housingProductLocationContentSlice;\r\nepic$.next(fetchHousingProductLocationContentEpic);\r\nstore.injectReducer('housingProductLocationContent', reducer);\r\n\r\nrequire('./components/snippetContentHandler');\r\nrequire('./components/breadcrumbContentHandler');\r\nrequire('./components/housingProductLocationContentHandler');\r\n\r\nexport { \r\n housingProductLocationContentActions, \r\n selectFetchStatus as selectHousingProductLocationFetchStatus,\r\n selectRequestStatus\r\n };\r\n","import { createSelector } from \"@reduxjs/toolkit\";\r\nimport { fetchingResultsCallStatusesSelector } from \"features/searchResultsFacets\";\r\n\r\nexport const selectTitle = (state) => state?.housingProductLocationContent?.title;\r\nexport const selectMetaDescription = (state) => state?.housingProductLocationContent?.metaDescription;\r\nexport const selectMetaRobots = (state) => state?.housingProductLocationContent?.metaRobots;\r\nexport const selectCanonical = (state) => state?.housingProductLocationContent?.canonical;\r\nexport const selectHeading1 = (state) => state?.housingProductLocationContent?.heading1;\r\nexport const selectHeading2 = (state) => state?.housingProductLocationContent?.heading2;\r\nexport const selectFooter = (state) => state?.housingProductLocationContent?.footer;\r\nexport const selectFetchStatus = (state) => state?.housingProductLocationContent?.fetchStatus;\r\n\r\n/**\r\n * Composed selector to get the fetch status of the:\r\n * List view\r\n * Counts\r\n * Housing product location\r\n */\r\nexport const selectRequestStatus = createSelector(\r\n fetchingResultsCallStatusesSelector,\r\n selectFetchStatus,\r\n (fetchingResultsCallStatuses, housingProductLocationFetchStatus) => ({\r\n fetchResultListingsStatus: fetchingResultsCallStatuses.fetchResultListingsStatus,\r\n fetchResultCountsStatus: fetchingResultsCallStatuses.fetchResultCountsStatus,\r\n housingProductLocationFetchStatus,\r\n })\r\n );\r\n","import LoadingStatus from 'enums/loadingStatus';\r\n\r\nconst fetchStatus = LoadingStatus.Idle;\r\nconst title = document.title;\r\nconst metaDescription = document.querySelector('meta[name=\"description\"]')?.content;\r\nconst metaRobots = document.querySelector('meta[name=\"robots\"]')?.content;\r\nconst canonical = document.querySelector('link[rel=\"canonical\"]')?.href;\r\nconst heading1 = document.querySelector('[data-heading1]')?.innerText;\r\nconst heading2 = document.querySelector('[data-heading2]')?.innerText;\r\nconst footer = document.querySelector('[data-footer-content]')?.innerHTM;\r\n\r\nexport default {\r\n fetchStatus,\r\n title,\r\n metaDescription,\r\n metaRobots,\r\n canonical,\r\n heading1,\r\n heading2,\r\n footer\r\n};","import { createSlice } from '@reduxjs/toolkit';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { camelCaseObjectKeys } from 'utils/camelCase';\r\nimport initialState from './initialState';\r\n\r\nconst housingProductLocationContentSlice = createSlice({\r\n name: 'housingProductLocationContent',\r\n initialState,\r\n reducers: {\r\n fetch: (state) => {\r\n state.fetchStatus = LoadingStatus.Loading;\r\n },\r\n fetchFulfilled: (state, action) => {\r\n const payload = camelCaseObjectKeys(action.payload);\r\n state.fetchStatus = LoadingStatus.Succeeded;\r\n state.title = payload.title;\r\n state.metaDescription = payload.metaDescription;\r\n state.metaRobots = payload.metaRobots;\r\n state.canonical = payload.canonical;\r\n state.heading1 = payload.heading1;\r\n state.heading2 = payload.heading2;\r\n state.footer = payload.footer;\r\n },\r\n fetchError: (state) => {\r\n state.fetchStatus = LoadingStatus.Failed;\r\n },\r\n },\r\n});\r\n\r\n// Extract the action creators object and the reducer\r\nexport default housingProductLocationContentSlice;\r\n","/**\r\n * @classdesc The `PillType` class is the source of truth for which pill types currently exist for the\r\n * popular searches pills feature.\r\n */\r\nexport default class PillType {\r\n /**\r\n * Gets the details for the HotDeals pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get HotDeals() {\r\n return this.getInstance('hotDeals', 'Hot deals');\r\n }\r\n\r\n /**\r\n * Gets the details for the Adult pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get Adult() {\r\n return this.getInstance('adult', '55+ Communities');\r\n }\r\n\r\n /**\r\n * Gets the details for the ComingSoon pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get ComingSoon() {\r\n return this.getInstance('comingSoon', 'Coming soon');\r\n }\r\n\r\n /**\r\n * Gets the details for the FloorPlans pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get FloorPlans() {\r\n return this.getInstance('floorPlans', 'Floor plans');\r\n }\r\n\r\n /**\r\n * Gets the details for the QuickMoveIns pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get QuickMoveIns() {\r\n return this.getInstance('quickMoveIns', 'Quick move-ins');\r\n }\r\n\r\n /**\r\n * Gets the details for the Condo and Townhomes pill type.\r\n * @returns {{ name: string, text: string }} The pill details for this type.\r\n */\r\n static get CondosAndTownhomes() {\r\n return this.getInstance('condosAndTownhomes', 'Condos & Townhomes');\r\n }\r\n\r\n /**\r\n * The getInstance function returns an instance of the PillType class based on the\r\n * provided key, creating a new instance if one does not already exist.\r\n * @param {string} name A unique identifier used to determine which instance of PillType class to retrieve.\r\n * @param {string} text The text that should be rendered for a given PillType class.\r\n * @returns {PillType} The instance of the PillType class with the specified key.\r\n */\r\n static getInstance(name, text) {\r\n if (!this.instances[name]) {\r\n this.instances[name] = new PillType(name, text);\r\n }\r\n return this.instances[name];\r\n }\r\n\r\n constructor(name, text) {\r\n this.name = name;\r\n this.text = text;\r\n }\r\n\r\n /**\r\n * Returns the name of the pill type as a string.\r\n * @returns {string} The name of the pill type.\r\n */\r\n toString() {\r\n return this.name;\r\n }\r\n}\r\n\r\nObject.defineProperty(PillType, 'instances', { value: {} });\r\n","import { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map, skip } from \"rxjs\";\r\nimport { selectNextPageUrl, selectPreviousPageUrl } from \"../redux/selectors\";\r\n\r\n/**\r\n * createRelationElement: Creates a new Rel Element related to the paging.\r\n * @param {string} relationType It is the rel element type. It could be prev or next.\r\n * @returns An HTMLElement with the required rel information.\r\n */\r\nfunction createRelationElement(relationType) { \r\n const relationElement = document.createElement('link');\r\n relationElement.rel = relationType;\r\n document.head.appendChild(relationElement);\r\n\r\n return relationElement;\r\n}\r\n\r\n/**\r\n * getPageLink: Gets the DOM element that is going to be used as a page link.\r\n * @param {string} pageLinkType The page link type that is going to get.\r\n * @returns An HTMLElement related to the page link required.\r\n */\r\nconst getPageLink = (pageLinkType) => {\r\n const pageLink = document.querySelector(`[rel=\"${pageLinkType}\"]`);\r\n return pageLink ?? createRelationElement(pageLinkType);\r\n}\r\n\r\n/**\r\n * removePageLink: Removes the page link element from the DOM.\r\n * @param {string} pageLinkType The page link type that is going to remove.\r\n */\r\nconst removePageLink = (pageLinkType) => {\r\n const previousPageLink = document.querySelector(`[rel=\"${pageLinkType}\"]`);\r\n previousPageLink?.remove();\r\n}\r\n\r\n/**\r\n * \r\n * @param {string} pageLinkUrl The url related to the page url element.\r\n * @param {string} pageLinkType Page link type that will be updated.\r\n */\r\nconst updatePageLink = (pageLinkUrl, pageLinkType) => {\r\n const pageLinkElement = getPageLink(pageLinkType);\r\n pageLinkElement.href = pageLinkUrl;\r\n}\r\n\r\n/**\r\n * handlePreviousPageLink: Handles the changes related to the Previous Page Link element.\r\n * @param {string} previousPageLinkUrl The url for the previous page link element.\r\n */\r\nconst handlePreviousPageLink = (previousPageLinkUrl) => {\r\n if (previousPageLinkUrl) {\r\n updatePageLink(previousPageLinkUrl, 'prev');\r\n } else {\r\n removePageLink('prev');\r\n }\r\n}\r\n\r\n/**\r\n * handleNextPageLink: Handles the changes related to the Next Page Link element.\r\n * @param {string} nextPageLinkUrl The url for the next page link element.\r\n */\r\nconst handleNextPageLink = (nextPageLinkUrl) => {\r\n if (nextPageLinkUrl) {\r\n updatePageLink(nextPageLinkUrl, 'next');\r\n } else {\r\n removePageLink('next');\r\n }\r\n}\r\n\r\nconst nextPageUrlChange$ = store$.pipe(\r\n map(selectNextPageUrl),\r\n distinctUntilChanged(),\r\n skip(1)\r\n);\r\n\r\nnextPageUrlChange$.subscribe(handleNextPageLink);\r\n\r\nconst previousPageUrlChange$ = store$.pipe(\r\n map(selectPreviousPageUrl),\r\n distinctUntilChanged(),\r\n skip(1)\r\n);\r\n\r\npreviousPageUrlChange$.subscribe(handlePreviousPageLink);","import { ofType } from \"redux-observable\";\r\nimport { debounceTime, of, switchMap, map, distinctUntilChanged } from \"rxjs\";\r\nimport routingStateSlice from \"./slices\";\r\nimport { buildNewUrl } from '../services/urlBuilder'\r\nimport { urlComponentsSelector } from \"./selectors\";\r\n\r\nconst actions = routingStateSlice.actions;\r\nconst updateUrlEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(\r\n actions.updatePagination,\r\n actions.updateSubdirectory,\r\n actions.updateLocation,\r\n actions.updateQueryString,\r\n actions.updateBuilderName,\r\n ),\r\n map(() => {\r\n const config = urlComponentsSelector(state$.value);\r\n const newUrl = buildNewUrl(config);\r\n return newUrl.href;\r\n }),\r\n distinctUntilChanged(),\r\n debounceTime(100),\r\n switchMap((url) => of(actions.updateUrl(url)))\r\n );\r\n\r\nexport default updateUrlEpic;","import { epic$, store } from \"@redux/store\";\r\nimport updateUrlEpic from \"./redux/epics\";\r\nimport {\r\n selectCurrentUrl,\r\n selectRoutingState,\r\n selectUrlLocation,\r\n urlComponentsSelector,\r\n urlFilterSelector,\r\n selectUrlSubdirectory,\r\n selectMapCoordinatesQueryString\r\n} from \"./redux/selectors\";\r\nimport routingStateSlice from \"./redux/slices\";\r\nimport { buildNewUrl, getPaging, getBrandName } from \"./services/urlBuilder\";\r\n\r\nrequire(\"./redux/listeners\");\r\nrequire(\"./components/pageLinkHandler\");\r\n\r\nconst { actions: routingStateActions, reducer } = routingStateSlice;\r\nepic$.next(updateUrlEpic);\r\nstore.injectReducer(\"routingState\", reducer);\r\n\r\nconst routingSelectors = {\r\n urlComponentsSelector,\r\n selectCurrentUrl,\r\n selectUrlLocation,\r\n};\r\n\r\nexport {\r\n routingStateActions,\r\n routingSelectors,\r\n selectUrlSubdirectory,\r\n getPaging,\r\n buildNewUrl,\r\n getBrandName,\r\n selectRoutingState,\r\n urlFilterSelector,\r\n selectCurrentUrl,\r\n selectMapCoordinatesQueryString\r\n};\r\n","import { createListenerMiddleware } from \"@reduxjs/toolkit\";\r\nimport { addMiddleware } from \"redux-dynamic-middlewares\";\r\nimport routingStateSlice from \"./slices\";\r\n\r\nconst routingActions = routingStateSlice.actions;\r\n\r\nconst listenerMiddleware = createListenerMiddleware();\r\n\r\n// This listener keeps the URL up to date on the window object.\r\nlistenerMiddleware.startListening({\r\n type: routingActions.updateUrl.type,\r\n effect: (action) => {\r\n const newUrl = action.payload;\r\n // This new URL is pushed into the window history state to be accessed through the browser's\r\n // back and forward buttons, however, those buttons won't trigger a page reload until the\r\n // the subscriber method in the backForwardHandler.js file is executed.\r\n window.history.pushState({}, \"\", newUrl);\r\n },\r\n});\r\n\r\naddMiddleware(listenerMiddleware.middleware);\r\n","import { createSelector } from \"@reduxjs/toolkit\";\r\n\r\nexport const selectUrlSubdirectory = (state) => state?.routingState?.urlSubdirectory;\r\nexport const selectUrlLocation = (state) => state?.routingState?.urlLocation;\r\nexport const selectUrlPagination = (state) => state?.routingState?.urlPaging;\r\nexport const selectUrlQueryString = (state) => state?.routingState?.urlQueryString;\r\nexport const selectNextPageUrl = (state) => state?.routingState?.nextPageUrl;\r\nexport const selectBuilderName = (state) => state?.routingState?.urlBuilderName;\r\nexport const selectPreviousPageUrl = (state) => state?.routingState?.previousPageUrl;\r\nexport const selectCurrentUrl = (state) => state?.routingState?.currentUrl;\r\nexport const selectRoutingState = (state) => state?.routingState;\r\nexport const selectMapCoordinatesQueryString = (state) => state?.routingState?.urlCoordinatesQueryString;\r\n\r\nexport const urlComponentsSelector = createSelector(\r\n selectUrlSubdirectory,\r\n selectUrlLocation,\r\n selectUrlPagination,\r\n selectUrlQueryString,\r\n selectBuilderName,\r\n selectMapCoordinatesQueryString,\r\n (urlSubdirectory, urlLocation, urlPaging, urlQueryString, urlBuilderName, urlCoordinatesQueryString) => ({\r\n urlSubdirectory,\r\n urlLocation,\r\n urlPaging,\r\n urlQueryString,\r\n urlBuilderName,\r\n urlCoordinatesQueryString,\r\n })\r\n);\r\n\r\nexport const urlFilterSelector = createSelector(\r\n selectUrlQueryString,\r\n selectUrlSubdirectory,\r\n (queryStringParameter, urlSubdirectory) => ({\r\n queryStringParameter,\r\n urlSubdirectory\r\n })\r\n);","const routingDataElement = document.querySelector('[data-component=\"routing-data\"]');\r\nconst routingData = JSON.parse(routingDataElement.innerHTML);\r\nconst currentUrl = new URL(window.location);\r\nconst initialState = {\r\n currentUrl,\r\n urlSubdirectory: routingData.urlSubdirectory,\r\n urlPaging: routingData.urlPaging,\r\n urlQueryString: currentUrl.searchParams.toString(),\r\n urlLocation: routingData.urlLocation,\r\n urlBuilderName: routingData.urlBuilderName,\r\n urlCoordinatesQueryString: routingData.urlCoordinatesQueryString,\r\n}\r\n\r\nexport default initialState;","import { createSlice } from '@reduxjs/toolkit';\r\nimport initialState from './initialState';\r\n\r\n/* Creating a slice of the state of the routing. */\r\nconst routingStateSlice = createSlice({\r\n name: 'routingState',\r\n initialState,\r\n reducers: {\r\n updateUrl: (state, action) => {\r\n const newUrl = action.payload;\r\n state.currentUrl = new URL(newUrl);\r\n },\r\n updatePagination: (state, action) => {\r\n state.urlPaging = action.payload;\r\n },\r\n updateBuilderName: (state, action) => {\r\n state.urlBuilderName = action.payload;\r\n },\r\n updateSubdirectory: (state, action) => {\r\n state.urlSubdirectory = action.payload;\r\n },\r\n updateLocation: (state, action) => {\r\n state.urlLocation = action.payload;\r\n },\r\n updateQueryString: (state, action) => {\r\n state.urlQueryString = action.payload;\r\n },\r\n updatePreviousPageUrl: (state, action) => {\r\n state.previousPageUrl = action.payload;\r\n },\r\n updateNextPageUrl: (state, action) => {\r\n state.nextPageUrl = action.payload;\r\n },\r\n updateRectangularSearchQueryString: (state, action) => {\r\n state.urlCoordinatesQueryString = action.payload;\r\n\r\n if (action.payload){\r\n state.urlLocation = 'map';\r\n }\r\n },\r\n },\r\n});\r\n\r\nexport default routingStateSlice;\r\n","import StringExtensions from \"utils/stringExtensions\";\r\n\r\n/**\r\n * buildUrlPathName: Builds the pathname of the new url.\r\n * @param {string} subdirectory Segment related to the search subdirectory.\r\n * @param {string} location Segments related to the search location. \r\n * @param {string} paging Segment related to the search page.\r\n * @returns An string with the pathname of the search.\r\n */\r\nfunction buildUrlPathName(subdirectory, location, paging, builderName) {\r\n // The order to build the current search results url pathname is\r\n // subdirectory segment, then the location segments and finally the paging segment.\r\n const urlSegments = [];\r\n if(subdirectory) {\r\n urlSegments.push(subdirectory);\r\n }\r\n\r\n if(location) {\r\n urlSegments.push(location);\r\n }\r\n\r\n if(builderName) {\r\n urlSegments.push(builderName);\r\n }\r\n\r\n if (paging) {\r\n urlSegments.push(paging);\r\n }\r\n\r\n return urlSegments.join('/');\r\n}\r\n\r\n/**\r\n * buildNewUrl: Builds the entire url for the new search.\r\n * @param {object} config configuration object, it includes the following fields:\r\n * subdirectory, location, pagination, queryString, builderName.\r\n * @returns \r\n */\r\nfunction buildNewUrl(config) {\r\n const { urlSubdirectory, urlLocation, urlPaging, urlQueryString, urlBuilderName } = config;\r\n\r\n const newPathName = buildUrlPathName(urlSubdirectory, urlLocation, urlPaging, urlBuilderName);\r\n const newUrl = new URL(newPathName, window.location.origin);\r\n\r\n newUrl.search = urlQueryString;\r\n\r\n return newUrl;\r\n}\r\n\r\n/**\r\n * getPaging: Gets the paging segment for the search.\r\n * @param {Number} pageNumber Number of the selected page.\r\n * @returns The segment related to the paging of the current search.\r\n */\r\nfunction getPaging(pageNumber) {\r\n // We only add the paging segment when the selected page is 2 or more.\r\n const shouldShowPagingOnUrl = pageNumber > 1;\r\n if (!shouldShowPagingOnUrl) {\r\n return '';\r\n }\r\n\r\n const newPaging = `page-${pageNumber}`;\r\n return newPaging;\r\n}\r\n\r\n/**\r\n * Returns a formatted brand name.\r\n *\r\n * @param {string} brandName - The name of the brand.\r\n * @param {number} brandId - The ID of the brand.\r\n * @returns {string} - The formatted brand name.\r\n */\r\nfunction getBrandName(brandName, brandId) {\r\n if (!brandName || !brandId) {\r\n // If either brandName or brandId is not provided, return an empty string\r\n return '';\r\n }\r\n\r\n // Remove any special characters from the brandName\r\n const name = StringExtensions.encodeNameToUrl(brandName);\r\n\r\n // Return the formatted brand name with the builder prefix and brandId\r\n return `builder-${name}-${brandId}`;\r\n}\r\n\r\nexport { buildNewUrl, getPaging, buildUrlPathName, getBrandName };","function isTouchDevice() {\r\n return (\r\n \"ontouchstart\" in window ||\r\n navigator.maxTouchPoints > 0 ||\r\n navigator.msMaxTouchPoints > 0\r\n );\r\n}\r\n\r\nclass MiniCardSlider {\r\n constructor() {\r\n this.counter = 0;\r\n this.element = document.querySelector(\".summary__cards-section\");\r\n\r\n if (!this.element) {\r\n return;\r\n }\r\n\r\n this.sliderItems = this.element.querySelectorAll(\".slideshow__card\");\r\n this.sliderLength = this.sliderItems.length - 1;\r\n this.sliderWidth = this.sliderItems[0].clientWidth;\r\n this.slidesContainer = this.element.querySelector(\".carousel--flyover-homes\");\r\n this.prevButton = this.element.querySelector(\".left--arrow\");\r\n this.nextButton = this.element.querySelector(\".right--arrow\");\r\n \r\n // Prevent initilization\r\n if (!this.initSlider()) { \r\n return;\r\n }\r\n\r\n this.prevButton?.addEventListener(\"click\", () => { \r\n if (this.counter >= 1) {\r\n this.counter -= 1; \r\n this.scrollIntoView();\r\n } \r\n });\r\n\r\n this.nextButton?.addEventListener(\"click\", () => { \r\n if (this.counter < this.sliderLength) {\r\n this.counter += 1; \r\n this.scrollIntoView();\r\n }\r\n });\r\n\r\n const reportWindowSize = () => { \r\n this.counter = 1;\r\n this.scrollIntoView();\r\n };\r\n\r\n this.checkArrowButtons();\r\n window.onresize = reportWindowSize;\r\n }\r\n\r\n\r\n isSliderDisable() {\r\n return this.element.scrollWidth >= this.sliderWidth * (this.sliderLength + 1)\r\n }\r\n\r\n initSlider() { \r\n if (this.isSliderDisable() || isTouchDevice()) {\r\n return false;\r\n }\r\n return true;\r\n } \r\n \r\n checkArrowButtons() {\r\n if (this.counter === 0) {\r\n this.prevButton?.setAttribute(\"disabled\", true);\r\n } else {\r\n this.prevButton?.removeAttribute(\"disabled\");\r\n } \r\n\r\n if (this.counter === this.sliderLength) {\r\n this.nextButton?.setAttribute(\"disabled\", true);\r\n } else {\r\n this.nextButton?.removeAttribute(\"disabled\");\r\n }\r\n }\r\n\r\n scrollIntoView() { \r\n const currentElement = this.sliderItems[this.counter];\r\n currentElement.scrollIntoView({ behavior: \"smooth\", inline: \"center\" });\r\n this.checkArrowButtons();\r\n }\r\n}\r\n\r\nexport default MiniCardSlider;\r\n","export default class ReadMore {\r\n constructor() {\r\n this.characterLimit = 170;\r\n this.readMoreText = 'read more';\r\n this.readLessText = 'read less';\r\n this.dataReadSelector = '[data-read]';\r\n }\r\n\r\n /**\r\n * Gets a string and add it a read more and read less link text.\r\n * @param {string} hiddenText with the text needed to be access with read more link. \r\n */\r\n getReadMoreHtml(hiddenText) {\r\n const hiddenTextArea = `${hiddenText}`;\r\n const readMore = `...${this.readMoreText}`;\r\n const readLess = `${this.readLessText}`;\r\n\r\n return `${hiddenTextArea}${readMore}${readLess}`;\r\n }\r\n\r\n /**\r\n * Toggle a class depending if the read more link is clicked showing all the text and\r\n * hidding the text when read less link is clicked.\r\n * @param {event} event click dispatch when click on read more or read less text.\r\n */\r\n static toggleReadMore(event) {\r\n const target = event.target;\r\n const closestReadMore = target.closest('.add-read-more');\r\n if (closestReadMore.classList.contains('show-less-content')) {\r\n closestReadMore.classList.remove('show-less-content');\r\n closestReadMore.classList.add('show-more-content');\r\n return;\r\n }\r\n\r\n closestReadMore.classList.add('show-less-content');\r\n closestReadMore.classList.remove('show-more-content');\r\n }\r\n\r\n /**\r\n * Shows the visible text and add the read more link when the string lenght is greater than\r\n * specified limit characters.\r\n * @param {DOMElement} textElement is the element where the read more or read less toggle would be apply.\r\n */\r\n addReadMoreToggle(textElement) {\r\n const text = textElement?.innerText;\r\n if (!textElement || text?.length <= this.characterLimit) {\r\n return;\r\n }\r\n\r\n textElement.classList.add('add-read-more', 'show-less-content');\r\n const visibleText = text.substring(0, this.characterLimit);\r\n const hiddenText = text.substring(this.characterLimit, text.length);\r\n const readMoreHtml = this.getReadMoreHtml(hiddenText);\r\n textElement.innerHTML = `${visibleText}${readMoreHtml}`;\r\n\r\n const readMoreSpans = document.querySelectorAll(this.dataReadSelector);\r\n readMoreSpans.forEach((element) => element.addEventListener('click', ReadMore.toggleReadMore));\r\n }\r\n}","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport modalService from 'layout/services/modalService';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport MiniCardSlider from './miniCardSlider';\r\nimport ReadMore from './readMore';\r\n\r\nconst { actions } = uiStateSlice;\r\nconst close = () => modalService.clearHtml();\r\nconst isExtendedCard = (state) => state?.uiState?.modalInformation?.name === 'extendedCard';\r\nconst modalInformation = (state) => state?.uiState?.modalInformation;\r\n\r\n/**\r\n * If the modal, container, imageItemTemplate, and brokenTemplate exist, then create a new\r\n * SliderCarousel object with the container, imageItemTemplate, brokenTemplate, and onCreateImage as\r\n * parameters.\r\n */\r\nconst init = () => {\r\n const modal = document.querySelector('.flyover__card');\r\n\r\n modal.querySelector('#nhs_CardClose').addEventListener('click', close);\r\n\r\n (() => new MiniCardSlider())();\r\n\r\n const textElement = modal.querySelector('.about__description');\r\n const readMore = new ReadMore();\r\n readMore.addReadMoreToggle(textElement);\r\n};\r\n\r\n/* Dispatching an action to the store to fetch the extended card. */\r\nconst fetchExtendedCard = (extendedCardInformation) => {\r\n store.dispatch(\r\n actions.fetchModal({\r\n isFetchingModal: true,\r\n parameters: extendedCardInformation,\r\n })\r\n );\r\n};\r\n\r\nmodalService.onHtmlReady({ name: 'extendedCard', fn: init });\r\n\r\nstore$\r\n .pipe(filter(modalInformation), filter(isExtendedCard), map(modalInformation), distinctUntilChanged())\r\n .subscribe(fetchExtendedCard);\r\n","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\n\r\nexport const getBuildeablePlanCard$ = (id) =>\r\n fromFetch(`/ajax/getextendbuildableplanscard?communityId=${id}`).pipe(\r\n switchMap((response) => response.text())\r\n );\r\n\r\nexport const getCommunityExtendCard$ = (id) =>\r\n fromFetch(`/ajax/getextendcommunitycard?communityid=${id}`).pipe(switchMap((response) => response.text()));\r\n\r\nexport const getPlanExtendCard$ = (id) =>\r\n fromFetch(`/ajax/getplanextendcard?planid=${id}`).pipe(switchMap((response) => response.text()));\r\n\r\nexport const getSpecExtendCard$ = (id) =>\r\n fromFetch(`/ajax/getspecextendcard?specid=${id}`).pipe(switchMap((response) => response.text()));\r\n","import { catchError, distinctUntilChanged, filter, map, of, switchMap, tap } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport modalService from 'layout/services/modalService';\r\nimport {\r\n getBuildeablePlanCard$,\r\n getCommunityExtendCard$,\r\n getPlanExtendCard$,\r\n getSpecExtendCard$,\r\n} from '../apis/getExtendedCard';\r\n\r\nconst actions = uiStateSlice.actions;\r\n\r\n/**\r\n * Epic to get the buidleable plan card observable to get the flyover.\r\n * \r\n * You may notice some filters and distinctUntilChanged before the ofType function, \r\n * it is needed caused by following scenario:\r\n * \r\n * When user open the flyover, and click any button of the leads and click back button, \r\n * or click the same button of the map, the flyover request is maked again,\r\n * since the reducer of uiState need to change the prevoius HTML keys (the flyover), but the housing product is\r\n * the same. For this reason we need the distinctUntilChanged, to analysis if the id of the housing product change.\r\n * \r\n * Then we face the other scenario when user open the flyover, close it and then open again the same card,\r\n * the ofType function don't allow to execute the distinctUntilChanged and the value never change, event though\r\n * the properties were set to null. To fix, we need to filter the action to avoid execute the distinctUntilChanged\r\n * when another action is fired, just clearModal and fetchModal actions, and the ask if the value change.\r\n * Then if the action is fetchModal we make the request.\r\n * \r\n */\r\nexport const getBuildeablePlanEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => action.type === actions.fetchModal.type ||\r\n action.type === actions.clearModal.type),\r\n distinctUntilChanged((previous, current) => previous?.payload?.parameters?.id === current?.payload?.parameters?.id),\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'buildeablePlan'),\r\n map((action) => action.payload.parameters?.id),\r\n switchMap((id) =>\r\n getBuildeablePlanCard$(id).pipe(\r\n switchMap((data) => of(actions.fetchModalFulfilled(data))),\r\n tap((data) => modalService.setHtml(data)),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n )\r\n )\r\n );\r\n\r\nexport const getCommunityEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => action.type === actions.fetchModal.type ||\r\n action.type === actions.clearModal.type),\r\n distinctUntilChanged((previous, current) => previous?.payload?.parameters?.id === current?.payload?.parameters?.id),\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'community'),\r\n map((action) => action.payload.parameters?.id),\r\n switchMap((id) =>\r\n getCommunityExtendCard$(id).pipe(\r\n switchMap((data) => of(actions.fetchModalFulfilled(data))),\r\n tap((data) => modalService.setHtml(data)),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n )\r\n )\r\n );\r\n\r\nexport const getPlanEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => action.type === actions.fetchModal.type ||\r\n action.type === actions.clearModal.type),\r\n distinctUntilChanged((previous, current) => previous?.payload?.parameters?.id === current?.payload?.parameters?.id),\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'plan'),\r\n map((action) => action.payload.parameters?.id),\r\n switchMap((id) =>\r\n getPlanExtendCard$(id).pipe(\r\n switchMap((data) => of(actions.fetchModalFulfilled(data))),\r\n tap((data) => modalService.setHtml(data)),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n )\r\n )\r\n );\r\n\r\nexport const getSpecEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => action.type === actions.fetchModal.type ||\r\n action.type === actions.clearModal.type),\r\n distinctUntilChanged((previous, current) => previous?.payload?.parameters?.id === current?.payload?.parameters?.id),\r\n ofType(actions.fetchModal.type),\r\n filter((action) => action.payload.parameters.type === 'spec'),\r\n map((action) => action.payload.parameters?.id),\r\n switchMap((id) =>\r\n getSpecExtendCard$(id).pipe(\r\n switchMap((data) => of(actions.fetchModalFulfilled(data))),\r\n tap((data) => modalService.setHtml(data)),\r\n catchError((err) => of(actions.fetchModalError(err)))\r\n )\r\n )\r\n );\r\n","import { epic$, store } from '@redux/store';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { getBuildeablePlanEpic, getCommunityEpic, getPlanEpic, getSpecEpic } from './redux/epics';\r\n\r\nepic$.next(getBuildeablePlanEpic);\r\nepic$.next(getCommunityEpic);\r\nepic$.next(getPlanEpic);\r\nepic$.next(getSpecEpic);\r\n\r\nexport default (id, type) => {\r\n store.dispatch(uiStateSlice.actions.modalInformation({ id, type, name: 'leadModal' }));\r\n};\r\n\r\nrequire('./components/extendedCard');\r\n","/**\r\n * Represents the type of Active Adult communities filter that can be applied to search results.\r\n */\r\nexport default class ActiveAdultType {\r\n /**\r\n * Used on the Active Adult communities filter, when the user selects the '55+ Communities Only' option.\r\n * It's used to exclusively show communities that are 55+ (adult and age restricted).\r\n */\r\n static get OnlyShowActiveAdultCommunities() {\r\n return this.getInstance('only');\r\n }\r\n\r\n /**\r\n * Used on the Active Adult communities filter, when the user selects the 'Exclude 55+ Communities' option.\r\n * It's used to exclude communities that are 55+ (adult and age restricted).\r\n */\r\n static get ExcludeActiveAdultCommunities() {\r\n return this.getInstance('exclude');\r\n }\r\n\r\n /**\r\n * Used on the Active Adult communities filter, when the user selects the 'Show All Communities' option.\r\n * This is the default value, and displays any kind of communities in the search results page.\r\n */\r\n static get AnyCommunities() {\r\n return this.getInstance('any');\r\n }\r\n\r\n static fromKey(key) {\r\n const map = {\r\n only: ActiveAdultType.Only,\r\n exclude: ActiveAdultType.Exclude,\r\n any: ActiveAdultType.Any,\r\n };\r\n return map[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new ActiveAdultType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(ActiveAdultType, 'instances', { value: {} });\r\n","import { store, store$ } from '@redux/store';\r\nimport { searchParametersActions, activeAdultCommunitiesSelector } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, fromEvent, map } from 'rxjs';\r\nimport ActiveAdultType from '../enums/activeAdultType';\r\n\r\n/**\r\n * The container element for the active adult filter.\r\n */\r\nconst container = document.querySelector('[data-active-adults]');\r\n\r\n/**\r\n * Observable that emits when the 'change' event is triggered on the 'container' element.\r\n * The emitted value is then used to determine which action to dispatch.\r\n * @type {Observable}\r\n */\r\nconst activeAdult$ = fromEvent(container, 'change');\r\n\r\n/**\r\n * Handles the change event for the active adult filter.\r\n * @param {Object} event - The event object.\r\n */\r\nfunction handleActiveAdultChange ({ target }) {\r\n const { value, checked } = target;\r\n \r\n switch (value) {\r\n case ActiveAdultType.OnlyShowActiveAdultCommunities.toString():\r\n store.dispatch(searchParametersActions.fetchActiveAdult(checked));\r\n break;\r\n case ActiveAdultType.ExcludeActiveAdultCommunities.toString():\r\n store.dispatch(searchParametersActions.fetchExcludeActiveAdult(checked));\r\n break;\r\n case ActiveAdultType.AnyCommunities.toString():\r\n store.dispatch(searchParametersActions.fetchAnyCommunities());\r\n break;\r\n default:\r\n break;\r\n }\r\n}\r\n\r\nactiveAdult$.subscribe(handleActiveAdultChange);\r\n\r\n/**\r\n * Updates the active adult filters based on the redux store values.\r\n * @param {Object} filters - The filters object containing the filter names and their corresponding boolean values.\r\n */\r\nfunction updateActiveAdultFilters(filters) {\r\n const filterNames = Object.keys(filters);\r\n\r\n filterNames.forEach((filter) => {\r\n const radio = container.querySelector(`[value=\"${filter}\"]`);\r\n radio.checked = filters[filter];\r\n });\r\n}\r\n\r\n/**\r\n * Subscribes to the store to update the active adult filters when the store values change.\r\n * uses the 'activeAdultCommunitiesSelector' selector to get the active adult filters values from the store.\r\n */\r\nstore$\r\n .pipe(\r\n map(activeAdultCommunitiesSelector),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(updateActiveAdultFilters);\r\n","import ClearFilters from './clearFilters';\r\n\r\nconst clearButton = document.querySelector('[data-advanced-clear-filters]');\r\nconst clearFilters = new ClearFilters(clearButton);\r\n\r\n/**\r\n * toggle the visibility of the clear all button\r\n * it should be less visible when no filters are applied, and more visible when filters are applied\r\n * @param {Array} appliedFacets List of applied facets.\r\n */\r\nconst toggleClearAllButton = (appliedFacets) => {\r\n if (appliedFacets.length > 0) {\r\n clearButton.removeAttribute('disabled');\r\n } else {\r\n clearButton.setAttribute('disabled', '');\r\n }\r\n};\r\n\r\n// subscribe to the observable and call the toggleClearAllButton function\r\nclearFilters.onFacetsApplied$.subscribe(toggleClearAllButton);\r\n","import { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { store$ } from '@redux/store';\r\nimport { ResultType } from 'features/searchResultsFacets';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport {\r\n isAnyHousingTypeActiveSelector,\r\n selectBrandId,\r\n selectGarages,\r\n selectLivingAreas,\r\n selectPrimaryBedroom,\r\n selectRvGarage,\r\n selectSchools,\r\n selectStories,\r\n activeAdultCommunitiesSelector,\r\n selectPriceReduction,\r\n selectReviews,\r\n selectConsumerPromos,\r\n selectNatureAreas,\r\n selectPool,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectGatedCommunity,\r\n selectMarketingStatus,\r\n selectCountsAndResultType,\r\n selectHomeOwnersAssociationFee,\r\n} from '../redux/selectors';\r\nimport OtherFiltersType from '../enums/otherFiltersType';\r\n\r\nlet appliedFilters = [];\r\nconst label = document.querySelector('[data-advanced-panel]');\r\nconst labelTxt = document.querySelector('[data-advanced-panel] span');\r\nconst initialLabelText = labelTxt.textContent;\r\nconst buttonConfirmation = document.querySelector('[data-panel-allfilters] [data-apply]');\r\n\r\n/**\r\n * A function that is called when the counts/result type [community] change to update the confirmation button's text.\r\n */\r\n\r\nfunction setButtonTextForCommunity(listingCounts) {\r\n buttonConfirmation.textContent = `Show ${listingCounts?.toLocaleString()} communities`;\r\n}\r\n\r\n/**\r\n * A function that is called when the counts/result type [homes] change to update the confirmation button's text.\r\n */\r\n\r\nfunction setButtonTextForHomes(listingCounts) {\r\n buttonConfirmation.textContent = `Show ${listingCounts?.toLocaleString()} homes`;\r\n}\r\n\r\nconst isResultTypeCommunity = (resultType) => resultType === ResultType.Communities.toString();\r\n\r\nconst isResultTypeLocations = (resultType) => resultType === ResultType.Locations.toString();\r\n/**\r\n * When the counts or result type change, map the the selector to get the result type\r\n * and the listing counts information.\r\n * Skip the first time for inital load.\r\n */\r\nconst onCountsAndResultsTypeChange$ = store$.pipe(\r\n map(selectCountsAndResultType),\r\n filter(\r\n ({ resultCountsStatus }) =>\r\n resultCountsStatus?.name === LoadingStatus.Succeeded.toString() ||\r\n resultCountsStatus?.name === LoadingStatus.Idle.toString()\r\n ),\r\n distinctUntilChanged()\r\n);\r\n\r\nonCountsAndResultsTypeChange$\r\n .pipe(\r\n filter(({ resultType }) => isResultTypeCommunity(resultType) || isResultTypeLocations(resultType)),\r\n map(({ listingCounts }) => listingCounts)\r\n )\r\n .subscribe(setButtonTextForCommunity);\r\n\r\nonCountsAndResultsTypeChange$\r\n .pipe(\r\n filter(({ resultType }) => !isResultTypeCommunity(resultType) && !isResultTypeLocations(resultType)),\r\n map(({ listingCounts }) => listingCounts)\r\n )\r\n .subscribe(setButtonTextForHomes);\r\n\r\n/**\r\n * Emits a custom event when the advanced filters panel is clicked,\r\n * passing the current applied filters as the event detail.\r\n */\r\nfunction handleAdvancedPanelClick() {\r\n // emit a custom event that lets subscribers know that the panel has been clicked\r\n const event = new CustomEvent('advancedFiltersClicked');\r\n\r\n document.body.dispatchEvent(event);\r\n}\r\n\r\nlabel.addEventListener('click', handleAdvancedPanelClick);\r\n\r\n/**\r\n * A function that is called when the filter is changed to update the advanced label text.\r\n */\r\nfunction updateLabel(data) {\r\n const { value, name } = data;\r\n if (!value || value === '0' || value.length === 0) {\r\n // remove the filter from the applied filters if the value is 0\r\n appliedFilters = appliedFilters.filter((element) => element !== name);\r\n }\r\n // only add the applied filter to the list if not already in the list\r\n else if (appliedFilters.indexOf(name) < 0) {\r\n appliedFilters.push(name);\r\n }\r\n\r\n if (appliedFilters.length > 0) {\r\n if (appliedFilters.length === 1) {\r\n labelTxt.textContent = `${appliedFilters.length} Filter`;\r\n } else {\r\n labelTxt.textContent = `${appliedFilters.length} Filters`;\r\n }\r\n label.classList.add('nhs-c-select-button--active');\r\n } else if (appliedFilters.length === 0) {\r\n labelTxt.textContent = initialLabelText;\r\n label.classList.remove('nhs-c-select-button--active');\r\n }\r\n}\r\n\r\n/**\r\n * Subscribing to the store when living areas change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectLivingAreas),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'livingArea' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when stories change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectStories),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'stories' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when privary bedroom change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectPrimaryBedroom),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'primaryBedroom' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when garages change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectGarages),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'garages' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when nature areas change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectNatureAreas),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'natureAreas' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when pool change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectPool),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'pool' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when golf course change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectGolfCourse),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'golfCourse' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when green change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectGreen),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'green' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when parks change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectParks),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'parks' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when views change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectViews),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'views' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when water front change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectWaterfront),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'waterfront' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when gated community change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectGatedCommunity),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'gatedCommunity' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when sports facilities change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectSportsFacilities),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'sportsFacilities' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when housing planel change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(isAnyHousingTypeActiveSelector),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'housingPanel' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when builder change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectBrandId),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'builder' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when RV garages change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectRvGarage),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'rvGarages' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when schools change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectSchools),\r\n distinctUntilChanged(),\r\n map((schools) => ({ value: schools?.length, name: 'schools' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when hot deals change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectConsumerPromos),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: OtherFiltersType.HotDeals.toString() }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when reviews change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectReviews),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: OtherFiltersType.Reviews.toString() }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when price reduction change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectPriceReduction),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: OtherFiltersType.PriceReduction.toString() }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when community status change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectMarketingStatus),\r\n distinctUntilChanged(),\r\n map((marketingStatus) => ({ value: marketingStatus?.length }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when the active adult filters change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(activeAdultCommunitiesSelector),\r\n distinctUntilChanged(),\r\n // check that the \"show 55+ communities\" or the \"exclude 55+ communities\" are applied.\r\n map((value) => value.only || value.exclude),\r\n map((value) => ({ value, name: 'activeAdult' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\n/**\r\n * Subscribing to the store when hasHomeOwnersAssociationFee change to update the label.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectHomeOwnersAssociationFee),\r\n distinctUntilChanged(),\r\n map((value) => ({ value, name: 'hoa' }))\r\n )\r\n .subscribe(updateLabel);\r\n\r\nrequire('./housingTypeSelect');\r\nrequire('./livingAreas');\r\nrequire('./stories');\r\nrequire('./primaryBedroom');\r\nrequire('./garages');\r\nrequire('./communityAmenities');\r\nrequire('./builders');\r\nrequire('./rvGarage');\r\nrequire('./schools');\r\nrequire('./communityStatus');\r\nrequire('./otherFilters');\r\nrequire('./adultCommunities');\r\n","import { searchParametersActions, selectBrand, selectBrandFilterContext } from 'features/searchResultsFacets';\r\nimport { map, distinctUntilChanged, filter, fromEvent, skip } from 'rxjs';\r\n\r\nimport { store, store$ } from '@redux/store';\r\n\r\nconst selectContainer = document.querySelector('[data-builders-filter]');\r\nconst selectUserChange$ = fromEvent(selectContainer, 'change');\r\n\r\n/**\r\n * Here we manage when the user modify the select UI element.\r\n */\r\nselectUserChange$.subscribe((event) => {\r\n const selectElement = event.target;\r\n const builderId = selectElement.value;\r\n const builderName = builderId ? selectElement.options[selectElement.selectedIndex].text : '';\r\n const brand = { name: builderName, id: builderId };\r\n store.dispatch(searchParametersActions.fetchBrandId({ brand }));\r\n});\r\n\r\n/**\r\n * Function used to clear all the options in a select, with the exception of the first option\r\n */\r\nfunction clearSelectOptions(){\r\n for (let index = selectContainer.options.length - 1; index > 0; index -= 1) {\r\n selectContainer.remove(index);\r\n }\r\n}\r\n\r\n/**\r\n * Function used to replace all the options in a select, with the exception of the first option\r\n * @param {Array} options All the options available.\r\n */\r\nfunction replaceOptionsInSelect(data) {\r\n const { brands, brandId } = data;\r\n if (brands) {\r\n \r\n clearSelectOptions();\r\n\r\n // Add new options\r\n brands.forEach((option) => {\r\n const optionElement = document.createElement('option');\r\n optionElement.value = option.Id;\r\n optionElement.text = option.Name;\r\n selectContainer.add(optionElement);\r\n\r\n if(option.Id === Number(brandId)) {\r\n optionElement.selected = true;\r\n }\r\n });\r\n }\r\n}\r\n\r\nconst onBuilderChange$ = store$.pipe(map(selectBrand), filter(Boolean), distinctUntilChanged());\r\nonBuilderChange$.subscribe((brand) => {\r\n const { brandId } = brand;\r\n\r\n const allBuildersOption = selectContainer.children[0];\r\n const selectedItem = selectContainer.querySelector(`[value=\"${brandId}\"]`) || allBuildersOption;\r\n\r\n selectedItem.selected = true;\r\n});\r\n\r\nconst onResultLoad$ = store$.pipe(map(selectBrandFilterContext), filter(Boolean), distinctUntilChanged(), skip(1));\r\nonResultLoad$.subscribe(replaceOptionsInSelect);\r\n","import { store } from '@redux/store';\r\nimport SortType from '../enums/sortType';\r\nimport { facetsSelector } from '../redux/selectors';\r\nimport ClearFilters from './clearFilters';\r\n\r\nconst clearButton = document.querySelector('[data-clear-filters]');\r\nconst clearFilters = new ClearFilters(clearButton);\r\n\r\n/**\r\n * toggle the visibility of the clear all button\r\n * it should be hidden when no filter is applied, and be shown when there is 1 or more filters applied.\r\n * @param {Array} appliedFacets List of applied facets.\r\n */\r\nconst toggleClearAllButton = (appliedFacets) => {\r\n const facetsValues = facetsSelector(store.getState());\r\n const ignoredSorts = [SortType.CommunityId.toString()];\r\n\r\n if (appliedFacets.length > 0 &&\r\n !(appliedFacets.length === 1 && appliedFacets[0] === 'sort' &&\r\n ignoredSorts.includes(facetsValues?.sort))) {\r\n clearButton.removeAttribute('disabled');\r\n } else {\r\n clearButton.setAttribute('disabled', '');\r\n }\r\n};\r\n\r\n// subscribe to the observable and call the toggleClearAllButton function\r\nclearFilters.onFacetsApplied$.subscribe(toggleClearAllButton);","import { store, store$ } from '@redux/store';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { map, filter, distinctUntilChanged } from 'rxjs';\r\nimport { selectAppliedFacets } from '../redux/selectors';\r\n\r\nexport default class ClearFilters {\r\n constructor(buttonElement) {\r\n \r\n buttonElement.addEventListener('click', () => {\r\n store.dispatch(searchParametersActions.clearFilters());\r\n });\r\n \r\n this.onFacetsApplied$ = store$.pipe(map(selectAppliedFacets), filter(Boolean), distinctUntilChanged());\r\n }\r\n}\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport CheckboxGroup from '@components/checkbox';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { communityAmenitiesSelector } from '../redux/selectors';\r\n\r\nconst select = document.querySelector('[data-amenities-group]');\r\nconst natureAreasElement = select.querySelector('[data-nature-areas]');\r\nconst poolElement = select.querySelector('[data-pool]');\r\nconst golfCourseElement = select.querySelector('[data-golf-couse]');\r\nconst greenElement = select.querySelector('[data-green]');\r\nconst sportFacilitiesElement = select.querySelector('[data-sport-facilities]');\r\nconst parksElement = select.querySelector('[data-parks]');\r\nconst viewsElement = select.querySelector('[data-views]');\r\nconst waterfrontElement = select.querySelector('[data-waterfront]');\r\nconst gatedCommunityElement = select.querySelector('[data-gated-community]');\r\nconst checkboxGroup = new CheckboxGroup(select);\r\nconst amenities$ = checkboxGroup.getObservable();\r\ncheckboxGroup.setSelector(communityAmenitiesSelector);\r\n\r\nconst setValue = (amenities) => {\r\n const { natureAreas, pool, golfCourse, green, sportsFacilities, parks, views, waterfront, gatedCommunity } =\r\n amenities;\r\n natureAreasElement.checked = natureAreas || false;\r\n poolElement.checked = pool || false;\r\n golfCourseElement.checked = golfCourse || false;\r\n greenElement.checked = green || false;\r\n sportFacilitiesElement.checked = sportsFacilities || false;\r\n parksElement.checked = parks || false;\r\n viewsElement.checked = views || false;\r\n waterfrontElement.checked = waterfront || false;\r\n gatedCommunityElement.checked = gatedCommunity || false;\r\n};\r\n\r\namenities$.subscribe((amenities) => {\r\n const payload = {};\r\n\r\n amenities.forEach((amenity) => {\r\n payload[amenity] = true;\r\n });\r\n\r\n store.dispatch(searchParametersActions.fetchAmenities(payload));\r\n});\r\n\r\nstore$.pipe(map(communityAmenitiesSelector), distinctUntilChanged()).subscribe(setValue);\r\n","/**\r\n * This component handles the logic related to the multi select HTML element in advanced filters\r\n * in charge of manage information about marketing status filter.\r\n * Interactions with the store, specifically with the marketing status property of the search\r\n * parameters slice, should be placed here.\r\n * Also, code here any logic related to the bahavior of the multi select element for marketing\r\n * status filtering.\r\n */\r\n\r\nimport CheckboxGroup from '@components/checkbox';\r\nimport Panel from '@components/panel';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map, tap, withLatestFrom } from 'rxjs';\r\nimport { searchParametersSlice } from '../redux/slices';\r\nimport { selectMarketingStatus } from '../redux/selectors';\r\n\r\nconst { actions } = searchParametersSlice;\r\n\r\nconst container = document.querySelector('[data-community-status-panel]');\r\nconst marketingStatusListContainer = container.querySelector('[data-group]');\r\nconst labelTextContainer = container.querySelector('[data-label-text]');\r\nconst allMarketingStatusOption = marketingStatusListContainer.querySelector('[data-default-all-status]');\r\n\r\n/**\r\n * The observable to track changes in the multi select element for marketing status.\r\n */\r\nconst selectedOptions$ = new CheckboxGroup(marketingStatusListContainer).getObservable();\r\n\r\n(() => new Panel({ container }))();\r\n\r\n/**\r\n * dispatchMarketingStatus function will take the marketingStatus argument\r\n * and dispatch the fetchMarketingStatus to store it.\r\n * @param {string} marketingStatus is a comma separated string representing the selected marketing status.\r\n */\r\nconst dispatchMarketingStatus = (marketingStatus) => store.dispatch(actions.fetchMarketingStatus(marketingStatus));\r\n\r\n/**\r\n * updateSelectedStatus function will update the marketing status multi select\r\n * HTML element depending in the informacion retrieved from the store related\r\n * to marketing statuses selected.\r\n * @param {Array} selectedStatuses to represent visually in the multi select.\r\n */\r\nconst updateSelectedStatus = (selectedStatuses) => {\r\n const allOptionInputs = marketingStatusListContainer.querySelectorAll('input[type=\"checkbox\"]');\r\n allOptionInputs.forEach((option) => {\r\n if (selectedStatuses.includes(option.value)) {\r\n option.checked = true;\r\n } else {\r\n option.checked = false;\r\n }\r\n option.parentElement.classList.toggle('nhs-c-dropdown__option--active', option.checked);\r\n });\r\n\r\n allMarketingStatusOption.checked = selectedStatuses.length === 0;\r\n allMarketingStatusOption.parentElement.classList.toggle(\r\n 'nhs-c-dropdown__option--active',\r\n allMarketingStatusOption.checked\r\n );\r\n labelTextContainer.classList.toggle('nhs-c-select-button--active', !allMarketingStatusOption.checked);\r\n};\r\n\r\n/**\r\n * updateCommunityStatusLabel function will update the label of the marketing status dropdown to\r\n * reflect the amount of selected options.\r\n * @param {Number} selectedCommunityStatusNumber Community Status selected amount.\r\n */\r\nconst updateCommunityStatusLabel = (selectedMarketingStatusNumber) => {\r\n if (selectedMarketingStatusNumber === 0) {\r\n labelTextContainer.innerText = labelTextContainer.dataset.defaultText;\r\n return;\r\n }\r\n\r\n labelTextContainer.innerText = `${selectedMarketingStatusNumber} Selected`;\r\n};\r\n\r\n/**\r\n * handleMarketingStatusChanges function will invoke functions in charge\r\n * of updating the multi select for marketing status to reflect store information.\r\n * @param {Array} selectedStatuses to represent visually in the multi select.\r\n */\r\nconst handleMarketingStatusChanges = (marketingStatuses) => {\r\n updateCommunityStatusLabel(marketingStatuses.length);\r\n updateSelectedStatus(marketingStatuses);\r\n};\r\n\r\n/**\r\n * onMarketingStatusChanged$ will emit a value every time marketing status string\r\n * changes from the search parameters slice in store.\r\n */\r\nconst onMarketingStatusChanged$ = store$.pipe(\r\n map(selectMarketingStatus),\r\n distinctUntilChanged(),\r\n map((statuses) => (statuses && statuses !== '' ? statuses?.split(',') : []))\r\n);\r\n\r\n/**\r\n * onSelectedMarketingStatus$ will emita a value every time the multi select for\r\n * marketing status changes in the UI.\r\n */\r\nconst onSelectedMarketingStatus$ = selectedOptions$.pipe(\r\n withLatestFrom(onMarketingStatusChanged$),\r\n map(([selectedOptions, marketingStatuses]) => {\r\n const shouldClearAll = marketingStatuses.length !== 0 && selectedOptions.includes(allMarketingStatusOption.value);\r\n return shouldClearAll\r\n ? ''\r\n : selectedOptions.filter((option) => option !== allMarketingStatusOption.value).join(',');\r\n }),\r\n tap((selectedOptions) => {\r\n if (selectedOptions === '') {\r\n allMarketingStatusOption.checked = true;\r\n }\r\n })\r\n);\r\n\r\nonSelectedMarketingStatus$.subscribe(dispatchMarketingStatus);\r\nonMarketingStatusChanged$.subscribe(handleMarketingStatusChanges);\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectGarages } from '../redux/selectors';\r\n\r\nconst select = document.querySelector('[data-garages-filter]');\r\nconst garages$ = new Select(select).getObservable();\r\nconst setValue = (value) => {\r\n select.value = value || 0;\r\n};\r\n\r\ngarages$.subscribe((value) => {\r\n store.dispatch(searchParametersActions.fetchGarages(value));\r\n});\r\n\r\nstore$.pipe(map(selectGarages), distinctUntilChanged()).subscribe(setValue);\r\n","export default class HousingType {\r\n static get DefaultHousingType(){\r\n return this.getInstance('defaultHousingType');\r\n }\r\n\r\n static get SingleFamily() {\r\n return this.getInstance('singleFamily');\r\n }\r\n\r\n static get Custom() {\r\n return this.getInstance('custom');\r\n }\r\n\r\n static get Luxury() {\r\n return this.getInstance('luxury');\r\n }\r\n\r\n static get CondosAndTownHomes() {\r\n return this.getInstance('condosAndTownHomes');\r\n }\r\n\r\n static get Manufactured() {\r\n return this.getInstance('manufactured');\r\n }\r\n\r\n static get ModelHomes() {\r\n return this.getInstance('modelHomes');\r\n }\r\n\r\n static get Redirect() {\r\n return this.getInstance('redirect');\r\n }\r\n\r\n static fromKey(key) {\r\n const formTypeMap = {\r\n singleFamily: HousingType.SingleFamily,\r\n custom: HousingType.Custom,\r\n luxury: HousingType.Luxury,\r\n condosAndTownHomes: HousingType.CondosAndTownHomes,\r\n manufactured: HousingType.Manufactured,\r\n modelHomes: HousingType.ModelHomes,\r\n defaultHousingType: HousingType.DefaultHousingType,\r\n };\r\n return formTypeMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new HousingType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(HousingType, 'instances', { value: {} });\r\n","import SingleFamilyHousingType from \"../components/singleFamilyHousingType\";\r\nimport CustomHousingType from \"../components/customHousingType\";\r\nimport HousingType from \"../enums/housingType\";\r\nimport LuxuryHousingType from \"../components/luxuryHousingType\";\r\nimport CondoAndTownHomesHousingType from \"../components/condosAndTownHomesHousingType\";\r\nimport ManufacturedHousingType from \"../components/manufacturedHousingType\";\r\nimport ModelHomeHousingType from \"../components/modelHomeHousingType\";\r\nimport DefaultHousingType from \"../components/defaultHousingType\";\r\n\r\nconst housingTypeConstructors = new Map();\r\n\r\nhousingTypeConstructors.set(HousingType.SingleFamily.toString(), SingleFamilyHousingType);\r\nhousingTypeConstructors.set(HousingType.Custom.toString(), CustomHousingType);\r\nhousingTypeConstructors.set(HousingType.Luxury.toString(), LuxuryHousingType);\r\nhousingTypeConstructors.set(HousingType.CondosAndTownHomes.toString(), CondoAndTownHomesHousingType);\r\nhousingTypeConstructors.set(HousingType.Manufactured.toString(), ManufacturedHousingType);\r\nhousingTypeConstructors.set(HousingType.ModelHomes.toString(), ModelHomeHousingType);\r\nhousingTypeConstructors.set(HousingType.DefaultHousingType.toString(), DefaultHousingType);\r\n\r\n/**\r\n * Returns the class constructor to create a housing type.\r\n *\r\n * @param housingTypeName - The name of the hosuing type requested.\r\n */\r\nexport default (housingTypeName) => {\r\n const generator = housingTypeConstructors.get(housingTypeName);\r\n\r\n if (!generator) {\r\n return null;\r\n }\r\n\r\n return new generator.prototype.constructor();\r\n};\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectProductAndResultType, selectSingleFamily } from '../redux/selectors';\r\nimport getDefaultProductType from '../services/productTypeService';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class SingleFamilyHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"singleFamily\"]';\r\n store$.pipe(map(selectSingleFamily), distinctUntilChanged()).subscribe(this.onSingleFamilyChange.bind(this));\r\n\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductAndResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchSingleFamily action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchSingleFamily(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of single family box.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of this Housing Box.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n singleFamily: this.singleFamilyToApply,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function updates the product type to apply based on the selected product and result type.\r\n * @param productAndResultType - It represents the object with the product and result type.\r\n */\r\n onProductAndResultTypeChange(productAndResultType) {\r\n const { resultType, productType} = productAndResultType;\r\n this.productTypeToApply = getDefaultProductType(productType, resultType);\r\n this.resultTypeToApply = getDefaultResultType(resultType);\r\n }\r\n\r\n /**\r\n * The function toggles a box based on the value of the singleFamily parameter.\r\n * @param singleFamily - The singleFamily parameter is a boolean value that represents whether the\r\n * property is a single-family home or not.\r\n */\r\n onSingleFamilyChange(singleFamily) {\r\n this.singleFamilyToApply = !singleFamily;\r\n this.toggleSelect(singleFamily);\r\n }\r\n\r\n /**\r\n * The select function adds or removes the 'active' class from a node based on the value of the\r\n * singleFamily property.\r\n */\r\n toggleSelect(singleFamily) {\r\n const node = this.getNode();\r\n if (singleFamily) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectProductAndResultType } from '../redux/selectors';\r\nimport ProductType from '../enums/productType';\r\nimport ResultType from '../enums/resultType';\r\nimport { searchParametersSlice } from '../redux/slices';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport getDefaultProductType from '../services/productTypeService';\r\n\r\nexport default class CustomHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"custom\"]';\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductAndResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchCustom action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchCustom(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of luxury box.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of this Housing Box.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function `onProductAndResultTypeChange` checks the `resultType` and `productType` to be able to update\r\n * the result and product type that the box should apply.\r\n * @param productAndResultType - It represents the object with the product and result type.\r\n */\r\n onProductAndResultTypeChange(productAndResultType) {\r\n const { productType, resultType } = productAndResultType;\r\n this.toggleBox(productType);\r\n\r\n // We have to open the home result type when this button is clicked. In other words, this is when the button\r\n // is not actived and it was clicked, so we should open the Custom Homes search.\r\n if (productType !== ProductType.Custom.toString() && productType !== ProductType.BuildOnYourLot.toString()) {\r\n this.resultTypeToApply = ResultType.Homes.toString();\r\n this.productTypeToApply = ProductType.Custom.toString();\r\n return;\r\n }\r\n\r\n // Otherwise, it means the custom/build on your lot search are actived, so if the button is clicked, we should\r\n // use the default result type when button is clicked again to deactivate the custom/build on your lot search.\r\n this.resultTypeToApply = getDefaultResultType(resultType);\r\n this.productTypeToApply = getDefaultProductType(productType, resultType);\r\n }\r\n\r\n toggleBox(productType) {\r\n const node = this.getNode();\r\n if (productType === ProductType.BuildOnYourLot.toString() || productType === ProductType.Custom.toString()) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectLuxury, selectProductAndResultType } from '../redux/selectors';\r\nimport getDefaultProductType from '../services/productTypeService';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class LuxuryHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"luxury\"]';\r\n store$.pipe(map(selectLuxury), distinctUntilChanged()).subscribe(this.onLuxuryChange.bind(this));\r\n\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductAndResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchLuxury action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchLuxury(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of luxury box.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of this Housing Box.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n luxury: this.luxuryToApply,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function updates the product and result type to apply based on the selected product and result type.\r\n * @param productAndResultType - It represents the object with the product and result type.\r\n */\r\n onProductAndResultTypeChange(productAndResultType) {\r\n const { resultType, productType} = productAndResultType;\r\n this.productTypeToApply = getDefaultProductType(productType, resultType);\r\n this.resultTypeToApply = getDefaultResultType(resultType);\r\n }\r\n\r\n /**\r\n * The function \"onLuxuryChange\" sets the \"luxury\" property to the provided value (or false if no\r\n * value is provided) and then calls the \"toggleBox\" function.\r\n * @param luxury - The \"luxury\" parameter is a boolean value that determines whether the luxury\r\n * feature should be enabled or disabled.\r\n */\r\n onLuxuryChange(luxury) {\r\n this.luxuryToApply = !luxury;\r\n this.toggleBox(luxury);\r\n }\r\n\r\n /**\r\n * The toggleBox function adds or removes the 'active' class from a node based on the value of the\r\n * 'luxury' property.\r\n */\r\n toggleBox(luxury) {\r\n const node = this.getNode();\r\n if (luxury) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectCondosAndTownHomes, selectProductAndResultType } from '../redux/selectors';\r\nimport getDefaultProductType from '../services/productTypeService';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class CondoAndTownHomesHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"condosAndTownHomes\"]';\r\n store$\r\n .pipe(map(selectCondosAndTownHomes), distinctUntilChanged())\r\n .subscribe(this.onCondosAndTownHomesChange.bind(this));\r\n\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductAndResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchCondosAndTownHomes action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchCondosAndTownHomes(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of condo and townhomes box.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommandProperty: Gets the search command property of this Housing Box.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n condosAndTownHomes: this.condosAndTownHomesToApply,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function updates the product and result type to apply based on the selected product and result type.\r\n * @param productAndResultType - It represents the object with the product and result type.\r\n */\r\n onProductAndResultTypeChange(productAndResultType) {\r\n const { resultType, productType} = productAndResultType;\r\n this.productTypeToApply = getDefaultProductType(productType, resultType);\r\n this.resultTypeToApply = getDefaultResultType(resultType);\r\n }\r\n\r\n onCondosAndTownHomesChange(condosAndTownHomes) {\r\n this.condosAndTownHomesToApply = !condosAndTownHomes;\r\n this.toggleBox(condosAndTownHomes);\r\n }\r\n\r\n toggleBox(condosAndTownHomes) {\r\n const node = this.getNode();\r\n if (condosAndTownHomes) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectProductAndResultType } from '../redux/selectors';\r\nimport ProductType from '../enums/productType';\r\nimport ResultType from '../enums/resultType';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class ManufacturedHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"manufactured\"]';\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductOrResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchManufactured action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchManufactured(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of luxury box.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of this Housing Box.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * Updates the value of productType and resultType based on the input\r\n * \"typeParameters\".\r\n * @param typeParameters - The productType and resultType parameters are a strings \r\n * that represents the values of the type of product and/or result types.\r\n */\r\n onProductOrResultTypeChange(typeParameters) {\r\n const { productType, resultType } = typeParameters;\r\n switch (true) {\r\n case productType === ProductType.Manufactured.toString() && resultType === ResultType.Homes.toString():\r\n this.productTypeToApply = ProductType.Homes.toString();\r\n this.resultTypeToApply = ResultType.Homes.toString();\r\n break;\r\n\r\n case productType === ProductType.Manufactured.toString() && resultType === ResultType.Locations.toString():\r\n this.productTypeToApply = ProductType.Communities.toString();\r\n this.resultTypeToApply = ResultType.Communities.toString();\r\n break;\r\n\r\n default:\r\n this.productTypeToApply = ProductType.Manufactured.toString();\r\n this.resultTypeToApply = ResultType.Homes.toString();\r\n }\r\n this.toggleSelect(productType);\r\n }\r\n\r\n toggleSelect(productType) {\r\n const node = this.getNode();\r\n if (productType === ProductType.Manufactured.toString()) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectHomeStatus } from '../redux/selectors';\r\nimport { searchParametersSlice } from '../redux/slices';\r\nimport SpecStatus from '../enums/specStatus';\r\nimport ProductType from '../enums/productType';\r\nimport ResultType from '../enums/resultType';\r\nimport { hasModelHome } from '../services/homeStatusValidator';\r\n\r\nexport default class ModelHomeHousingType {\r\n constructor() {\r\n this.selector = '[data-housing-type=\"modelHomes\"]';\r\n this.productType = ProductType.Homes.toString();\r\n this.resultType = ResultType.Homes.toString();\r\n\r\n store$.pipe(map(selectHomeStatus), distinctUntilChanged()).subscribe(this.onModelHomesChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a fetchModelHome action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.fetchModelHome(payload));\r\n }\r\n\r\n /**\r\n * Gets the node element of Model Home Housing Type.\r\n * @returns {Node} element.\r\n */\r\n getNode() {\r\n return document.querySelector(this.selector);\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of this Housing Type.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n homeStatus: SpecStatus.Model.toString(),\r\n productType: this.productType,\r\n resultType: this.resultType,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function select the option based on the value of the model home parameter.\r\n * @param homeStatus - The modelHomes parameter is a string value that represents\r\n * the current home status selected from the store.\r\n */\r\n onModelHomesChange(homeStatus) {\r\n this.toggleSelect(homeStatus);\r\n }\r\n \r\n /**\r\n * The select function adds or removes the 'active' class from a node based on the value of the\r\n * modelHomes property.\r\n */\r\n toggleSelect(homeStatus) {\r\n const node = this.getNode();\r\n if (hasModelHome(homeStatus)) {\r\n node.selected = true;\r\n } else {\r\n node.selected = false;\r\n }\r\n }\r\n}\r\n","import { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectProductAndResultType } from '../redux/selectors';\r\nimport getDefaultProductType from '../services/productTypeService';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class DefaultHousingType {\r\n constructor() {\r\n store$.pipe(map(selectProductAndResultType), distinctUntilChanged())\r\n .subscribe(this.onProductAndResultTypeChange.bind(this));\r\n }\r\n\r\n /**\r\n * The dispatchAction function dispatches a default housing type action with the payload obtained from the\r\n * getSearchCommands function.\r\n */\r\n dispatchFetchResultAction() {\r\n const payload = this.getSearchCommands();\r\n store.dispatch(searchParametersSlice.actions.allOptions(payload));\r\n }\r\n\r\n /**\r\n * getSearchCommands: Gets the search command property of the default Housing type.\r\n * @returns The search command property string.\r\n */\r\n getSearchCommands() {\r\n const searchCommandPropertyStructure = {\r\n productType: this.productTypeToApply,\r\n resultType: this.resultTypeToApply,\r\n homeStatus: null,\r\n };\r\n\r\n return searchCommandPropertyStructure;\r\n }\r\n\r\n /**\r\n * The function updates the product type to apply based on the selected product and result type.\r\n * @param productAndResultType - It represents the object with the product and result type.\r\n */\r\n onProductAndResultTypeChange(productAndResultType) {\r\n const { resultType, productType} = productAndResultType;\r\n this.productTypeToApply = getDefaultProductType(productType, resultType);\r\n this.resultTypeToApply = getDefaultResultType(resultType);\r\n }\r\n}\r\n","import housingTypeConstructor from './housingTypeConstructor';\r\n\r\n/**\r\n * The function `getHousingType` takes an array of housing elements and returns an object containing\r\n * housing types, where each option is associated with a housing type.\r\n * @param housingElements - The `housingElements` parameter is an array of DOM elements representing\r\n * housing boxes. Each element should have a `data-housing-type` attribute that specifies the type of\r\n * housing.\r\n * @returns an object called `housingBoxes` which contains housing types as keys and the result of\r\n * calling the `housingBoxConstructor` function with the housing type as the argument as values.\r\n */\r\nfunction getHousingType(housingElements) {\r\n const housingTypeOptions = {};\r\n housingElements.forEach((option) => {\r\n const housingType = option.dataset.housingType;\r\n housingTypeOptions[housingType] = housingTypeConstructor(housingType);\r\n });\r\n\r\n return housingTypeOptions;\r\n}\r\n\r\nexport default getHousingType;\r\n","import { fromEvent } from 'rxjs';\r\nimport getHousingType from '../services/housingTypeService';\r\n\r\nconst container = document.querySelector('[data-housing-select]');\r\nconst selectChange$ = fromEvent(container, 'change');\r\nconst housingElements = [...container.querySelectorAll('[data-housing-type]')];\r\nconst housingTypeOptions = getHousingType(housingElements);\r\n\r\n/**\r\n * Handles when the housing type select dropdown changes.\r\n */\r\nselectChange$.subscribe((event) => {\r\n const selectElement = event.target;\r\n const housingType = selectElement.value;\r\n const housingOption = housingTypeOptions[housingType];\r\n housingOption.dispatchFetchResultAction(); \r\n});\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectLivingAreas } from '../redux/selectors';\r\n\r\nconst select = document.querySelector('[data-living-areas-filter]');\r\nconst livingAreas$ = new Select(select).getObservable();\r\nconst setValue = (value) => {\r\n select.value = value || 0;\r\n};\r\n\r\nlivingAreas$.subscribe((value) => {\r\n store.dispatch(searchParametersActions.fetchLivingAreas(value));\r\n});\r\n\r\nstore$.pipe(map(selectLivingAreas), distinctUntilChanged()).subscribe(setValue);\r\n","import { store, store$ } from '@redux/store';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, fromEvent, map } from 'rxjs';\r\nimport OtherFiltersType from '../enums/otherFiltersType';\r\n\r\nconst container = document.querySelector('[data-other-filters]');\r\nconst otherFilterValue$ = fromEvent(container, 'change');\r\n\r\notherFilterValue$.subscribe((event) => {\r\n const target = event?.target;\r\n const value = target?.value;\r\n switch (value) {\r\n case OtherFiltersType.HotDeals.toString():\r\n store.dispatch(searchParametersActions.fetchConsumerPromos(target.checked));\r\n break;\r\n case OtherFiltersType.PriceReduction.toString():\r\n store.dispatch(searchParametersActions.fetchPriceReduction(target.checked));\r\n break;\r\n case OtherFiltersType.Reviews.toString():\r\n store.dispatch(searchParametersActions.fetchBuilderReviews(target.checked));\r\n break;\r\n case OtherFiltersType.HomeOwnersAssociationFee.toString():\r\n store.dispatch(searchParametersActions.fetchHomeOwnersAssociationFee(target.checked));\r\n break;\r\n default:\r\n break;\r\n }\r\n});\r\n\r\nstore$\r\n .pipe(\r\n map((lastState) => {\r\n const otherFilters = {\r\n reviews: lastState.searchParameters?.facts?.builderReviews === true,\r\n hotDeals: lastState.searchParameters?.facts?.consumerPromos,\r\n priceReduction: lastState.searchParameters?.facts?.priceReduction,\r\n homeOwnersAssociationFee: lastState.searchParameters?.facts?.hasHomeOwnersAssociationFee,\r\n };\r\n return otherFilters;\r\n }),\r\n distinctUntilChanged()\r\n )\r\n .subscribe((otherFilters) => {\r\n const filterNames = Object.keys(otherFilters);\r\n filterNames.forEach((filter) => {\r\n const filterCheckbox = container.querySelector(`[value=\"${filter}\"]`);\r\n filterCheckbox.checked = otherFilters[filter];\r\n });\r\n });\r\n","import { store, store$ } from '@redux/store';\r\nimport { debounceTime, distinctUntilChanged, filter, fromEventPattern, map } from 'rxjs';\r\nimport noUiSlider from 'nouislider';\r\nimport { searchParametersSlice } from '../redux/slices';\r\nimport { selectPrice } from '../redux/selectors';\r\n\r\nexport default class PriceDualSlider {\r\n constructor(container) {\r\n this.onPriceChange$ = store$.pipe(filter(selectPrice), map(selectPrice), distinctUntilChanged());\r\n\r\n // The price range for the slider will be from $0 until $1.5M.\r\n this.maximumSliderValue = 1500000;\r\n this.minimumSliderValue = 0;\r\n this.highPriceLimit = 1500000;\r\n\r\n // Here we have to define the initial al last value of the slider, which is the min and max values.\r\n // Also, we have to define the slider step value that we have to use according to the selected value.\r\n // The business rule is from 0 to 500k, we have to use a 50k step, after 500k we have to use 100k step.\r\n this.rangeConfiguration = {\r\n min: [this.minimumSliderValue, 50000],\r\n '33.3%': [500000, 100000],\r\n max: [this.maximumSliderValue],\r\n };\r\n\r\n this.setDualRangeSlider(container);\r\n this.dualRangeSliderValueChange$.subscribe(PriceDualSlider.priceChangeHandler);\r\n this.onPriceChange$.subscribe(({ minimumPrice, maximumPrice }) =>\r\n this.updateValueSliders({\r\n minimumValue: minimumPrice || this.minimumSliderValue,\r\n maximumValue: maximumPrice || this.maximumSliderValue,\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * setDualRangeSlider: Configures all the initial code to make the slider works.\r\n * @param {HTMLElement} container Element where all the HTML slider elements will be.\r\n */\r\n setDualRangeSlider(container) {\r\n this.minimumSliderLabel = container.querySelector('[data-minimum-slider-label]');\r\n this.maximumSliderLabel = container.querySelector('[data-maximum-slider-label]');\r\n\r\n this.slider = container.querySelector('[data-slider]');\r\n\r\n this.dualRangeSlider = noUiSlider.create(this.slider, {\r\n start: [this.minimumSliderValue, this.maximumSliderValue],\r\n connect: true,\r\n range: this.rangeConfiguration,\r\n cssPrefix: 'nhs-c-slider-control__',\r\n });\r\n\r\n this.setInputEvent();\r\n this.setChangeEvents();\r\n this.setQaDataAttributeTag();\r\n this.updateSliderLabels();\r\n }\r\n\r\n /**\r\n * updateValueSliders: Updates the slider values from an external action.\r\n * @param {Object} values Object with new values.\r\n */\r\n updateValueSliders(values) {\r\n const { minimumValue, maximumValue } = values;\r\n this.slider.noUiSlider.set([minimumValue, maximumValue]);\r\n this.updateSliders();\r\n }\r\n\r\n /**\r\n * getLabel: Gets the label to use for the input depending on the value.\r\n * @param {Number} value Number value to convert.\r\n * @returns A string with the formatted number.\r\n * @example XXXk if under $999k, returns $X.XM if over $999k.\r\n */\r\n static getLabel(value) {\r\n if (value < 999000) {\r\n return `$${value / 1000}k`;\r\n }\r\n return `$${value / 1000000}M`;\r\n }\r\n\r\n /**\r\n * getSliderValues: Gets the actual slider values.\r\n * @returns An object with the current slider values.\r\n */\r\n getSliderValues() {\r\n const minimumIndex = 0;\r\n const maximumIndex = 1;\r\n const sliderValues = this.dualRangeSlider.get(true);\r\n const minimumSliderValue = Math.ceil(sliderValues[minimumIndex]);\r\n const maximumSliderValue = Math.ceil(sliderValues[maximumIndex]);\r\n const highPriceLimit = this.highPriceLimit;\r\n\r\n return {\r\n minimumSliderValue,\r\n maximumSliderValue,\r\n highPriceLimit,\r\n };\r\n }\r\n\r\n /**\r\n * updateSliderLabels: Updates the label for each slider.\r\n */\r\n updateSliderLabels() {\r\n const { minimumSliderValue, maximumSliderValue } = this.getSliderValues();\r\n if (minimumSliderValue === this.minimumSliderValue) {\r\n this.minimumSliderLabel.innerHTML = 'Min';\r\n } else {\r\n this.minimumSliderLabel.innerHTML = PriceDualSlider.getLabel(minimumSliderValue);\r\n }\r\n\r\n if (maximumSliderValue === this.maximumSliderValue) {\r\n this.maximumSliderLabel.innerHTML = 'Max';\r\n } else {\r\n this.maximumSliderLabel.innerHTML = PriceDualSlider.getLabel(maximumSliderValue);\r\n }\r\n }\r\n\r\n /**\r\n * setChangeEvents: Configures the change event that the dual range slider should manage.\r\n * It refers when the user stopped moving the slider.\r\n */\r\n setChangeEvents() {\r\n this.dualRangeSliderValueChange$ = fromEventPattern(this.getSlideEvent.bind(this)).pipe(\r\n map(this.getSliderValues.bind(this)),\r\n debounceTime(500),\r\n distinctUntilChanged()\r\n );\r\n }\r\n\r\n /**\r\n * setQaDataAttributeTag: Adds data QA to price slider\r\n */\r\n setQaDataAttributeTag() {\r\n this.slider.querySelector('.nhs-c-slider-control__handle-lower').dataset.qa = 'Minimum_price_slider';\r\n this.slider.querySelector('.nhs-c-slider-control__handle-upper').dataset.qa = 'Maximum_price_slider';\r\n }\r\n\r\n /**\r\n * getSlideEvent: Gets a slide event of the slider. It is called slide because it is as the API uses it.\r\n * It is very similar to the input event, where it is triggered when the user moved a slider.\r\n * @param {Function} handler It is a callback that will be used when the slide event is triggered.\r\n * @returns An event that relates to the slide action.\r\n */\r\n getSlideEvent(handler) {\r\n return this.slider.noUiSlider.on('slide', handler);\r\n }\r\n\r\n /**\r\n * updateSliders: Updates the UI for the component.\r\n */\r\n updateSliders() {\r\n this.updateSliderLabels();\r\n }\r\n\r\n /**\r\n * setInputEvent: Configures the input events that the dual range slider should manage.\r\n * It refers each time when the user moves the slider.\r\n */\r\n setInputEvent() {\r\n // Those events are to track actively the movement of the sliders\r\n fromEventPattern(this.getSlideEvent.bind(this)).subscribe(this.updateSliders.bind(this));\r\n }\r\n\r\n /**\r\n * priceChangeHandler: Handles when the price has changed on the store.\r\n * @param {Object} sliderValues An object with the value to execute the price action.\r\n */\r\n static priceChangeHandler(sliderValues) {\r\n const { minimumSliderValue, maximumSliderValue, highPriceLimit } = sliderValues;\r\n\r\n store.dispatch(\r\n searchParametersSlice.actions.fetchPrice({\r\n minimumPrice: minimumSliderValue,\r\n maximumPrice: maximumSliderValue,\r\n maximumPriceLimit: highPriceLimit,\r\n })\r\n );\r\n }\r\n}\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectPrimaryBedroom } from '../redux/selectors';\r\n\r\nconst select = document.querySelector('[data-primary-bedroom-filter]');\r\nconst primaryBedroom$ = new Select(select).getObservable();\r\nconst setValue = (value) => {\r\n select.value = value || 0;\r\n};\r\n\r\nprimaryBedroom$.subscribe((value) => {\r\n store.dispatch(searchParametersActions.fetchPrimaryBedroom(value));\r\n});\r\n\r\nstore$.pipe(map(selectPrimaryBedroom), distinctUntilChanged()).subscribe(setValue);\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport CheckboxGroup from '@components/checkbox';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectRvGarage } from '../redux/selectors';\r\n\r\nconst checkbox = document.querySelector('[data-rv-garage-filter]');\r\nconst rvGarage$ = new CheckboxGroup(checkbox).getObservable();\r\nconst setValue = (value) => {\r\n checkbox.checked = value || false;\r\n};\r\n\r\nrvGarage$.subscribe((value) => {\r\n const payload = !!value.length;\r\n store.dispatch(searchParametersActions.fetchRvGarages(payload));\r\n});\r\n\r\nstore$.pipe(map(selectRvGarage), distinctUntilChanged()).subscribe(setValue);\r\n","import CheckboxGroup from '@components/checkbox';\r\nimport Panel from '@components/panel';\r\nimport { store, store$ } from '@redux/store';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\n\r\nconst container = document.querySelector('[data-schools-panel]');\r\nconst schoolListContainer = container.querySelector('[data-group]');\r\nconst labelTextContainer = container.querySelector('[data-label-text]');\r\nconst allSchoolsOption = schoolListContainer.children[0].cloneNode(true);\r\nconst schoolsSelector = (state) => state?.searchParameters?.features?.schoolDistrictIds || [];\r\nlet isAllSchoolsInactive = false;\r\n\r\n/**\r\n * createOptionElement: Creates the HTML element of an school.\r\n * @param {Object} schoolInformation Contains the name and value of the school.\r\n * @returns {HTMLElement} The HTML element of the school option.\r\n */\r\nfunction createOptionElement(schoolInformation) {\r\n const schoolId = `chk-${schoolInformation.Id}`;\r\n\r\n const optionElement = document.createElement('li');\r\n optionElement.classList.add('nhs-c-dropdown__option');\r\n optionElement.setAttribute('tabindex', 0);\r\n\r\n const inputElement = document.createElement('input');\r\n inputElement.type = 'checkbox';\r\n inputElement.id = schoolId;\r\n inputElement.value = schoolInformation.Id;\r\n inputElement.classList.add('nhs-c-input__check-box');\r\n inputElement.dataset.qa = `school-${schoolInformation.Id}`;\r\n\r\n const labelElement = document.createElement('label');\r\n labelElement.classList.add('nhs-c-dropdown__option-label');\r\n labelElement.setAttribute('for', schoolId);\r\n labelElement.innerText = schoolInformation.Name;\r\n\r\n optionElement.append(inputElement);\r\n optionElement.append(labelElement);\r\n\r\n return optionElement;\r\n}\r\n\r\n/**\r\n * setSchoolsList: Sets all the list of the current location.\r\n * @param {Array} schools List of schools.\r\n */\r\nfunction setSchoolsList(schools) {\r\n schoolListContainer.innerHTML = '';\r\n schoolListContainer.append(allSchoolsOption);\r\n schools.forEach((schoolInformation) => {\r\n const optionElement = createOptionElement(schoolInformation);\r\n schoolListContainer.append(optionElement);\r\n });\r\n}\r\n\r\n/**\r\n * updateSelectedSchool: Updates the option selected UI of the selected schools.\r\n * @param {Array} selectedSchools Selected schools list\r\n */\r\nfunction updateSelectedSchool(selectedSchools) {\r\n const defaultValue = allSchoolsOption.value;\r\n const actualDefaultOption = schoolListContainer.querySelector(`[value=\"${defaultValue}\"]`);\r\n if (isAllSchoolsInactive) {\r\n const allOptionInputs = schoolListContainer.querySelectorAll(':checked');\r\n allOptionInputs.forEach((option) => {\r\n option.checked = false;\r\n option.parentElement.classList.remove('nhs-c-dropdown__option--active');\r\n });\r\n\r\n actualDefaultOption.checked = true;\r\n actualDefaultOption.parentElement.classList.add('nhs-c-dropdown__option--active');\r\n labelTextContainer.classList.remove('nhs-c-select-button--active');\r\n\r\n return;\r\n }\r\n\r\n actualDefaultOption.parentElement.classList.remove('nhs-c-dropdown__option--active');\r\n labelTextContainer.classList.add('nhs-c-select-button--active');\r\n selectedSchools.forEach((schoolId) => {\r\n const schoolOption = schoolListContainer.querySelector(`[value=\"${schoolId}\"]`);\r\n schoolOption.checked = true;\r\n schoolOption.parentElement.classList.add('nhs-c-dropdown__option--active');\r\n });\r\n actualDefaultOption.checked = false;\r\n}\r\n\r\n/**\r\n * updateSchoolsLabel: Updates the label of the dropdown.\r\n * @param {Number} selectedSchoolsNumber Schools selected quantity.\r\n */\r\nfunction updateSchoolsLabel(selectedSchoolsNumber) {\r\n if (!selectedSchoolsNumber) {\r\n labelTextContainer.innerText = labelTextContainer.dataset.defaultText;\r\n return;\r\n }\r\n\r\n labelTextContainer.innerText = `${selectedSchoolsNumber} Selected`;\r\n}\r\n\r\n(() => new Panel({ container }))();\r\n\r\nconst selectedOptions$ = new CheckboxGroup(schoolListContainer).getObservable();\r\n\r\n/**\r\n * Here we manage the options selected to get only the schools id list that will be used.\r\n */\r\nconst selectedSchoolIds$ = selectedOptions$.pipe(\r\n // Here we are checking if the last option selected was All Schools.\r\n // If yes, we have to remove all the schools. Otherwise, we keep the same options.\r\n map((selectedOptions) => {\r\n const defaultValue = String(allSchoolsOption.value);\r\n const shouldClearAllSchools = !isAllSchoolsInactive && selectedOptions.includes(defaultValue);\r\n\r\n return selectedOptions.filter(() => !shouldClearAllSchools);\r\n }),\r\n\r\n // Here we are removing the All Schools option if it is checked.\r\n map((selectedOptions) => selectedOptions.filter((schoolId) => Number(schoolId) !== allSchoolsOption.value))\r\n);\r\n\r\n/**\r\n * Here we map the schools data into the dispatch object structure.\r\n */\r\nselectedSchoolIds$.subscribe((schoolIds) => {\r\n const payload = schoolIds.map((id) => {\r\n const schoolOption = schoolListContainer.querySelector(`label[for=\"chk-${id}\"]`);\r\n return {\r\n name: schoolOption.innerText,\r\n id,\r\n };\r\n });\r\n store.dispatch(searchParametersActions.fetchSchools(payload));\r\n});\r\n\r\nconst newSchoolDistricts$ = store$.pipe(\r\n map((state) => state?.searchParameters?.counts?.schoolDistricts),\r\n filter((value) => !!value),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst schoolDistrictIdsChange$ = store$.pipe(\r\n map((state) => state?.searchParameters?.features?.schoolDistrictIds),\r\n filter(Boolean),\r\n distinctUntilChanged()\r\n);\r\n\r\nnewSchoolDistricts$.subscribe((schools) => {\r\n const schoolsSelected = schoolsSelector(store.getState());\r\n setSchoolsList(schools);\r\n isAllSchoolsInactive = !Array.isArray(schoolsSelected) || !schoolsSelected.length;\r\n updateSelectedSchool(schoolsSelected);\r\n updateSchoolsLabel(schoolsSelected.length);\r\n});\r\nschoolDistrictIdsChange$.subscribe((selectedSchools) => {\r\n isAllSchoolsInactive = !Array.isArray(selectedSchools) || !selectedSchools.length;\r\n updateSelectedSchool(selectedSchools);\r\n updateSchoolsLabel(selectedSchools.length);\r\n});\r\n","import { searchParametersActions } from 'features/searchResultsFacets';\r\nimport Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectStories } from '../redux/selectors';\r\n\r\nconst select = document.querySelector('[data-stories-filter]');\r\nconst stories$ = new Select(select).getObservable();\r\nconst setValue = (value) => {\r\n select.value = value || 0;\r\n};\r\n\r\nstories$.subscribe((value) => {\r\n store.dispatch(searchParametersActions.fetchStories(value));\r\n});\r\n\r\nstore$.pipe(map(selectStories), distinctUntilChanged()).subscribe(setValue);\r\n","export default class LocationType {\r\n /**\r\n * This is a static method that returns a new instance of the LocationType class with the type\r\n * 'city'.\r\n * @returns A new instance of the `LocationType` class with the value of `'city'` as its parameter.\r\n */\r\n static get City() {\r\n return new LocationType('city');\r\n }\r\n\r\n/**\r\n * The above code defines a static getter function that returns a new instance of a LocationType object\r\n * with the type 'market'.\r\n * @returns A new instance of the `LocationType` class with the type `market` is being returned.\r\n */\r\n static get Market() {\r\n return new LocationType('market');\r\n }\r\n\r\n /**\r\n * The above code defines a static method that returns a new instance of a LocationType object with\r\n * the type 'rectangularArea'.\r\n * @returns A new instance of the `LocationType` class with the value `'rectangularArea'` is being\r\n * returned.\r\n */\r\n static get RectangularArea() {\r\n return new LocationType('rectangularArea');\r\n }\r\n\r\n/**\r\n * The function returns a new LocationType object with the type 'zip'.\r\n * @returns A new instance of the `LocationType` class with the argument `'zip'`.\r\n */\r\n static get Zip() {\r\n return new LocationType('zip');\r\n }\r\n\r\n /**\r\n * The function returns a new instance of a LocationType object with the type 'synthetic'.\r\n * @returns A new instance of the LocationType class with the type 'synthetic'.\r\n */\r\n static get Synthetic() {\r\n return new LocationType('syntheticGeo');\r\n }\r\n\r\n/**\r\n * The function returns a new instance of a LocationType object with the type 'county'.\r\n * @returns A new instance of the LocationType class with the type 'county'.\r\n */\r\n static get County() {\r\n return new LocationType('county');\r\n }\r\n\r\n static fromKey(key) {\r\n const locationType = {\r\n city: LocationType.City,\r\n market: LocationType.Market,\r\n rectangulararea: LocationType.RectangularArea,\r\n zip: LocationType.Zip,\r\n syntheticgeo: LocationType.Synthetic,\r\n county: LocationType.County,\r\n };\r\n return locationType[key.toLowerCase()];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * This is a toString() method in JavaScript that returns the name property of an object as a string.\r\n * @returns The `toString()` method is returning the value of the `name` property of the object.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}","export default class MoveInDate {\r\n static get OneToTwoMonths() {\r\n return new MoveInDate('1-2');\r\n }\r\n\r\n static get ThreeToSixMonths() {\r\n return new MoveInDate('3-6');\r\n }\r\n\r\n static get BuildablePlans() {\r\n return new MoveInDate(null);\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n","export default class OtherFiltersType {\r\n static get HotDeals() {\r\n return this.getInstance('hotDeals');\r\n }\r\n\r\n // This is also know as HOA fee.\r\n static get HomeOwnersAssociationFee() {\r\n return this.getInstance('homeOwnersAssociationFee');\r\n }\r\n\r\n static get PriceReduction() {\r\n return this.getInstance('priceReduction');\r\n }\r\n\r\n static get Reviews() {\r\n return this.getInstance('reviews');\r\n }\r\n\r\n static get Adult() {\r\n return this.getInstance('adult');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n hotDeals: OtherFiltersType.HotDeals,\r\n reviews: OtherFiltersType.Reviews,\r\n adult: OtherFiltersType.Adult,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new OtherFiltersType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(OtherFiltersType, 'instances', { value: {} });\r\n","export default class PlanStatus {\r\n static get AvailableNow() {\r\n return this.getInstance('A');\r\n }\r\n\r\n static get Model() {\r\n return this.getInstance('M');\r\n }\r\n\r\n static get ReadyToBuild() {\r\n return this.getInstance('R');\r\n }\r\n\r\n static get UnderConstruction() {\r\n return this.getInstance('UC');\r\n }\r\n\r\n static get HotDeals() {\r\n return this.getInstance('H');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n R: PlanStatus.ReadyToBuild,\r\n A: PlanStatus.AvailableNow,\r\n UC: PlanStatus.UnderConstruction,\r\n M: PlanStatus.Model,\r\n H: PlanStatus.HotDeals,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new PlanStatus(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(PlanStatus, 'instances', { value: {} });\r\n","export default class ProductType {\r\n static get AllProducts() {\r\n return this.getInstance('AllProducts');\r\n }\r\n\r\n static get Custom() {\r\n return this.getInstance('custom');\r\n }\r\n\r\n static get Communities() {\r\n return this.getInstance('communities');\r\n }\r\n\r\n static get Homes() {\r\n return this.getInstance('homes');\r\n }\r\n\r\n static get BuildOnYourLot() {\r\n return this.getInstance('boyl');\r\n }\r\n\r\n static get Manufactured() {\r\n return this.getInstance('manufactured');\r\n }\r\n\r\n static fromKey(key) {\r\n const productTypeMap = {\r\n allProducts: ProductType.AllProducts,\r\n custom: ProductType.Custom,\r\n communities: ProductType.Communities,\r\n homes: ProductType.Homes,\r\n boyl: ProductType.BuildOnYourLot,\r\n manufactured: ProductType.Manufactured,\r\n };\r\n\r\n return productTypeMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new ProductType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(ProductType, 'instances', { value: {} });","export default class ResultType {\r\n static get Communities() {\r\n const configuration = {\r\n cssSelectorForNativeAds: '[data-list-view-element] .result__card:not([data-is-featured-listing])',\r\n name: 'communities',\r\n };\r\n\r\n return this.getInstance('communities', configuration);\r\n }\r\n\r\n static get Homes() {\r\n const configuration = {\r\n cssSelectorForNativeAds: '[data-list-view-element] .result__card:not([data-is-featured-listing])',\r\n name: 'homes',\r\n };\r\n\r\n return this.getInstance('homes', configuration);\r\n }\r\n\r\n static get Builders() {\r\n const configuration = {\r\n cssSelectorForNativeAds:\r\n '[data-list-view-element] .result__card:not([data-is-featured-listing]):not([data-basic-card])',\r\n };\r\n\r\n return this.getInstance('builders', configuration);\r\n }\r\n\r\n static get Locations() {\r\n const configuration = {\r\n cssSelectorForNativeAds: '[data-list-view-element] .result__card:not([data-is-featured-listing])',\r\n name: 'locations',\r\n };\r\n\r\n return this.getInstance('locations', configuration);\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(name) {\r\n const statusMap = {\r\n builders: ResultType.Builders,\r\n communities: ResultType.Communities,\r\n homes: ResultType.Homes,\r\n locations: ResultType.Locations,\r\n };\r\n\r\n return statusMap[name];\r\n }\r\n\r\n /**\r\n * Gets an instance of a ResultType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the ResultType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the ResultType class that is being created.\r\n *\r\n * @returns an instance of `ResultType` that corresponds to the given `name`.\r\n */\r\n static getInstance(name, configuration) {\r\n configuration.name = name;\r\n\r\n if (!this.instances[name]) {\r\n this.instances[name] = new ResultType(configuration);\r\n }\r\n\r\n return this.instances[name];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a configuration object as a parameter and sets the name\r\n * and CSS selector for native ads properties.\r\n * @param configuration - The `configuration` parameter is an object that contains the configuration\r\n * settings for the constructor. It may contain properties such as `name` and\r\n * `cssSelectorForNativeAds`. The `name` property is a string that represents the name of the\r\n * configuration, while `cssSelectorForNativeAds` is a\r\n */\r\n constructor(configuration) {\r\n this.name = configuration.name;\r\n this.cssSelectorForNativeAds = configuration.cssSelectorForNativeAds;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(ResultType, 'instances', { value: {} });\r\n","import ResultType from \"./resultType\";\r\n\r\n/**\r\n * An enum in charge of holding SortBy information as the SortBy name\r\n * and the possible query strings values for each SortBy key.\r\n */\r\nexport default class SortType {\r\n /**\r\n * Key for city sorting. It could be from A-Z or Z-A.\r\n */\r\n static get City() {\r\n const configuration = {\r\n queryStringValueDescending: 'city-z-a',\r\n queryStringValueAscending: 'city-a-z',\r\n name: 'city',\r\n validResultTypes: [ResultType.Communities, ResultType.Homes, ResultType.Locations],\r\n };\r\n\r\n return this.getInstance('city', configuration);\r\n }\r\n\r\n /**\r\n * Key for price sorting. It could be from low to high or from high to low.\r\n */\r\n static get Price() {\r\n const configuration = {\r\n queryStringValueDescending: 'price-high-low',\r\n queryStringValueAscending: 'price-low-high',\r\n name: 'price',\r\n validResultTypes: [ResultType.Communities, ResultType.Homes, ResultType.Locations],\r\n };\r\n\r\n return this.getInstance('price', configuration);\r\n }\r\n\r\n /**\r\n * Key for bed sorting. It could be from low to high or from high to low.\r\n */\r\n static get Bed() {\r\n const configuration = {\r\n queryStringValueDescending: 'bed-high-low',\r\n queryStringValueAscending: 'bed-low-high',\r\n name: 'bed',\r\n validResultTypes: [ResultType.Homes],\r\n };\r\n\r\n return this.getInstance('bed', configuration);\r\n }\r\n\r\n /**\r\n * Key for builders sorting. It could be from A-Z or Z-A.\r\n */\r\n static get Builders() {\r\n const configuration = {\r\n queryStringValueDescending: 'builder-z-a',\r\n queryStringValueAscending: 'builder-a-z',\r\n name: 'builders',\r\n validResultTypes: [ResultType.Communities, ResultType.Homes, ResultType.Locations],\r\n };\r\n\r\n return this.getInstance('builders', configuration);\r\n }\r\n\r\n /**\r\n * Key for community name sorting. It could be from A-Z or Z-A.\r\n */\r\n static get Community() {\r\n const configuration = {\r\n queryStringValueDescending: 'community-z-a',\r\n queryStringValueAscending: 'community-a-z',\r\n name: 'community',\r\n validResultTypes: [ResultType.Communities, ResultType.Locations],\r\n };\r\n\r\n return this.getInstance('community', configuration);\r\n }\r\n\r\n /**\r\n * Key for community id sorting.\r\n */\r\n static get CommunityId() {\r\n const configuration = {\r\n name: 'communityId',\r\n validResultTypes: [ResultType.Homes, ResultType.Communities, ResultType.Locations],\r\n };\r\n\r\n return this.getInstance('communityId', configuration);\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(name) {\r\n const statusMap = {\r\n city: SortType.City,\r\n price: SortType.Price,\r\n bed: SortType.Bed,\r\n community: SortType.Community,\r\n builders: SortType.Builders,\r\n communityId: SortType.CommunityId,\r\n };\r\n\r\n return statusMap[name];\r\n }\r\n\r\n /**\r\n * Gets an instance of a SortType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the SortType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the SortType class that is being created.\r\n *\r\n * @returns an instance of `SortType` that corresponds to the given `name`.\r\n */\r\n static getInstance(name, configuration) {\r\n configuration.name = name;\r\n\r\n if (!this.instances[name]) {\r\n this.instances[name] = new SortType(configuration);\r\n }\r\n\r\n return this.instances[name];\r\n }\r\n\r\n constructor(configuration) {\r\n this.name = configuration.name;\r\n this.queryStringValueAscending = configuration.queryStringValueAscending;\r\n this.queryStringValueDescending = configuration.queryStringValueDescending;\r\n this.validResultTypes = configuration.validResultTypes;\r\n }\r\n\r\n /**\r\n * getQueryStringValue: gets the SortType's instance query string value.\r\n * @param {boolean} isAscendingOrder is a flag indicating if the SortType instance has to retrieve\r\n * its ascending or descending query string value. \r\n * @returns \r\n */\r\n getQueryStringValue(isAscendingOrder) {\r\n return isAscendingOrder ? this.queryStringValueAscending : this.queryStringValueDescending;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(SortType, 'instances', { value: {} });\r\n","export default class SpecStatus {\r\n static get AvailableNow() {\r\n return this.getInstance('A');\r\n }\r\n\r\n static get Model() {\r\n return this.getInstance('M');\r\n }\r\n\r\n static get ReadyToBuild() {\r\n return this.getInstance('R');\r\n }\r\n\r\n static get UnderConstruction() {\r\n return this.getInstance('UC');\r\n }\r\n\r\n static get HotDeals() {\r\n return this.getInstance('H');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n R: SpecStatus.ReadyToBuild,\r\n A: SpecStatus.AvailableNow,\r\n UC: SpecStatus.UnderConstruction,\r\n M: SpecStatus.Model,\r\n H: SpecStatus.HotDeals,\r\n };\r\n\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new SpecStatus(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(SpecStatus, 'instances', { value: {} });\r\n","import { searchParametersSlice } from '../redux/slices';\r\n\r\nconst actions = searchParametersSlice.actions;\r\n\r\n/**\r\n * List of actions that should update the query string depending if a value is applied.\r\n * If a new action changes filters, and should update the query string we need to add it to this list.\r\n */\r\nconst facetsActionTypes = [\r\n actions.fetchRvGarages.type,\r\n actions.fetchAmenities.type,\r\n actions.fetchCustom.type,\r\n actions.fetchSingleFamily.type,\r\n actions.fetchLuxury.type,\r\n actions.fetchCondosAndTownHomes.type,\r\n actions.fetchManufactured.type,\r\n actions.fetchModelHome.type,\r\n actions.fetchConsumerPromos.type,\r\n actions.fetchPriceReduction.type,\r\n actions.fetchBuilderReviews.type,\r\n actions.fetchActiveAdult.type,\r\n actions.fetchPrice.type,\r\n actions.fetchBedrooms.type,\r\n actions.fetchBathrooms.type,\r\n actions.fetchSchools.type,\r\n actions.clearFilters.type,\r\n actions.allOptions.type,\r\n actions.fetchBrandId.type,\r\n actions.fetchLivingAreas.type,\r\n actions.fetchStories.type,\r\n actions.fetchPrimaryBedroom.type,\r\n actions.fetchGarages.type,\r\n actions.fetchMoveInDateByRange.type,\r\n actions.fetchMoveInDateByStatus.type,\r\n actions.clearMoveInDateFilter.type,\r\n actions.fetchViewBrandResults.type,\r\n actions.fetchViewBrandMarketResults.type,\r\n actions.fetchExcludeActiveAdult.type,\r\n actions.fetchAnyCommunities.type,\r\n actions.fetchGolfCourse.type,\r\n actions.fetchMarketingStatus.type,\r\n actions.fetchSort.type,\r\n actions.fetchHomeOwnersAssociationFee.type,\r\n actions.fetchInteractiveSitePlanResults.type,\r\n];\r\n\r\nexport default facetsActionTypes;\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { getListingCounts } from 'constants/routes'\r\nimport { switchMap } from 'rxjs';\r\n\r\nfunction getCounts(payload) {\r\n const url = `${getListingCounts}`;\r\n\r\n return fromFetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...payload\r\n }\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n }\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n}\r\n\r\nexport default getCounts;\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { getResultFacets } from 'constants/routes'\r\nimport { switchMap } from 'rxjs';\r\n\r\nfunction getBrandsAndSchoolDistricts(payload) {\r\n const url = `${getResultFacets}`;\r\n\r\n return fromFetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...payload\r\n }\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n }\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n}\r\n\r\nexport default getBrandsAndSchoolDistricts;\r\n","/**\r\n * Enumeration to map the fetch request names that could be done along the page.\r\n * It is not intended to execute the requests, but to be able to make any reference about them.\r\n */\r\nexport default class FetchRequest {\r\n\r\n // This result-related call is about the listings that will be shown on the page.\r\n // This call only returns the HTML related to the listing cards that will be shown.\r\n static get Listings() {\r\n return this.getInstance('listings');\r\n }\r\n\r\n // This result-related call is about the counts on the search.\r\n // This call returns a JSON with the total result count value.\r\n static get Counts() {\r\n return this.getInstance('counts');\r\n }\r\n\r\n // This result-related call is about the facets information on the search.\r\n // This call returns a JSON with the values that are used on faceting that changes according to\r\n // the search.\r\n static get SchoolsAndBrandsFaceting() {\r\n return this.getInstance('schoolsAndBrandsFaceting');\r\n }\r\n\r\n static fromKey(key) {\r\n const resultsFetchingCallMap = {\r\n listings: FetchRequest.Listings,\r\n counts: FetchRequest.Counts,\r\n schoolsAndBrandsFaceting: FetchRequest.SchoolsAndBrandsFaceting,\r\n };\r\n\r\n return resultsFetchingCallMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new FetchRequest(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(FetchRequest, 'instances', { value: {} });","import FetchRequest from '../enums/fetchRequest';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nconst actions = searchParametersSlice.actions;\r\n\r\n// The listings call gets the HTML string about all the cards that is shown on the page.\r\n// The Counts call gets the counting value related to the search.\r\n// The SchoolsAndBrandsFaceting call gets the custom faceting values related to schools and brands\r\n// that depends on the search.\r\nconst allResultsCalls = [FetchRequest.Listings, FetchRequest.Counts, FetchRequest.SchoolsAndBrandsFaceting];\r\n\r\n// Here we have the list about the result calls that we have to do according to the action that was\r\n// triggered. Where currently we have the listings, counts and Facets calls.\r\nconst fetchRequestListByAction = {\r\n [actions.fetchSchools.type]: allResultsCalls,\r\n\r\n [actions.fetchBuilderReviews.type]: allResultsCalls,\r\n\r\n [actions.fetchConsumerPromos.type]: allResultsCalls,\r\n\r\n [actions.fetchActiveAdult.type]: allResultsCalls,\r\n\r\n [actions.fetchExcludeActiveAdult.type]: allResultsCalls,\r\n\r\n [actions.fetchAnyCommunities.type]: allResultsCalls,\r\n\r\n [actions.fetchPageSize.type]: [FetchRequest.Listings],\r\n\r\n [actions.fetchPageNumber.type]: [FetchRequest.Listings],\r\n\r\n [actions.fetchPagingControlsNext.type]: [FetchRequest.Listings],\r\n\r\n [actions.fetchPagingControlsPrev.type]: [FetchRequest.Listings],\r\n\r\n [actions.fetchBathrooms.type]: allResultsCalls,\r\n\r\n [actions.fetchBedrooms.type]: allResultsCalls,\r\n\r\n [actions.fetchLocations.type]: allResultsCalls,\r\n\r\n [actions.fetchPrice.type]: allResultsCalls,\r\n\r\n [actions.fetchResultsType.type]: allResultsCalls,\r\n\r\n [actions.fetchSort.type]: [FetchRequest.Listings],\r\n\r\n [actions.fetchLivingAreas.type]: allResultsCalls,\r\n\r\n [actions.fetchStories.type]: allResultsCalls,\r\n\r\n [actions.fetchPrimaryBedroom.type]: allResultsCalls,\r\n\r\n [actions.fetchGarages.type]: allResultsCalls,\r\n\r\n [actions.fetchAmenities.type]: allResultsCalls,\r\n\r\n [actions.fetchMoveInDateByStatus.type]: allResultsCalls,\r\n\r\n [actions.clearMoveInDateFilter.type]: allResultsCalls,\r\n\r\n [actions.clearFilters.type]: allResultsCalls,\r\n\r\n [actions.fetchMoveInDateByRange.type]: allResultsCalls,\r\n\r\n [actions.fetchCustom.type]: allResultsCalls,\r\n\r\n [actions.fetchSingleFamily.type]: allResultsCalls,\r\n\r\n [actions.fetchLuxury.type]: allResultsCalls,\r\n\r\n [actions.fetchCondosAndTownHomes.type]: allResultsCalls,\r\n\r\n [actions.fetchManufactured.type]: allResultsCalls,\r\n\r\n [actions.fetchBrandId.type]: allResultsCalls,\r\n\r\n [actions.fetchViewBrandResults.type]: allResultsCalls,\r\n\r\n [actions.fetchViewBrandMarketResults.type]: allResultsCalls,\r\n\r\n [actions.fetchRvGarages.type]: allResultsCalls,\r\n\r\n [actions.fetchGolfCourse.type]: allResultsCalls,\r\n\r\n [actions.fetchMarketingStatus.type]: allResultsCalls,\r\n\r\n [actions.fetchPriceReduction.type]: allResultsCalls,\r\n\r\n [actions.fetchModelHome.type]: allResultsCalls,\r\n\r\n [actions.allOptions.type]: allResultsCalls,\r\n\r\n [actions.fetchHomeOwnersAssociationFee.type]: allResultsCalls,\r\n\r\n [actions.fetchInteractiveSitePlanResults.type]: allResultsCalls,\r\n};\r\n\r\n/**\r\n * validateIfFetchRequest: Checks if the fetch request should be triggered according the action.\r\n * @param {string} actionType Name of the action.\r\n * @param {FetchRequest} fetchRequest Request to validate if it should ve fetched\r\n * @returns A boolean value indicating if the fetch request should be triggered according to action.\r\n */\r\nconst validateIfFetchRequest = (actionType, fetchRequest) => {\r\n const fetchRequestList = fetchRequestListByAction[actionType];\r\n if (!fetchRequestList) {\r\n return false;\r\n }\r\n\r\n return fetchRequestList.includes(fetchRequest);\r\n};\r\n\r\nexport default validateIfFetchRequest;\r\n","import { catchError, filter, of, switchMap, map, distinctUntilChanged } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport TypeaheadLocationType from 'enums/typeaheadLocationType';\r\nimport facetsActionTypes from '../constants/actionTypeGroupsConstants';\r\nimport LocationType from '../enums/locationType';\r\nimport ResultType from '../enums/resultType';\r\nimport getCounts$ from '../apis/getCounts';\r\nimport getBrandsAndSchoolDistricts$ from '../apis/getBrandsAndSchoolDistricts';\r\nimport { facetsSlice, searchParametersSlice } from './slices';\r\nimport { facetsSelector, selectResultType, selectSearchParameters } from './selectors';\r\nimport FetchRequest from '../enums/fetchRequest';\r\nimport validateIfFetchRequest from '../services/fetchingValidator';\r\n\r\nconst actions = searchParametersSlice.actions;\r\n\r\n// if the action is of type actions.fetchLocations.type, make sure that the location type is not 'Community'\r\n// to prevent fetching new results when being redirected to the detail page.\r\nconst isCommunityLocationTypeSearch = (action) =>\r\n action.type === actions.fetchLocations.type &&\r\n action.payload.locationType.toLowerCase() === TypeaheadLocationType.Community.toString();\r\n\r\nconst isBuilderResultType = (resultType) => resultType === ResultType.Builders.toString();\r\n\r\n// Epic to be able to know when the fetchResultListings should be executed. In other words, it checks all\r\n// the actions and verify if it should execute the fetchResultListings action.\r\nexport const fetchResultListingsEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => validateIfFetchRequest(action.type, FetchRequest.Listings)),\r\n // if the action is of type actions.fetchLocations.type, make sure that the location type is not 'Community'\r\n // to prevent fetching new results when being redirected to the detail page.\r\n filter((action) => !isCommunityLocationTypeSearch(action)),\r\n switchMap(() => of(actions.fetchResultListings()))\r\n );\r\n\r\n// Epic to be able to retrieve the result count information by checking when the fetchResultCounts action\r\n// was executed. Then, according to the retrieving status, executes the action according to it.\r\n// If it gets successful, it means this call was fulfilled, otherwise it means there was an error.\r\nexport const getResultCountsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.fetchResultCounts.type),\r\n switchMap(() => {\r\n const payload = selectSearchParameters(state$.value);\r\n return getCounts$(payload).pipe(\r\n switchMap((data) => of(actions.fetchResultsCountsFulfilled(data))),\r\n catchError((error) => of(actions.fetchResultsCountsError(error)))\r\n );\r\n })\r\n );\r\n\r\n// Epic to be able to know when the fetchResultCounts should be executed. In other words, it checks all\r\n// the actions and verify if it should execute the fetchResultCounts action.\r\nexport const fetchResultCountsEpic = (action$) =>\r\n action$.pipe(\r\n filter((action) => validateIfFetchRequest(action.type, FetchRequest.Counts)),\r\n // if the action is of type actions.fetchLocations.type, make sure that the location type is not 'Community'\r\n // to prevent fetching new results when being redirected to the detail page.\r\n filter((action) => !isCommunityLocationTypeSearch(action)),\r\n switchMap(() => of(actions.fetchResultCounts()))\r\n );\r\n\r\n// Epic to be able to retrieve the result facet information by checking when the fetchSchoolsAndBrandsFaceting action\r\n// was executed. Then, according to the retrieving status, executes the action according to it.\r\n// If it gets successful, it means this call was fulfilled, otherwise it means there was an error.\r\nexport const getResultFacetsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.fetchSchoolsAndBrandsFaceting.type),\r\n switchMap(() => {\r\n // Facts and Features parameters should not be used due to it will filtered the location builders.\r\n const parameters = selectSearchParameters(state$.value);\r\n return getBrandsAndSchoolDistricts$(parameters).pipe(\r\n switchMap((data) => of(actions.fetchResultFacetsFulfilled(data))),\r\n catchError((error) => of(actions.fetchResultFacetsError(error)))\r\n );\r\n })\r\n );\r\n\r\n// Epic to be able to know when the fetchSchoolsAndBrandsFaceting should be executed. In other words, it checks all\r\n// the actions and verify if it should execute the fetchSchoolsAndBrandsFaceting action.\r\nexport const fetchResultFacetsEpic = (action$, state$) =>\r\n action$.pipe(\r\n filter((action) => validateIfFetchRequest(action.type, FetchRequest.SchoolsAndBrandsFaceting)),\r\n // if the action is of type actions.fetchLocations.type, make sure that the location type is not 'Community'\r\n // to prevent fetching new results when being redirected to the detail page.\r\n filter((action) => !isCommunityLocationTypeSearch(action)),\r\n // As the faceting is not being shown when the builder result type is shown, we don't have to keep doing\r\n // result facets calls while it is builder result type.\r\n filter(() => !isBuilderResultType(selectResultType(state$.value))),\r\n switchMap(() => of(actions.fetchSchoolsAndBrandsFaceting()))\r\n );\r\n\r\nconst filters = facetsSlice.actions;\r\n\r\n// Gets the current state of the facets using a selector\r\nfunction getFacetsStatus(state) {\r\n return facetsSelector(state);\r\n}\r\n\r\n/**\r\n * Epic that updates the filters when any of the facets actions is dispatched\r\n * @param {*} action$\r\n * @param {*} state$\r\n * @returns a new action of type updateFilters, with the payload being the current state of the facets\r\n */\r\nexport const updateFacetsEpic = (action$, state$) =>\r\n action$.pipe(\r\n filter((action) => facetsActionTypes.includes(action.type)),\r\n // if the action is of type actions.fetchLocations.type, make sure that the location type is not 'Community'\r\n // to prevent fetching new results when being redirected to the detail page.\r\n filter((action) => !isCommunityLocationTypeSearch(action)),\r\n map(() => ({\r\n type: filters.updateFilters.type,\r\n payload: getFacetsStatus(state$.value),\r\n }))\r\n );\r\n/**\r\n * Epic that updates the location when result type is changed to Builder directory.\r\n * By biz rule, when there is a tab change (result type) to builder directory, with a zip location context,\r\n * it should be redirected to its city\r\n * @param {*} action$\r\n * @param {*} state$\r\n */\r\nexport const updateZipSearchesOnBuildersResult = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.fetchResultsType.type),\r\n filter((action) => action.payload.resultType === ResultType.Builders.toString()),\r\n filter(() => state$.value?.searchParameters.location.locationType === LocationType.Zip.toString()),\r\n distinctUntilChanged(),\r\n switchMap(() => of(actions.changeZipSearchtoCitySearch()))\r\n );\r\n","/**\r\n * This component interacts with the label for price facets section.\r\n */\r\nimport { store$ } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { selectPrice } from '../redux/selectors';\r\nimport PriceDualSlider from './priceDualRangeSlider';\r\n\r\nexport default class PriceFilterLabel {\r\n constructor(facetPriceLabel) {\r\n this.priceSlider = document.querySelector('[data-price-slider-container]');\r\n this.priceMinimumSlider = +this.priceSlider.dataset.min;\r\n this.priceMaximumSlider = +this.priceSlider.dataset.max;\r\n this.facetPriceLabel = facetPriceLabel;\r\n (() => new PriceDualSlider(this.priceSlider))();\r\n const onPriceChange$ = this.onPriceChange();\r\n onPriceChange$.subscribe(this.toggleActiveClass.bind(this));\r\n onPriceChange$.subscribe(this.updatePriceRangeText.bind(this));\r\n }\r\n\r\n /**\r\n * gets the label to use for the input depending on the value.\r\n * returns XXXk if under $999k, returns $X.XM if over $999k\r\n * @param {int} value\r\n */\r\n static getLabel(value) {\r\n if (value < 999000) {\r\n return `$${value / 1000}k`;\r\n }\r\n return `$${value / 1000000}M`;\r\n }\r\n\r\n onPriceChange() {\r\n return store$.pipe(\r\n filter(selectPrice),\r\n map(selectPrice),\r\n distinctUntilChanged(),\r\n map((value) => ({\r\n minimum: value.minimumPrice || this.priceMinimumSlider,\r\n maximum: value.maximumPrice || this.priceMaximumSlider,\r\n }))\r\n );\r\n }\r\n\r\n updatePriceRangeText(price) {\r\n const { minimum, maximum } = price;\r\n const priceLabels = {\r\n minimum: 'No Min',\r\n maximum: 'No Max',\r\n };\r\n\r\n if (minimum !== this.priceMinimumSlider) {\r\n priceLabels.minimum = PriceFilterLabel.getLabel(minimum);\r\n }\r\n\r\n if (maximum !== this.priceMaximumSlider) {\r\n priceLabels.maximum = PriceFilterLabel.getLabel(maximum);\r\n }\r\n\r\n // if both values are the same as the slider's minimum and maximum values, then display 'Price', the default value.\r\n // otherwise, display the price range.\r\n if (minimum === this.priceMinimumSlider && maximum === this.priceMaximumSlider) {\r\n this.facetPriceLabel.textContent = 'Price';\r\n } else {\r\n this.facetPriceLabel.textContent = `${priceLabels.minimum} - ${priceLabels.maximum}`;\r\n }\r\n }\r\n\r\n /**\r\n * toggleActiveClass: Adds the active class to the label if the minimumSliderValue and the maximumSliderValue\r\n * are different than the slider's minimum and maximum values.\r\n */\r\n toggleActiveClass(price) {\r\n const { minimum, maximum } = price;\r\n if (minimum === this.priceMinimumSlider && maximum === this.priceMaximumSlider) {\r\n this.facetPriceLabel.classList.remove('nhs-c-select__label--big-text',\r\n 'nhs-mq-select__label--big-text-medium',\r\n 'nhs-c-select-button--active');\r\n } else {\r\n this.facetPriceLabel.classList.add('nhs-c-select__label--big-text', \r\n 'nhs-mq-select__label--big-text-medium', \r\n 'nhs-c-select-button--active');\r\n }\r\n }\r\n}\r\n","import Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { moveInDateSelector, selectProductType } from '../redux/selectors';\r\nimport { getMovingDateFilterApplied } from '../services/moveInDateService';\r\nimport PlanStatus from '../enums/planStatus';\r\nimport SpecStatus from '../enums/specStatus';\r\nimport { searchParametersSlice } from '../redux/slices';\r\nimport { getInventoryStatusCombination } from '../services/homeStatusValidator';\r\nimport ProductType from '../enums/productType';\r\n\r\nclass SelectMoveInDate {\r\n constructor(moveInDate) {\r\n this.moveInDate = moveInDate;\r\n const selectMoveInDate$ = new Select(moveInDate).getObservable();\r\n selectMoveInDate$.subscribe(SelectMoveInDate.onChangeMoveInDate);\r\n this.moveInDateChange$ = store$.pipe(\r\n map(moveInDateSelector),\r\n distinctUntilChanged(),\r\n map(getMovingDateFilterApplied)\r\n );\r\n this.moveInDateChange$.subscribe(this.setMoveInDateValue.bind(this));\r\n store$.pipe(map(selectProductType), distinctUntilChanged()).subscribe(this.onProductTypeChange.bind(this));\r\n }\r\n\r\n static onChangeMoveInDate(value) {\r\n switch (value) {\r\n case PlanStatus.AvailableNow.toString():\r\n case SpecStatus.AvailableNow.toString():\r\n case PlanStatus.ReadyToBuild.toString():\r\n case SpecStatus.ReadyToBuild.toString():\r\n case getInventoryStatusCombination():\r\n store.dispatch(searchParametersSlice.actions.fetchMoveInDateByStatus(value));\r\n break;\r\n case '':\r\n store.dispatch(searchParametersSlice.actions.clearMoveInDateFilter(value));\r\n break;\r\n default:\r\n store.dispatch(searchParametersSlice.actions.fetchMoveInDateByRange(value));\r\n break;\r\n }\r\n }\r\n\r\n onProductTypeChange(productType) {\r\n switch (productType) {\r\n case ProductType.BuildOnYourLot.toString():\r\n case ProductType.Custom.toString():\r\n case ProductType.Manufactured.toString():\r\n this.disable();\r\n break;\r\n\r\n default:\r\n this.enable();\r\n }\r\n }\r\n\r\n disable() {\r\n this.moveInDate.setAttribute('disabled', '');\r\n }\r\n\r\n /**\r\n * Set the value of the moveInDateElement to update the select.\r\n * @param value - The value of move in date in the store.\r\n */\r\n setMoveInDateValue(value) {\r\n this.moveInDate.value = value;\r\n }\r\n\r\n enable() {\r\n this.moveInDate.removeAttribute('disabled');\r\n }\r\n\r\n toggleActiveClass() {\r\n this.moveInDateChange$.subscribe((value) => {\r\n if (value) {\r\n this.moveInDate.classList.add('nhs-c-select-button--active');\r\n } else {\r\n this.moveInDate.classList.remove('nhs-c-select-button--active');\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport default SelectMoveInDate;\r\n","import { fromEvent, map } from \"rxjs\";\r\n\r\nfunction radioButton(group){\r\n const group$ = fromEvent(group, 'change').pipe(\r\n map((event) => event.target.value)\r\n );\r\n \r\n return group$;\r\n}\r\n\r\nexport default radioButton;","import radioButton from '@components/radioButton';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectBedrooms } from '../redux/selectors';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class Bedroom {\r\n constructor(bedroomsGroup) {\r\n this.bedroomsGroup = bedroomsGroup;\r\n const bedroomsRadio$ = radioButton(bedroomsGroup);\r\n bedroomsRadio$.subscribe((value) => store.dispatch(searchParametersSlice.actions.fetchBedrooms(value)));\r\n store$.pipe(map(selectBedrooms), distinctUntilChanged()).subscribe(this.updateValue.bind(this));\r\n }\r\n\r\n updateValue(value) {\r\n const bedrooms = value || 0;\r\n const previousValue = this.bedroomsGroup.querySelector('input:checked');\r\n const newValue = this.bedroomsGroup.querySelector(`[value=\"${bedrooms}\"]`);\r\n if (previousValue) {\r\n previousValue.checked = false;\r\n }\r\n newValue.checked = true;\r\n }\r\n}\r\n","import radioButton from '@components/radioButton';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, map } from 'rxjs';\r\nimport { selectBathrooms } from '../redux/selectors';\r\nimport { searchParametersSlice } from '../redux/slices';\r\n\r\nexport default class Bathroom {\r\n constructor(bathroomGroup) {\r\n this.bathroomGroup = bathroomGroup;\r\n const bathroomsRadio$ = radioButton(this.bathroomGroup);\r\n bathroomsRadio$.subscribe((value) => store.dispatch(searchParametersSlice.actions.fetchBathrooms(value)));\r\n store$.pipe(map(selectBathrooms), distinctUntilChanged()).subscribe(this.updateValue.bind(this));\r\n }\r\n\r\n updateValue(value) {\r\n const bathrooms = value || 0;\r\n const previousValue = this.bathroomGroup.querySelector('input:checked');\r\n const newValue = this.bathroomGroup.querySelector(`[value=\"${bathrooms}\"]`);\r\n if (previousValue) {\r\n previousValue.checked = false;\r\n }\r\n newValue.checked = true;\r\n }\r\n}\r\n","/**\r\n * This component interacts with the label for price facets section.\r\n */\r\nimport { store$ } from '@redux/store';\r\nimport { combineLatest, distinctUntilChanged, map } from 'rxjs';\r\nimport { selectBathrooms, selectBedrooms } from '../redux/selectors';\r\nimport Bedroom from './bedroom';\r\nimport Bathroom from './bathroom';\r\n\r\nexport default class BedroomAndBathroomFilterLabel {\r\n constructor(bedroomAndBathRoomLabel) {\r\n this.bedroomAndBathRoomLabel = bedroomAndBathRoomLabel;\r\n this.bedroomElement = document.querySelector('[data-bedrooms-group]');\r\n this.bedroomLabel = bedroomAndBathRoomLabel.querySelector('[data-label-bedroom]');\r\n\r\n this.bathroomElement = document.querySelector('[data-bathrooms-group]');\r\n this.bathroomLabel = bedroomAndBathRoomLabel.querySelector('[data-label-bathroom]');\r\n\r\n (() => new Bedroom(this.bedroomElement))();\r\n (() => new Bathroom(this.bathroomElement))();\r\n\r\n const onBedroomChange$ = BedroomAndBathroomFilterLabel.onBedroomChange();\r\n onBedroomChange$.subscribe(this.changeBedroomLabel.bind(this));\r\n const onBathroomChange$ = BedroomAndBathroomFilterLabel.onBathroomChange();\r\n onBathroomChange$.subscribe(this.changeBathroomLabel.bind(this));\r\n\r\n combineLatest([onBedroomChange$, onBathroomChange$]).subscribe(this.toggleActiveClass.bind(this));\r\n }\r\n\r\n static onBathroomChange() {\r\n return store$.pipe(map(selectBathrooms), distinctUntilChanged());\r\n }\r\n\r\n static onBedroomChange() {\r\n return store$.pipe(map(selectBedrooms), distinctUntilChanged());\r\n }\r\n\r\n changeBathroomLabel(value) {\r\n if (value) {\r\n this.bathroomLabel.innerText = `${value}+ Ba`;\r\n return;\r\n }\r\n this.bathroomLabel.innerText = `Bath`;\r\n }\r\n\r\n changeBedroomLabel(value) {\r\n if (value) {\r\n this.bedroomLabel.innerText = `${value}+ Br`;\r\n return;\r\n }\r\n this.bedroomLabel.innerText = `Bed`;\r\n }\r\n\r\n /**\r\n * toggleActiveClass: Adds the active class to the label if the minimumSliderValue and the maximumSliderValue\r\n * are different than the slider's minimum and maximum values.\r\n */\r\n toggleActiveClass(facts) {\r\n const [minimumBedroom, minimumBathroom] = facts;\r\n if (minimumBedroom || minimumBathroom) {\r\n this.bedroomAndBathRoomLabel.classList.add('nhs-c-select__label--big-text',\r\n 'nhs-mq-select__label--big-text-medium',\r\n 'nhs-mq-select__label--big-text-bed-bath-large',\r\n 'nhs-c-select-button--active');\r\n return;\r\n }\r\n this.bedroomAndBathRoomLabel.classList.remove('nhs-c-select__label--big-text',\r\n 'nhs-mq-select__label--big-text-medium',\r\n 'nhs-mq-select__label--big-text-bed-bath-large',\r\n 'nhs-c-select-button--active');\r\n }\r\n}\r\n","import { epic$ } from '@redux/store';\r\nimport TypeaheadLocationType from 'enums/typeaheadLocationType';\r\nimport LocationType from './enums/locationType';\r\nimport {\r\n fetchResultCountsEpic,\r\n getResultCountsEpic,\r\n fetchResultListingsEpic,\r\n fetchResultFacetsEpic,\r\n getResultFacetsEpic,\r\n updateFacetsEpic,\r\n updateZipSearchesOnBuildersResult,\r\n} from './redux/epics';\r\nimport {\r\n isNotCommunityLocationType,\r\n selectConsumerPromos,\r\n selectCondosAndTownHomes,\r\n selectFacts,\r\n selectFeatures,\r\n selectListingCount,\r\n selectResultsModifiers,\r\n selectPage,\r\n selectProduct,\r\n selectProductType,\r\n selectResults,\r\n selectCounties,\r\n selectBrand,\r\n selectHomeStatus,\r\n selectLocation,\r\n selectLocationContentContext,\r\n selectMarketingStatus,\r\n pageCountSelector,\r\n selectPaginationContext,\r\n selectContentTemplateTypeModifiers,\r\n selectSubdirectory,\r\n moveInDateSelector,\r\n selectBrandFilterContext,\r\n selectSearchResultFacetsTrackingCommonProperties,\r\n selectLocationType,\r\n selectResultType,\r\n selectPaging,\r\n selectProductAndResultType,\r\n selectSearchCommandContext,\r\n selectSnippetCommand,\r\n selectSorting,\r\n activeAdultCommunitiesSelector,\r\n fetchingResultsCallStatusesSelector,\r\n selectFetchResultListingsStatus,\r\n facetsSelector,\r\n selectSearchCount,\r\n selectAppliedFacets,\r\n selectFetchCountsStatusAndsCounts,\r\n facetsPanelSelector,\r\n homeFactsSelectors,\r\n selectLinkedPopularPillsFilters,\r\n selectPageSize,\r\n selectNatureAreas,\r\n selectPool,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectGatedCommunity,\r\n selectBathrooms,\r\n selectBedrooms,\r\n selectLuxury,\r\n selectMaximumPrice,\r\n selectMinimumPrice,\r\n selectLivingAreas,\r\n selectGarages,\r\n selectStories,\r\n selectPrimaryBedroom,\r\n selectRvGarage,\r\n selectReviews,\r\n selectMoveInDateRange,\r\n selectPriceReduction,\r\n selectResultTypeAndSorting,\r\n selectSearchParameters,\r\n selectSearchModifiers,\r\n selectHomeOwnersAssociationFee,\r\n selectResultsType\r\n} from './redux/selectors';\r\nimport getResults$ from './apis/getResults';\r\nimport { searchParametersSlice, facetsSlice } from './redux/slices';\r\nimport MoveInDate from './enums/moveInDate';\r\nimport PlanStatus from './enums/planStatus';\r\nimport SpecStatus from './enums/specStatus';\r\nimport ResultType from './enums/resultType';\r\nimport ProductType from './enums/productType';\r\nimport SortType from './enums/sortType';\r\nimport UrlSubdirectoryTypes from '../../pages/searchResults/enums/urlSubdirectoryTypes';\r\nimport PriceFilterLabel from './components/priceFilterLabel';\r\nimport SelectMoveInDate from './components/selectMoveInDate';\r\nimport BedroomAndBathroomFilterLabel from './components/bedroomAndBathroomFilterLabel';\r\nimport {\r\n getInventoryStatusCombination,\r\n hasReadyToBuild,\r\n hasAvailableNow,\r\n hasInventoryStatusCombination,\r\n hasModelHome,\r\n} from './services/homeStatusValidator';\r\n\r\nconst { actions, reducer } = searchParametersSlice;\r\nconst facetsActions = facetsSlice.actions;\r\nconst facetsReducers = facetsSlice.reducer;\r\nconst facetPriceLabel = document.querySelector('[data-price-toggle-label]');\r\nconst moveInDateElement = document.querySelector('[data-move-in-date-filter]');\r\nconst facetBedroomBathroomLabel = document.querySelector('[data-bedroom-bathroom-label]');\r\n\r\nepic$.next(fetchResultCountsEpic);\r\nepic$.next(getResultCountsEpic);\r\nepic$.next(fetchResultListingsEpic);\r\nepic$.next(fetchResultFacetsEpic);\r\nepic$.next(getResultFacetsEpic);\r\nepic$.next(updateFacetsEpic);\r\nepic$.next(updateZipSearchesOnBuildersResult);\r\n\r\nconst searchParametersSelectors = {\r\n selectLocation,\r\n selectProductType,\r\n selectContentTemplateTypeModifiers,\r\n};\r\n\r\n(() => new PriceFilterLabel(facetPriceLabel))();\r\n(() => new BedroomAndBathroomFilterLabel(facetBedroomBathroomLabel))();\r\n\r\nconst selectMoveInDate = new SelectMoveInDate(moveInDateElement);\r\nselectMoveInDate.toggleActiveClass();\r\n\r\nexport { LocationType };\r\nexport { TypeaheadLocationType };\r\nexport {\r\n actions as searchParametersActions,\r\n reducer as searchParametersReducers,\r\n facetsActions,\r\n facetsReducers,\r\n isNotCommunityLocationType,\r\n pageCountSelector,\r\n searchParametersSelectors,\r\n selectPaginationContext,\r\n moveInDateSelector,\r\n selectBrand,\r\n selectLocationType,\r\n selectResultType,\r\n selectProduct,\r\n selectProductAndResultType,\r\n selectLocation,\r\n selectListingCount,\r\n selectPage,\r\n facetsSelector,\r\n selectSorting,\r\n activeAdultCommunitiesSelector,\r\n fetchingResultsCallStatusesSelector,\r\n selectFetchResultListingsStatus,\r\n MoveInDate,\r\n SpecStatus,\r\n PlanStatus,\r\n ResultType,\r\n ProductType,\r\n SortType,\r\n UrlSubdirectoryTypes,\r\n selectCounties,\r\n selectSubdirectory,\r\n getInventoryStatusCombination,\r\n hasReadyToBuild,\r\n hasAvailableNow,\r\n hasInventoryStatusCombination,\r\n hasModelHome,\r\n selectBrandFilterContext,\r\n selectSearchResultFacetsTrackingCommonProperties,\r\n selectSnippetCommand,\r\n selectSearchCount,\r\n selectConsumerPromos,\r\n selectCondosAndTownHomes,\r\n selectFacts,\r\n selectFeatures,\r\n selectMarketingStatus,\r\n selectHomeStatus,\r\n selectAppliedFacets,\r\n selectResultsModifiers,\r\n selectResults,\r\n selectSearchCommandContext,\r\n selectLocationContentContext,\r\n selectFetchCountsStatusAndsCounts,\r\n facetsPanelSelector,\r\n homeFactsSelectors,\r\n selectLinkedPopularPillsFilters,\r\n selectPageSize,\r\n selectPaging,\r\n selectProductType,\r\n selectNatureAreas,\r\n selectPool,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectGatedCommunity,\r\n selectBathrooms,\r\n selectBedrooms,\r\n selectLuxury,\r\n selectMaximumPrice,\r\n selectMinimumPrice,\r\n selectLivingAreas,\r\n selectGarages,\r\n selectStories,\r\n selectPrimaryBedroom,\r\n selectRvGarage,\r\n selectReviews,\r\n selectMoveInDateRange,\r\n selectPriceReduction,\r\n selectResultTypeAndSorting,\r\n selectSearchParameters,\r\n getResults$,\r\n selectSearchModifiers,\r\n selectHomeOwnersAssociationFee,\r\n selectResultsType\r\n};\r\n\r\nrequire('./components/priceDualRangeSlider');\r\nrequire('./components/advancedFiltersPanel');\r\nrequire('./components/advancedClearButton');\r\nrequire('./components/clearButton');\r\nrequire('./redux/listeners');\r\n","import { createListenerMiddleware } from '@reduxjs/toolkit';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport TypeaheadLocationType from 'enums/typeaheadLocationType';\r\nimport { searchParametersSlice } from './slices';\r\n\r\nconst { actions } = searchParametersSlice;\r\n\r\nconst listenerMiddleware = createListenerMiddleware();\r\n\r\n// Handling the redirection as a side effect of the fetchLocations action\r\n// This listener is in charge to redirect to the community detail page when a community location is \r\n// selected from the search results page.\r\nlistenerMiddleware.startListening({\r\n type: actions.fetchLocations.type,\r\n effect: (action) => {\r\n const isCommunity = action?.payload?.locationType?.toLowerCase() === TypeaheadLocationType.Community.toString();\r\n const isMasterPlannedCommunity = action?.payload?.locationType?.toLowerCase() === \r\n TypeaheadLocationType.MasterPlannedCommunity.toString().toLowerCase();\r\n\r\n if (isCommunity || isMasterPlannedCommunity) {\r\n window.location.href = `/communitydetail/community-${action?.payload?.communityId}`\r\n }\r\n },\r\n});\r\n\r\naddMiddleware(listenerMiddleware.middleware);","import { createSelector } from '@reduxjs/toolkit';\r\nimport { isActive, isCloseOut, isComingSoon, isGrandOpening } from 'services/marketingStatusValidator';\r\nimport TypeaheadLocationType from 'enums/typeaheadLocationType';\r\nimport { getMovingDateFilterApplied, isMoveInDateApplied } from '../services/moveInDateService';\r\nimport ProductType from '../enums/productType';\r\nimport { hasModelHome } from '../services/homeStatusValidator';\r\nimport SpecStatus from '../enums/specStatus';\r\n\r\nconst selectAdult = (state) => state?.searchParameters?.features?.adult;\r\nconst selectAgeRestricted = (state) => state?.searchParameters?.features?.ageRestricted;\r\nconst isCustom = (state) => state?.searchParameters?.product?.productType === ProductType.Custom.toString();\r\nconst selectBrands = (state) => state?.searchParameters?.counts?.brands;\r\nconst selectFetchResultCountsStatus = (state) => state?.searchParameters?.fetchResultCountsStatus;\r\nconst selectCommunityName = (state) => state?.searchParameters?.facts?.communityName;\r\nconst selectMarketId = (state) => state?.searchParameters?.location?.marketId;\r\nconst selectMarketName = (state) => state?.searchParameters?.location?.marketName;\r\nconst selectStateAbbreviation = (state) => state?.searchParameters?.location?.marketState;\r\nconst selectCity = (state) => state?.searchParameters?.location?.city;\r\nconst selectZip = (state) => state?.searchParameters?.location?.zip;\r\nconst selectCounty = (state) => state?.searchParameters?.location?.county;\r\nconst selectSyntheticName = (state) => state?.searchParameters?.location?.syntheticGeographicName;\r\nconst selectContentTemplateType = (state) => state?.searchParameters?.contentTemplateType;\r\nconst selectSchoolDistrictName = (state) => state?.searchParameters?.features?.schoolDistrictName;\r\nconst selectHotDealsCount = (state) => state?.searchParameters?.counts?.hotDealsCount;\r\nconst selectAdultCount = (state) => state?.searchParameters?.counts?.adultCount;\r\nconst selectComingSoonCount = (state) => state?.searchParameters?.counts?.comingSoonCount;\r\nconst selectQuickMoveInCount = (state) => state?.searchParameters?.counts?.quickMoveInCount;\r\nconst selectBuildablePlansCount = (state) => state?.searchParameters?.counts?.buildablePlansCount;\r\nconst selectMultiFamilyCount = (state) => state?.searchParameters?.counts?.multiFamilyCount;\r\nconst isBuildOnYourLot = (state) =>\r\n state?.searchParameters?.product?.productType === ProductType.BuildOnYourLot.toString();\r\nconst isCustomHomes = createSelector(isCustom, isBuildOnYourLot, (custom, buildOnYourLot) =>\r\n Boolean(custom, buildOnYourLot)\r\n);\r\n /**\r\n * The function checks if a product is manufactured based on the search parameters in the state object.\r\n * @param state - The `state` parameter is an object that represents the current state of the\r\n * application. It may contain various properties and values that are relevant to the application's\r\n * functionality.\r\n */\r\nconst isManufactured = (state) =>\r\n state?.searchParameters?.product?.productType === ProductType.Manufactured.toString();\r\n\r\nexport const selectPriceReduction = (state) => state?.searchParameters?.facts?.priceReduction;\r\nexport const selectMoveInDateRange = (state) => state?.searchParameters?.facts?.moveInDateRange;\r\nexport const selectMinimumPrice = (state) => state?.searchParameters?.facts?.price?.minimumPrice;\r\nexport const selectMaximumPrice = (state) => state?.searchParameters?.facts?.price?.maximumPrice;\r\nexport const selectNatureAreas = (state) => state?.searchParameters?.features?.natureAreas;\r\nexport const selectPool = (state) => state?.searchParameters?.features?.pool;\r\nexport const selectGolfCourse = (state) => state?.searchParameters?.features?.golfCourse;\r\nexport const selectGreen = (state) => state?.searchParameters?.features?.green;\r\nexport const selectSportsFacilities = (state) => state?.searchParameters?.features?.sportsFacilities;\r\nexport const selectParks = (state) => state?.searchParameters?.features?.parks;\r\nexport const selectViews = (state) => state?.searchParameters?.features?.views;\r\nexport const selectWaterfront = (state) => state?.searchParameters?.features?.waterfront;\r\nexport const selectGatedCommunity = (state) => state?.searchParameters?.features?.gatedCommunity;\r\nexport const selectMarketingStatus = (state) => state?.searchParameters?.facts?.marketingStatus;\r\nexport const selectConsumerPromos = (state) => state?.searchParameters?.facts?.consumerPromos;\r\nexport const selectRvGarage = (state) => state?.searchParameters?.facts?.recreationalVehicleGarage;\r\nexport const selectHomeStatus = (state) => state?.searchParameters?.facts?.homeStatus;\r\nexport const selectBathrooms = (state) => state?.searchParameters?.facts?.minimumBathroom;\r\nexport const selectBedrooms = (state) => state?.searchParameters?.facts?.minimumBedroom;\r\nexport const selectSchools = (state) => state?.searchParameters?.features?.schoolDistrictIds;\r\nexport const selectBrandId = (state) => state?.searchParameters?.facts?.brandId;\r\nexport const selectBrandName = (state) => state?.searchParameters?.facts?.brandName;\r\nexport const selectLivingAreas = (state) => state?.searchParameters?.facts?.livingAreas;\r\nexport const selectStories = (state) => state?.searchParameters?.facts?.stories;\r\nexport const selectPrimaryBedroom = (state) => state?.searchParameters?.facts?.primaryBedroom;\r\nexport const selectGarages = (state) => state?.searchParameters?.facts?.garages;\r\nexport const selectSingleFamily = (state) => state?.searchParameters?.features?.singleFamily;\r\nexport const selectLuxury = (state) => state?.searchParameters?.features?.luxury;\r\nexport const selectCondosAndTownHomes = (state) => state?.searchParameters?.features?.condosAndTownHomes;\r\nexport const selectPage = (state) => Number(state?.searchParameters?.results?.paging?.page);\r\nexport const selectPaging = (state) => state?.searchParameters?.results?.paging;\r\nexport const selectPrice = (state) => state?.searchParameters?.facts?.price;\r\nexport const selectCounties = (state) => state?.searchParameters?.counts?.counties;\r\nexport const selectAppliedFacets = (state) => state?.facetsState?.appliedFilters;\r\nexport const selectListingCount = (state) => state?.searchParameters?.counts?.listingCount;\r\nexport const selectProductType = (state) => state?.searchParameters?.product?.productType;\r\nexport const selectLocation = (state) => state?.searchParameters?.location;\r\nexport const selectProduct = (state) => state?.searchParameters?.product;\r\nexport const selectResults = (state) => state?.searchParameters?.results;\r\nexport const selectFeatures = (state) => state?.searchParameters?.features;\r\nexport const selectFacts = (state) => state?.searchParameters?.facts;\r\nexport const selectResultsType = (state) => state?.searchParameters?.results.resultType;\r\nexport const selectResultsModifiers = (state) => state?.searchParameters?.resultsModifiers;\r\nexport const selectFetchResultListingsStatus = (state) => state?.searchParameters?.fetchResultListingsStatus;\r\nexport const selectResultType = (state) => state?.searchParameters?.results?.resultType;\r\nexport const selectLocationType = (state) => state?.searchParameters?.location?.locationType;\r\nexport const selectSearchParameters = (state) => state?.searchParameters;\r\nexport const selectSorting = (state) => state?.searchParameters?.results?.sorting;\r\nexport const selectPageSize = (state) => Number(state?.searchParameters?.results?.paging?.pageSize);\r\nexport const selectReviews = (state) => state?.searchParameters?.facts?.builderReviews;\r\nexport const isNotCommunityLocationType = (state) =>\r\n state?.searchParameters?.location?.locationType !== TypeaheadLocationType.Community.toString();\r\nexport const selectedMarkerId = (state) => state?.mapState?.selectedMarker?.id;\r\nexport const selectHomeOwnersAssociationFee = (state) => state?.searchParameters?.facts?.hasHomeOwnersAssociationFee;\r\n\r\n// Selector used to get the values from the brand as the ID and Name.\r\nconst selectBrandInformation = createSelector(selectBrandId, selectBrandName, (brandId, brandName) => ({\r\n brandId,\r\n brandName,\r\n}));\r\n\r\n/**\r\n * Selects the value of the excludeAdult feature from the search parameters in the Redux store state.\r\n * @param {Object} state - The current state of the application.\r\n * @returns {boolean} - The value of the excludeAdult parameter.\r\n */\r\nconst selectExcludeAdult = (state) => state?.searchParameters?.resultsModifiers?.excludeAdult;\r\n\r\n/**\r\n * Selects the value of the excludeAgeRestricted feature from the search parameters in the state.\r\n * @param {Object} state - The current state of the application.\r\n * @returns {boolean} - The value of the excludeAgeRestricted parameter.\r\n */\r\nconst selectExcludeAgeRestricted = (state) => state?.searchParameters?.resultsModifiers?.excludeAgeRestricted;\r\n\r\n/**\r\n * This selector aims to expose all the properties that we have in the housing options section in the All filters menu.\r\n */\r\nconst housingOptionsSelector = createSelector(\r\n selectSingleFamily,\r\n selectLuxury,\r\n selectCondosAndTownHomes,\r\n isCustomHomes,\r\n isManufactured,\r\n selectHomeStatus,\r\n (singleFamily, luxury, condosAndTownHomes, custom, manufactured, homeStatus) => {\r\n const filters = {singleFamily, luxury ,condosAndTownHomes, custom, manufactured, \r\n model_homes: hasModelHome(homeStatus)};\r\n return filters;\r\n }\r\n);\r\n\r\n/**\r\n * This selector aims to expose all the properties that we have in the community status selector \r\n * in the All filters menu.\r\n */\r\nconst communityStatusSelector = createSelector(\r\n selectMarketingStatus,\r\n (marketingStatus) => {\r\n const filters = {\r\n coming_soon: isComingSoon(marketingStatus),\r\n grand_opening: isGrandOpening(marketingStatus),\r\n active: isActive(marketingStatus),\r\n closeout: isCloseOut(marketingStatus),\r\n };\r\n return filters;\r\n }\r\n);\r\n\r\n/**\r\n * Selects information about listing counts and result type for the Advanced Filters confirmation button.\r\n */\r\nexport const selectCountsAndResultType = createSelector(\r\n selectListingCount,\r\n selectFetchResultListingsStatus,\r\n selectResultType,\r\n (\r\n listingCounts,\r\n resultCountsStatus,\r\n resultType,\r\n ) =>\r\n ({ \r\n listingCounts,\r\n resultCountsStatus,\r\n resultType,\r\n })\r\n );\r\n\r\n/**\r\n * This selector aims to expose the filtered brandId (if any) and the list of schools (if any) properties.\r\n */\r\nconst brandIdAndSchoolsSelector = createSelector(\r\n selectSchools,\r\n selectBrandId,\r\n (schools, brandId) => {\r\n const filters = {schools, brandId: Number(brandId)};\r\n return filters;\r\n}\r\n);\r\n\r\n/**\r\n * Returns an object with properties indicating the active adult communities based on the selected filters.\r\n *\r\n * @function\r\n * @name activeAdultCommunitiesSelector\r\n * @param {boolean} selectAdult - Indicates if adult communities are selected.\r\n * @param {boolean} selectAgeRestricted - Indicates if age-restricted communities are selected.\r\n * @param {boolean} selectExcludeAdult - Indicates if adult communities are excluded.\r\n * @param {boolean} selectExcludeAgeRestricted - Indicates if age-restricted communities are excluded.\r\n * @returns {Object} Object indicating the 55+ communities status based on the selected filters.\r\n */\r\nexport const activeAdultCommunitiesSelector = createSelector(\r\n selectAdult,\r\n selectAgeRestricted,\r\n selectExcludeAdult,\r\n selectExcludeAgeRestricted,\r\n (adult, ageRestricted, excludeAdult, excludeAgeRestricted) => {\r\n const only = adult === true && ageRestricted === true;\r\n const exclude = excludeAdult === true && excludeAgeRestricted === true;\r\n\r\n return {\r\n only,\r\n exclude,\r\n any: !only && !exclude,\r\n };\r\n }\r\n);\r\n\r\n/**\r\n * This selector aims to expose all the properties that we have in the other filters section in the All filters menu.\r\n * Such as; only with reviews, hotdeal and the different states of Active adult communities.\r\n */\r\nconst otherFiltersSelector = createSelector(\r\n selectReviews,\r\n selectConsumerPromos,\r\n selectPriceReduction,\r\n selectHomeOwnersAssociationFee,\r\n activeAdultCommunitiesSelector,\r\n ( reviews, consumerPromos, priceReduction, hasHomeOwnersAssociationFee, activeAdultCommunities) => {\r\n const {only, exclude, any } = activeAdultCommunities;\r\n const filters = {\r\n reviews,\r\n hotDeals: Boolean(consumerPromos),\r\n priceReduction: Boolean(priceReduction),\r\n hasHomeOwnersAssociationFee: Boolean(hasHomeOwnersAssociationFee),\r\n any,\r\n only,\r\n exclude,\r\n };\r\n return filters;\r\n }\r\n);\r\n\r\nexport const selectFetchCountsStatusAndsCounts = createSelector(\r\n selectListingCount,\r\n selectFetchResultCountsStatus,\r\n (listingCounts, resultCountsStatus) => ({ listingCounts, resultCountsStatus })\r\n );\r\n\r\nexport const fetchingResultsCallStatusesSelector = createSelector(\r\n selectFetchResultListingsStatus,\r\n selectFetchResultCountsStatus,\r\n (fetchResultListingsStatus, fetchResultCountsStatus) => ({ fetchResultListingsStatus, fetchResultCountsStatus })\r\n);\r\n\r\nexport const selectSnippetCommand = createSelector(\r\n selectLocation,\r\n selectProduct,\r\n selectResultType,\r\n selectContentTemplateType,\r\n (location, product, resultType, contentTemplateType) => ({\r\n location,\r\n product,\r\n results: { resultType },\r\n contentTemplateType,\r\n })\r\n);\r\n\r\nexport const selectProductAndResultType = createSelector(\r\n selectProductType,\r\n selectResultType,\r\n (productType, resultType) => ({ productType, resultType })\r\n);\r\n\r\nexport const selectSearchCount = createSelector(\r\n selectHotDealsCount,\r\n selectAdultCount,\r\n selectComingSoonCount,\r\n selectQuickMoveInCount,\r\n selectBuildablePlansCount,\r\n selectMultiFamilyCount,\r\n (hotDealsCount,\r\n adultCount,\r\n comingSoonCount,\r\n quickMoveInCount,\r\n buildablePlansCount,\r\n multiFamilyCount\r\n ) => ({ \r\n hotDealsCount,\r\n adultCount,\r\n comingSoonCount,\r\n quickMoveInCount,\r\n buildablePlansCount,\r\n multiFamilyCount\r\n })\r\n );\r\n\r\n\r\nexport const selectSearchCommandContext = createSelector(selectSearchParameters, (searchParameters) => ({\r\n searchParameters,\r\n}));\r\n\r\nexport const selectLocationContentContext = createSelector(\r\n selectLocationType,\r\n selectMarketId,\r\n selectMarketName,\r\n selectCity,\r\n selectCounty,\r\n selectSyntheticName,\r\n selectStateAbbreviation,\r\n selectZip,\r\n selectProductType,\r\n selectBrandId,\r\n selectBrandName,\r\n selectSchoolDistrictName,\r\n selectCommunityName,\r\n selectResultType,\r\n selectPage,\r\n selectSportsFacilities,\r\n selectMoveInDateRange,\r\n (\r\n geoLocationType,\r\n marketId,\r\n marketName,\r\n city,\r\n county,\r\n syntheticName,\r\n stateAbbreviation,\r\n zip,\r\n productType,\r\n brandId,\r\n brandName,\r\n schoolDistrictName,\r\n communityName,\r\n resultType,\r\n pageNumber,\r\n sportsFacilities,\r\n moveInDateRange\r\n ) => ({\r\n geoLocationType,\r\n marketId,\r\n marketName,\r\n city,\r\n county,\r\n syntheticName,\r\n stateAbbreviation,\r\n zip,\r\n productType,\r\n brandId,\r\n brandName,\r\n schoolDistrictName,\r\n communityName,\r\n resultType,\r\n pageNumber,\r\n sportsFacilities,\r\n moveInDateRange,\r\n })\r\n);\r\n\r\nexport const selectSubdirectory = createSelector(\r\n selectResultsType,\r\n selectCondosAndTownHomes,\r\n selectSingleFamily,\r\n selectHomeStatus,\r\n isCustom,\r\n isBuildOnYourLot,\r\n isManufactured,\r\n (resultType, condosAndTownHomes, singleFamily, homeStatus, custom, buildOnYourLot, manufactured) => ({\r\n resultType,\r\n condosAndTownHomes,\r\n singleFamily,\r\n homeStatus,\r\n custom,\r\n buildOnYourLot,\r\n manufactured,\r\n })\r\n);\r\n\r\nexport const selectBrand = createSelector(\r\n selectBrandName,\r\n selectBrandId,\r\n selectResultType,\r\n (brandName, brandId, resultType) => ({\r\n brandName,\r\n brandId,\r\n resultType,\r\n })\r\n);\r\n\r\nexport const selectBrandFilterContext = createSelector(selectBrands, selectBrandId, (brands, brandId) => ({\r\n brands,\r\n brandId,\r\n}));\r\n\r\n// selector created to tap into the features object in the store\r\n// and return the current values of the community amenities.\r\nexport const communityAmenitiesSelector = createSelector(\r\n selectNatureAreas,\r\n selectPool,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectGatedCommunity,\r\n (natureAreas, pool, golfCourse, green, sportsFacilities, parks, views, waterfront, gatedCommunity) => ({\r\n natureAreas,\r\n pool,\r\n golfCourse,\r\n green,\r\n sportsFacilities,\r\n parks,\r\n views,\r\n waterfront,\r\n gatedCommunity,\r\n })\r\n);\r\n\r\nexport const selectContentTemplateTypeModifiers = createSelector(\r\n selectAppliedFacets,\r\n selectProductType,\r\n selectHomeStatus,\r\n selectBrandId,\r\n (appliedFacetList, productType, homeStatus, brandId) => ({ appliedFacetList, productType, homeStatus, brandId })\r\n);\r\n\r\nexport const selectPaginationContext = createSelector(\r\n selectPage,\r\n selectPageSize,\r\n selectListingCount,\r\n (pageNumber, pageSize, listingCount) => ({ pageNumber, pageSize, listingCount })\r\n);\r\n\r\nexport const pageCountSelector = createSelector(selectPageSize, selectListingCount, (pageSize, listingCount) =>\r\n Math.ceil(listingCount / pageSize)\r\n);\r\n\r\nexport const moveInDateSelector = createSelector(\r\n selectHomeStatus,\r\n selectMoveInDateRange,\r\n (homeStatus, moveInDateRange) => ({\r\n homeStatus,\r\n moveInDateRange,\r\n })\r\n);\r\n\r\nexport const isAnyHousingTypeActiveSelector = createSelector(\r\n selectSingleFamily,\r\n selectLuxury,\r\n selectCondosAndTownHomes,\r\n isCustom,\r\n isBuildOnYourLot,\r\n isManufactured,\r\n selectHomeStatus,\r\n (singleFamily, luxury, condosAndTownHomes, custom, buildOnYourLot, manufactured, homeStatus) =>\r\n Boolean(singleFamily || luxury || condosAndTownHomes ||\r\n custom || buildOnYourLot || manufactured || (homeStatus === SpecStatus.Model.toString()))\r\n);\r\n\r\n/**\r\n * selector used to get the facets' current state from the store\r\n * @param {object} state\r\n */\r\nexport const facetsSelector = createSelector(\r\n selectNatureAreas,\r\n selectPool,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectGatedCommunity,\r\n selectRvGarage,\r\n selectReviews,\r\n selectConsumerPromos,\r\n selectPriceReduction,\r\n selectAdult,\r\n selectAgeRestricted,\r\n selectMinimumPrice,\r\n selectMaximumPrice,\r\n selectBathrooms,\r\n selectBedrooms,\r\n selectSchools,\r\n selectBrandId,\r\n selectGarages,\r\n selectMarketingStatus,\r\n selectPrimaryBedroom,\r\n selectStories,\r\n selectLivingAreas,\r\n selectSingleFamily,\r\n selectLuxury,\r\n selectCondosAndTownHomes,\r\n isCustomHomes,\r\n moveInDateSelector,\r\n selectCommunityName,\r\n isManufactured,\r\n selectHomeStatus,\r\n selectExcludeAdult,\r\n selectExcludeAgeRestricted,\r\n selectSorting,\r\n selectHomeOwnersAssociationFee,\r\n (\r\n natureAreas,\r\n pool,\r\n golfCourse,\r\n green,\r\n sportsFacilities,\r\n parks,\r\n views,\r\n waterfront,\r\n gatedCommunity,\r\n rvGarage,\r\n reviews,\r\n consumerPromos,\r\n priceReduction,\r\n adult,\r\n ageRestricted,\r\n minimumPrice,\r\n maximumPrice,\r\n bathrooms,\r\n bedrooms,\r\n schools,\r\n brand,\r\n garages,\r\n marketingStatus,\r\n primaryBedroom,\r\n stories,\r\n livingAreas,\r\n singleFamily,\r\n luxury,\r\n condosAndTownHomes,\r\n customHomes,\r\n moveInDate,\r\n communityName,\r\n manufactured,\r\n homeStatus,\r\n excludeAdult,\r\n excludeAgeRestricted,\r\n sorting,\r\n hasHomeOwnersAssociationFee,\r\n ) => {\r\n const filters = {\r\n natureAreas,\r\n comingsoon: isComingSoon(marketingStatus),\r\n grandOpening: isGrandOpening(marketingStatus),\r\n active: isActive(marketingStatus),\r\n closeOut: isCloseOut(marketingStatus),\r\n pool,\r\n golfCourse,\r\n green,\r\n sportsFacilities,\r\n parks,\r\n views,\r\n waterfront,\r\n gatedCommunity,\r\n rvGarage,\r\n reviews,\r\n hotDeals: consumerPromos,\r\n priceReduction,\r\n moveInDate: isMoveInDateApplied(moveInDate),\r\n modelHomes: hasModelHome(homeStatus),\r\n adult,\r\n ageRestricted,\r\n price: minimumPrice || maximumPrice,\r\n bathrooms: Number(bathrooms),\r\n bedrooms: Number(bedrooms),\r\n schoolDistrict: Boolean(schools?.length),\r\n builderBrand: Number(brand),\r\n garages: Number(garages),\r\n primaryBedroom: Number(primaryBedroom),\r\n stories: Number(stories),\r\n livingAreas: Number(livingAreas),\r\n singleFamily,\r\n luxury,\r\n condosAndTownHomes,\r\n customHomes,\r\n communityName,\r\n manufactured,\r\n exclude55: Boolean(excludeAdult && excludeAgeRestricted),\r\n sort: sorting?.sortBy,\r\n hasHomeOwnersAssociationFee,\r\n };\r\n\r\n return filters;\r\n }\r\n);\r\n\r\n/** this selector is intended to expose all the properties that should be included as common tracking properties.\r\n * the idea behind this is tha here should be placed the selectors/props that are usually used in tracking events.\r\n * then the consumers will filter and take the props they need, this will just serve the information.\r\n */\r\nexport const selectSearchResultFacetsTrackingCommonProperties = createSelector(\r\n selectLocation,\r\n selectBrandInformation,\r\n facetsSelector,\r\n selectPaginationContext,\r\n selectPrice,\r\n selectSchools,\r\n moveInDateSelector,\r\n (location, brandInformation, facetsList, paginationContext, price, schools, moveInDate) => {\r\n const { brandId, brandName } = brandInformation;\r\n const { pageNumber, listingCount } = paginationContext;\r\n return { location, brandId, brandName, facetsList, pageNumber, listingCount, price, schools, moveInDate };\r\n }\r\n);\r\n\r\n/**\r\n * This selector aims to expose all properties that can be used as a filter in a home.\r\n */\r\nexport const homeFactsSelectors = createSelector(\r\n selectRvGarage,\r\n selectBathrooms,\r\n selectBedrooms,\r\n selectGarages,\r\n selectPrimaryBedroom,\r\n selectStories,\r\n selectLivingAreas,\r\n (\r\n rvGarage,\r\n bathrooms,\r\n bedrooms,\r\n garages,\r\n primaryBedroom,\r\n stories,\r\n livingAreas,\r\n ) => {\r\n const filters = {\r\n rvGarage,\r\n bathrooms: Number(bathrooms),\r\n bedrooms: Number(bedrooms),\r\n garages: Number(garages),\r\n primaryBedroom: Number(primaryBedroom),\r\n stories: Number(stories),\r\n livingAreas: Number(livingAreas),\r\n }\r\n return filters;\r\n }\r\n);\r\n\r\n/**\r\n * This selector has the objective of displaying all the properties related to the filters in the SRP all filters menu.\r\n */\r\nexport const facetsPanelSelector = createSelector(\r\n communityAmenitiesSelector,\r\n selectPrice,\r\n homeFactsSelectors,\r\n brandIdAndSchoolsSelector,\r\n otherFiltersSelector,\r\n moveInDateSelector,\r\n housingOptionsSelector,\r\n communityStatusSelector,\r\n (\r\n communityAmenities,\r\n price,\r\n homeFacts,\r\n brandAndSchools,\r\n otherFilters,\r\n moveInDate,\r\n housingOptions,\r\n communityStatus,\r\n ) => {\r\n const filters = {\r\n amenities: communityAmenities,\r\n moveInDate: getMovingDateFilterApplied(moveInDate),\r\n price,\r\n homeFacts,\r\n brandAndSchools,\r\n housingOptions,\r\n communityStatus,\r\n otherFilters,\r\n };\r\n\r\n return filters;\r\n }\r\n);\r\n\r\n/**\r\n * This selector aims to display all the properties related to the filters in the popular search pills.\r\n * When the golf course pill is removed from the popular searches pills, please delete the amenities property from here.\r\n * Ticket where that pill will be removed: https://builderhomesite.atlassian.net/browse/NHS20-2391.\r\n */\r\nexport const selectLinkedPopularPillsFilters = createSelector(\r\n communityAmenitiesSelector,\r\n otherFiltersSelector,\r\n moveInDateSelector,\r\n housingOptionsSelector,\r\n selectMarketingStatus,\r\n (\r\n communityAmenities,\r\n otherFilters,\r\n moveInDate,\r\n housingOptions,\r\n marketingStatus,\r\n ) => {\r\n const filters = {\r\n amenities: communityAmenities,\r\n otherFilters,\r\n moveInDate: getMovingDateFilterApplied(moveInDate),\r\n housingOptions,\r\n comingsoon: isComingSoon(marketingStatus),\r\n };\r\n return filters;\r\n }\r\n);\r\n\r\n/**\r\n * This selectors maps the sorting value along with the result type value from Store.\r\n */\r\nexport const selectResultTypeAndSorting = createSelector(\r\n selectSorting,\r\n selectResultType,\r\n (\r\n sorting,\r\n resultType\r\n ) => ({\r\n sorting,\r\n resultType,\r\n })\r\n);\r\n\r\n/**\r\n * This selector maps all the state properties that can drive an user search.\r\n */\r\nexport const selectSearchModifiers = createSelector(\r\n selectFeatures,\r\n selectFacts,\r\n selectLocation,\r\n selectProduct,\r\n selectResults,\r\n selectResultsModifiers,\r\n selectFetchResultListingsStatus,\r\n (feature, facts, location, product, results, modifiers, fetchResultsListingStatus) => ({\r\n feature,\r\n facts,\r\n location,\r\n product,\r\n results,\r\n modifiers,\r\n fetchResultsListingStatus,\r\n })\r\n);","import LoadingStatus from 'enums/loadingStatus';\r\nimport { camelCaseObjectKeys } from 'utils/camelCase';\r\n\r\nconst searchCommandElement = document.querySelector(\"[data-component='search-command-data']\");\r\n\r\n// Results facets element with Brand and School Districts information.\r\nconst resultFacetsElement = document.querySelector(\"[data-component='results-facets-data']\");\r\n\r\n// Result counts element with the listing counts information.\r\nconst resultCountsElement = document.querySelector(\"[data-component='results-counts-data']\");\r\n\r\nconst initialState = camelCaseObjectKeys(JSON.parse(searchCommandElement.innerHTML));\r\nconst resultFacets = resultFacetsElement ? JSON.parse(resultFacetsElement.innerHTML) : {};\r\nconst resultCounts = resultCountsElement ? JSON.parse(resultCountsElement.innerHTML) : {};\r\ninitialState.counts = {\r\n brands: resultFacets?.Brands || [],\r\n schoolDistricts: resultFacets?.SchoolDistricts || [],\r\n listingCount: resultCounts?.totalListingCount || 0,\r\n adultCount: resultCounts?.adultCount || 0,\r\n comingSoonCount: resultCounts?.comingSoonCount || 0,\r\n hotDealsCount: resultCounts?.hotDealsCount || 0,\r\n buildablePlansCount: resultCounts?.buildablePlansCount || 0,\r\n quickMoveInCount: resultCounts?.quickMoveInCount || 0,\r\n multiFamilyCount: resultCounts?.multiFamilyCount || 0,\r\n};\r\n\r\n// We have to set those fetching statuses to idle as it does not have done anything.\r\n// TODO: Implement the idle status after X time when it got the Succeeded or Failed status.\r\n// In this way, we keep an up-to-date status.\r\ninitialState.fetchResultListingsStatus = LoadingStatus.Idle;\r\ninitialState.fetchResultCountsStatus = LoadingStatus.Idle;\r\ninitialState.fetchSchoolsAndBrandsFacetingStatus = LoadingStatus.Idle;\r\n\r\nexport default initialState;\r\n","import { createSlice } from '@reduxjs/toolkit';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport initialState from './initialState';\r\nimport getDefaultProductType from '../services/productTypeService';\r\nimport { getHomeStatusFilterApplied } from '../services/moveInDateService';\r\nimport getDefaultResultType from '../services/resultTypeService';\r\nimport LocationType from '../enums/locationType';\r\nimport ProductType from '../enums/productType';\r\nimport { hasInventoryStatusCombination } from '../services/homeStatusValidator';\r\nimport { facetsSelector } from './selectors';\r\nimport SortType from '../enums/sortType';\r\nimport ResultType from '../enums/resultType';\r\n\r\nexport const searchParametersSlice = createSlice({\r\n name: 'searchParameters',\r\n initialState,\r\n reducers: {\r\n fetchContentTemplateType: (state, action) => {\r\n state.contentTemplateType = action.payload;\r\n },\r\n fetchSchools: (state, action) => {\r\n const schoolList = action.payload;\r\n const schoolIds = schoolList.map((school) => school.id);\r\n\r\n // We should show the first school name selected.\r\n const firstSchoolName = schoolList[0]?.name || '';\r\n state.features.schoolDistrictIds = schoolIds;\r\n state.features.schoolDistrictName = firstSchoolName;\r\n },\r\n fetchBuilderReviews: (state, action) => {\r\n state.facts.builderReviews = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchConsumerPromos: (state, action) => {\r\n state.facts.consumerPromos = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchPriceReduction: (state, action) => {\r\n state.facts.priceReduction = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchHomeOwnersAssociationFee: (state, action) => {\r\n state.facts.hasHomeOwnersAssociationFee = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchActiveAdult: (state, action) => {\r\n state.features.adult = action.payload;\r\n state.features.ageRestricted = action.payload;\r\n\r\n // toggle the excludes\r\n state.resultsModifiers.excludeAdult = !action.payload;\r\n state.resultsModifiers.excludeAgeRestricted = !action.payload;\r\n\r\n // reset the page\r\n state.results.paging.page = 1;\r\n },\r\n fetchAnyCommunities: (state) => {\r\n // toggle off the excludes\r\n state.resultsModifiers.excludeAdult = false;\r\n state.resultsModifiers.excludeAgeRestricted = false;\r\n\r\n // toggle off the includes\r\n state.features.adult = false;\r\n state.features.ageRestricted = false;\r\n\r\n // reset the page\r\n state.results.paging.page = 1;\r\n },\r\n fetchExcludeActiveAdult: (state, action) => {\r\n state.resultsModifiers.excludeAdult = action.payload;\r\n state.resultsModifiers.excludeAgeRestricted = action.payload;\r\n\r\n // toggle the includes\r\n state.features.adult = !action.payload;\r\n state.features.ageRestricted = !action.payload;\r\n\r\n // reset the page\r\n state.results.paging.page = 1;\r\n },\r\n fetchResultsListingError: (state) => {\r\n state.fetchResultListingsStatus = LoadingStatus.Failed;\r\n },\r\n fetchResultFacetsError: (state) => {\r\n state.counts.brands = [];\r\n state.counts.schoolDistricts = [];\r\n state.counts.counties = [];\r\n state.fetchSchoolsAndBrandsFacetingStatus = LoadingStatus.Failed;\r\n },\r\n fetchPageSize: (state, action) => {\r\n state.results.paging.pageSize = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchPageNumber: (state, action) => {\r\n state.results.paging.page = action.payload;\r\n },\r\n fetchPagingControlsPrev: (state) => {\r\n const newPage = parseInt(state.results.paging.page, 10) - 1;\r\n state.results.paging.page = newPage;\r\n },\r\n fetchPagingControlsNext: (state) => {\r\n const newPage = parseInt(state.results.paging.page, 10) + 1;\r\n state.results.paging.page = newPage;\r\n },\r\n fetchBathrooms: (state, action) => {\r\n const value = action.payload !== '0' ? action.payload : null;\r\n state.facts.minimumBathroom = value;\r\n state.results.paging.page = 1;\r\n },\r\n fetchBedrooms: (state, action) => {\r\n const value = action.payload !== '0' ? action.payload : null;\r\n state.facts.minimumBedroom = value;\r\n state.results.paging.page = 1;\r\n },\r\n fetchLocations: (state, action) => {\r\n // Here we have to assign each property separately because it affects when\r\n // location parameter is compared against itself. If the spread operator is used, it creates\r\n // a new object so the location property comparison fails when its values are the same.\r\n state.location.locationType = LocationType.fromKey(action.payload.locationType)?.toString();\r\n state.location.marketId = action.payload.marketId;\r\n state.location.stateName = action.payload.stateName;\r\n state.location.marketState = action.payload.marketState;\r\n state.location.marketName = action.payload.marketName;\r\n state.location.marketStateName = action.payload.marketStateName;\r\n state.location.geoLocationState = action.payload.geoLocationState;\r\n state.location.city = action.payload.city;\r\n state.location.county = action.payload.county;\r\n state.location.syntheticGeographicName = action.payload.syntheticGeographicName;\r\n state.location.zip = action.payload.zip;\r\n state.location.originLatitude = action.payload.originLatitude;\r\n state.location.originLongitude = action.payload.originLongitude;\r\n state.location.minimumLatitude = action.payload.minimumLatitude;\r\n state.location.maximumLatitude = action.payload.maximumLatitude;\r\n state.location.minimumLongitude = action.payload.minimumLongitude;\r\n state.location.maximumLongitude = action.payload.maximumLongitude;\r\n\r\n state.results.paging.page = 1;\r\n\r\n state.facts.brandId = null;\r\n state.facts.brandName = '';\r\n },\r\n fetchPrice: (state, action) => {\r\n const { minimumPrice, maximumPrice, maximumPriceLimit } = action.payload;\r\n const isMaximum = maximumPriceLimit === maximumPrice;\r\n state.facts.price.minimumPrice = minimumPrice;\r\n // send null if the maximum value is the maximum value of the slider, to avoid removing\r\n // listings with a price range higher than the maximum value of the slider.\r\n state.facts.price.maximumPrice = !isMaximum ? maximumPrice : null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchResultsType: (state, action) => {\r\n // We have to deactivate the All Quick Move In option (Inventory) if we switches to Communities tab.\r\n const shouldRemoveInventoryStatus = action.payload.productType === ProductType.Communities.toString() && \r\n hasInventoryStatusCombination(state.facts.homeStatus);\r\n if (shouldRemoveInventoryStatus) {\r\n state.facts.homeStatus = '';\r\n }\r\n\r\n state.product.productType = action.payload.productType;\r\n state.results.resultType = action.payload.resultType;\r\n state.results.paging.page = 1;\r\n\r\n const sortType = SortType.fromKey(state.results.sorting.sortBy);\r\n const resultType = ResultType.fromKey(state.results.resultType);\r\n\r\n if (!sortType?.validResultTypes.includes(resultType)) {\r\n state.results.sorting = {\r\n sortBy: null,\r\n };\r\n }\r\n },\r\n fetchSort: (state, action) => {\r\n state.results.sorting = {\r\n sortBy: action.payload.sortBy,\r\n sortOrder: action.payload.sortOrder,\r\n sortFirstBy: action.payload.sortFirstBy,\r\n };\r\n state.results.paging.page = 1;\r\n },\r\n fetchLivingAreas: (state, action) => {\r\n state.facts.livingAreas = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchStories: (state, action) => {\r\n state.facts.stories = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchPrimaryBedroom: (state, action) => {\r\n state.facts.primaryBedroom = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchGarages: (state, action) => {\r\n state.facts.garages = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchGolfCourse: (state, action) => {\r\n state.features.golfCourse = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchMarketingStatus: (state, action) => {\r\n state.facts.marketingStatus = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n fetchAmenities: (state, action) => {\r\n // assign either the new value or the existing value\r\n // we need to do this since using the spread operator doesn't\r\n // work with nested objects when using selectors to get the latest values\r\n state.features.natureAreas = action.payload.natureAreas;\r\n state.features.pool = action.payload.pool;\r\n state.features.golfCourse = action.payload.golfCourse;\r\n state.features.green = action.payload.green;\r\n state.features.sportsFacilities = action.payload.sportsFacilities;\r\n state.features.parks = action.payload.parks;\r\n state.features.views = action.payload.views;\r\n state.features.waterfront = action.payload.waterfront;\r\n state.features.gatedCommunity = action.payload.gatedCommunity;\r\n\r\n state.results.paging.page = 1;\r\n },\r\n fetchMoveInDateByStatus: (state, action) => {\r\n state.facts.homeStatus = action.payload;\r\n state.facts.moveInDateRange = null;\r\n state.results.paging.page = 1;\r\n\r\n // changing the result type to homes since we don't have communities\r\n // with move in dates\r\n state.results.resultType = 'homes';\r\n state.product.productType = 'homes';\r\n },\r\n clearMoveInDateFilter: (state) => {\r\n state.facts.homeStatus = null;\r\n state.facts.moveInDateRange = null;\r\n state.results.paging.page = 1;\r\n },\r\n clearFilters: (state) => {\r\n // resetting the features and facts from the state.\r\n const productType = getDefaultProductType(state.product.productType, state.results.resultType);\r\n const resultType = getDefaultResultType(state.results.resultType);\r\n state.features = {};\r\n state.resultsModifiers = {};\r\n state.facts = {\r\n price: {},\r\n };\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n\r\n // setting the page as page 1\r\n state.results.paging.page = 1;\r\n\r\n state.results.sorting = {\r\n sortBy: null,\r\n };\r\n },\r\n fetchMoveInDateByRange: (state, action) => {\r\n state.facts.homeStatus = null;\r\n state.facts.moveInDateRange = action.payload;\r\n state.results.paging.page = 1;\r\n\r\n // changing the result type to homes since we don't have communities\r\n // with move in dates\r\n state.results.resultType = 'homes';\r\n state.product.productType = 'homes';\r\n },\r\n fetchResultListings: (state) => {\r\n state.fetchResultListingsStatus = LoadingStatus.Loading;\r\n },\r\n fetchResultCounts: (state) => {\r\n state.fetchResultCountsStatus = LoadingStatus.Loading;\r\n },\r\n fetchSchoolsAndBrandsFaceting: (state) => {\r\n state.fetchSchoolsAndBrandsFacetingStatus = LoadingStatus.Loading;\r\n },\r\n fetchResultFacetsFulfilled: (state, action) => {\r\n state.counts.brands = action.payload.Brands;\r\n state.counts.schoolDistricts = action.payload.SchoolDistricts;\r\n state.counts.counties = action.payload.Counties;\r\n state.fetchSchoolsAndBrandsFacetingStatus = LoadingStatus.Succeeded;\r\n },\r\n fetchResultsCountsFulfilled: (state, action) => {\r\n state.counts.listingCount = action.payload.ListingCount;\r\n state.counts.hotDealsCount = action.payload.HotDealsCount;\r\n state.counts.comingSoonCount = action.payload.ComingSoonCount;\r\n state.counts.adultCount = action.payload.AdultCount;\r\n state.counts.buildablePlansCount = action.payload.BuildablePlansCount;\r\n state.counts.quickMoveInCount = action.payload.QuickMoveInCount;\r\n state.counts.multiFamilyCount = action.payload.MultiFamilyCount;\r\n state.counts.listingCount = action.payload.ListingCount;\r\n state.fetchResultCountsStatus = LoadingStatus.Succeeded;\r\n },\r\n fetchResultsCountsError: (state) => {\r\n state.counts.listingCount = 0;\r\n state.fetchResultCountsStatus = LoadingStatus.Failed;\r\n },\r\n fetchResultsListingFulfilled: (state) => {\r\n state.fetchResultListingsStatus = LoadingStatus.Succeeded;\r\n },\r\n fetchCustom: (state, action) => {\r\n const { resultType, productType } = action.payload;\r\n const homeStatusApplied = getHomeStatusFilterApplied(state.results.homeStatus);\r\n const newHomeStatus = state.results?.homeStatus?.replace(state.results.homeStatus, homeStatusApplied) || null;\r\n state.features.singleFamily = false;\r\n state.features.luxury = false;\r\n state.features.condosAndTownHomes = false;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = newHomeStatus;\r\n state.facts.moveInDateRange = null;\r\n state.facts.homeStatus = null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchSingleFamily: (state, action) => {\r\n const { resultType, productType, singleFamily } = action.payload;\r\n state.features.singleFamily = singleFamily;\r\n state.features.luxury = false;\r\n state.features.condosAndTownHomes = false;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchModelHome: (state, action) => {\r\n const { resultType, productType, homeStatus } = action.payload;\r\n state.facts.homeStatus = homeStatus;\r\n state.features.singleFamily = false;\r\n state.features.luxury = false;\r\n state.features.condosAndTownHomes = false;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.results.paging.page = 1;\r\n },\r\n fetchLuxury: (state, action) => {\r\n const { resultType, productType, luxury } = action.payload;\r\n state.features.singleFamily = false;\r\n state.features.luxury = luxury;\r\n state.features.condosAndTownHomes = false;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchCondosAndTownHomes: (state, action) => {\r\n const { resultType, productType, condosAndTownHomes } = action.payload;\r\n state.features.singleFamily = false;\r\n state.features.luxury = false;\r\n state.features.condosAndTownHomes = condosAndTownHomes;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchManufactured: (state, action) => {\r\n const { resultType, productType } = action.payload;\r\n const homeStatusApplied = getHomeStatusFilterApplied(state.results.homeStatus);\r\n const newHomeStatus = state.results?.homeStatus?.replace(state.results.homeStatus, homeStatusApplied) || null;\r\n state.features.singleFamily = false;\r\n state.features.luxury = false;\r\n state.features.condosAndTownHomes = false;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = newHomeStatus;\r\n state.facts.moveInDateRange = null;\r\n state.results.paging.page = 1;\r\n },\r\n fetchBrandId: (state, action) => {\r\n const brand = action.payload.brand;\r\n const brandId = brand.id || null;\r\n state.facts.brandId = brandId;\r\n state.facts.brandName = brand.name;\r\n },\r\n fetchViewBrandResults: (state, action) => {\r\n const brand = action.payload.brand;\r\n const brandId = brand.id || null;\r\n state.facts.brandId = brandId;\r\n state.facts.brandName = brand.name;\r\n state.results.resultType = action.payload.resultType;\r\n state.product.productType = action.payload.productType;\r\n state.results.paging.page = 1;\r\n },\r\n fetchViewBrandMarketResults: (state, action) => {\r\n const brand = action.payload.brand;\r\n const brandId = brand.id || null;\r\n state.facts.brandId = brandId;\r\n state.facts.brandName = brand.name;\r\n state.results.resultType = action.payload.resultType;\r\n state.product.productType = action.payload.productType;\r\n state.location.locationType = action.payload.locationType;\r\n state.location.city = \"\";\r\n state.location.county = \"\";\r\n state.location.zip = \"\";\r\n state.location.syntheticGeographicName = \"\";\r\n state.results.paging.page = 1;\r\n }, \r\n fetchRvGarages: (state, action) => {\r\n state.facts.recreationalVehicleGarage = action.payload;\r\n state.results.paging.page = 1;\r\n },\r\n changeZipSearchtoCitySearch: (state) => {\r\n state.location.zip = null;\r\n state.location.locationType = LocationType.City.toString();\r\n },\r\n clearModelHomeStatusFilter: (state) => {\r\n state.facts.homeStatus = null;\r\n state.results.paging.page = 1;\r\n },\r\n toggleCurrentLocationSearch: (state, action) => {\r\n state.isCurrentLocationSearch = action.payload;\r\n },\r\n fetchInteractiveSitePlanResults: (state, action) => {\r\n state.results.paging.page = 1;\r\n state.results.resultType = action.payload.resultType;\r\n state.product.productType = action.payload.productType;\r\n },\r\n allOptions: (state, action) => {\r\n const { resultType, productType } = action.payload;\r\n state.product.productType = productType;\r\n state.results.resultType = resultType;\r\n state.facts.homeStatus = action.payload.homeStatus;\r\n state.features.singleFamily = false;\r\n state.features.condosAndTownHomes = false;\r\n state.features.luxury = false;\r\n // setting the page as page 1\r\n state.results.paging.page = 1;\r\n },\r\n },\r\n});\r\n\r\nconst searchParams = {\r\n searchParameters: initialState,\r\n}\r\n\r\n/**\r\n * getAppliedFilters: this function takes an object containing the current applied filters and\r\n * transforms it into an array. Each filter is represented with a common name that is easily\r\n * understandable by other components that need to access these filters.\r\n * @param {Object} payload represents the an object with the derived filters from Search Parameters.\r\n * @param {Array} appliedFilters array containing any current applied filter.\r\n * @returns an array with all the filters applied.\r\n */\r\nconst getAppliedFilters = (payload, appliedFilters) => { \r\n // Get a list of filters that have been applied and whether to add/remove from the applied filters\r\n const filters = Object.keys(payload).map((key) => ({ key, add: !!payload[key] }));\r\n \r\n filters.forEach((filter) => {\r\n const key = filter.key.toLowerCase();\r\n const isCurrentlyActive = appliedFilters.includes(key);\r\n \r\n // Add the filter to the list of applied filters only if it's not already there\r\n if (filter.add && !isCurrentlyActive) {\r\n appliedFilters.push(key);\r\n }\r\n \r\n // Remove the filter from the list of applied filters only if it's already there\r\n if (!filter.add && isCurrentlyActive) {\r\n const indexToRemove = appliedFilters.findIndex((item) => item === key);\r\n appliedFilters.splice(indexToRemove, 1);\r\n }\r\n });\r\n\r\n return appliedFilters;\r\n};\r\n\r\nexport const facetsSlice = createSlice({\r\n name: 'facetsState',\r\n initialState: {\r\n appliedFilters: getAppliedFilters(facetsSelector(searchParams), []).sort(),\r\n },\r\n reducers: {\r\n updateFilters: (state, action) => {\r\n state.appliedFilters = getAppliedFilters(action.payload, state.appliedFilters);\r\n },\r\n },\r\n});\r\n","import PlanStatus from '../enums/planStatus';\r\nimport SpecStatus from '../enums/specStatus';\r\n\r\n/**\r\n * It checks if the homeStatus has AvailableNow (A).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasAvailableNow = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some(\r\n (key) => PlanStatus.fromKey(key) === PlanStatus.AvailableNow || SpecStatus.fromKey(key) === SpecStatus.AvailableNow\r\n );\r\n};\r\n\r\n/**\r\n * It checks if the homeStatus has ReadyToBuild (R).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasReadyToBuild = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some(\r\n (key) => PlanStatus.fromKey(key) === PlanStatus.ReadyToBuild || SpecStatus.fromKey(key) === SpecStatus.ReadyToBuild\r\n );\r\n};\r\n\r\n/**\r\n * It checks if the homeStatus has UnderConstruction (UC).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasUnderConstruction = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some(\r\n (key) =>\r\n PlanStatus.fromKey(key) === PlanStatus.UnderConstruction ||\r\n SpecStatus.fromKey(key) === SpecStatus.UnderConstruction\r\n );\r\n};\r\n\r\n/**\r\n * It checks if the homeStatus has Model (M).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasModelHome = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some((key) => SpecStatus.fromKey(key) === SpecStatus.Model);\r\n};\r\n\r\n/**\r\n * It checks if the homeStatus has Hot Deal (H)\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasHotDeal = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some(\r\n (key) => PlanStatus.fromKey(key) === PlanStatus.HotDeals || SpecStatus.fromKey(key) === SpecStatus.HotDeals\r\n );\r\n};\r\n\r\n/**\r\n * It checks if the homeStatus has Inventory status combination (A,UC).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const hasInventoryStatusCombination = (homeStatus) => {\r\n const isAvailableNowIncluded = hasAvailableNow(homeStatus);\r\n const isUnderConstructionIncluded = hasUnderConstruction(homeStatus);\r\n\r\n return isAvailableNowIncluded && isUnderConstructionIncluded;\r\n};\r\n\r\n/**\r\n * Returns the Inventory status combination (A,UC).\r\n * @param homeStatus - The status of the home.\r\n */\r\nexport const getInventoryStatusCombination = () => {\r\n const inventoryStatuses = [SpecStatus.AvailableNow.name, SpecStatus.UnderConstruction.name];\r\n\r\n return inventoryStatuses.join(',');\r\n};","import MoveInDate from '../enums/moveInDate';\r\nimport PlanStatus from '../enums/planStatus';\r\nimport {\r\n getInventoryStatusCombination,\r\n hasAvailableNow,\r\n hasInventoryStatusCombination,\r\n hasReadyToBuild,\r\n} from './homeStatusValidator';\r\n\r\n/**\r\n * A function that verifies if move in date filters are applied.\r\n *\r\n * When the home status Available Now, Ready to Build or move in data range are applied\r\n * the move in date filter is applied. Otherwise false.\r\n */\r\nfunction isMoveInDateApplied(selector) {\r\n const { homeStatus, moveInDateRange } = selector;\r\n // For All Quick Move In option.\r\n if (hasInventoryStatusCombination(homeStatus)) {\r\n return true;\r\n }\r\n\r\n // For Move Now option.\r\n if (hasAvailableNow(homeStatus)) {\r\n return true;\r\n }\r\n\r\n // For Buildable plans option.\r\n if (hasReadyToBuild(homeStatus)) {\r\n return true;\r\n }\r\n\r\n // For Move In date ranges options.\r\n if (\r\n moveInDateRange === MoveInDate.OneToTwoMonths.toString() ||\r\n moveInDateRange === MoveInDate.ThreeToSixMonths.toString()\r\n ) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Gets the home status filter applied from the state.\r\n * @param {string} homeStatus The home status search parameter value.\r\n * @returns The type of home status filter applied if any.\r\n */\r\nconst getHomeStatusFilterApplied = (homeStatus) => {\r\n if (hasInventoryStatusCombination(homeStatus)) {\r\n return getInventoryStatusCombination();\r\n }\r\n\r\n if (hasAvailableNow(homeStatus)) {\r\n return PlanStatus.AvailableNow.toString();\r\n }\r\n\r\n if (hasReadyToBuild(homeStatus)) {\r\n return PlanStatus.ReadyToBuild.toString();\r\n }\r\n\r\n return '';\r\n};\r\n\r\n/**\r\n * Gets the move in date filter applied from the state.\r\n * @param {string} moveInDateRange The move in date range search parameter value.\r\n * @returns the move in date filter applied if any.\r\n */\r\nconst getMoveInDateFilterApplied = (moveInDateRange) => {\r\n switch (moveInDateRange) {\r\n case MoveInDate.OneToTwoMonths.toString():\r\n return MoveInDate.OneToTwoMonths.toString();\r\n case MoveInDate.ThreeToSixMonths.toString():\r\n return MoveInDate.ThreeToSixMonths.toString();\r\n case MoveInDate.BuildablePlans.toString():\r\n return MoveInDate.BuildablePlans.toString();\r\n default:\r\n return '';\r\n }\r\n};\r\n\r\n/**\r\n * Return the move in date filter applied according to home status or moveInDateRange search parameters.\r\n */\r\nconst getMovingDateFilterApplied = (parameters) => {\r\n const { homeStatus, moveInDateRange } = parameters;\r\n const homeStatusFilterApplied = getHomeStatusFilterApplied(homeStatus);\r\n\r\n if (homeStatusFilterApplied) {\r\n return homeStatusFilterApplied;\r\n }\r\n\r\n const moveInDateFilterApplied = getMoveInDateFilterApplied(moveInDateRange);\r\n if (moveInDateFilterApplied) {\r\n return moveInDateFilterApplied;\r\n }\r\n\r\n return '';\r\n};\r\n\r\nexport { isMoveInDateApplied, getMovingDateFilterApplied, getHomeStatusFilterApplied };\r\n","import ProductType from '../enums/productType';\r\nimport ResultType from '../enums/resultType';\r\n\r\n/**\r\n * The function `getDefaultProductType` returns a default product type based on the input product type.\r\n * @param productType - The `productType` parameter is a variable that represents the type of product.\r\n * @returns The function `getDefaultProductType` returns a string value representing the default\r\n * product type.\r\n */\r\nconst getDefaultProductType = (productType, resultType = '') => {\r\n switch (true) {\r\n case productType === ProductType.BuildOnYourLot.toString() && ResultType.Locations.toString() === resultType:\r\n case productType === ProductType.Communities.toString():\r\n case productType === ProductType.Manufactured.toString() && ResultType.Locations.toString() === resultType:\r\n return ProductType.Communities.toString();\r\n\r\n case productType === ProductType.Custom.toString() && ResultType.Homes.toString() === resultType:\r\n case productType === ProductType.Homes.toString():\r\n case productType === ProductType.Manufactured.toString() && ResultType.Homes.toString() === resultType:\r\n return ProductType.Homes.toString();\r\n\r\n case productType === ProductType.Custom.toString() && ResultType.Builders.toString() === resultType:\r\n return ProductType.Communities.toString();\r\n // This return is going to be evaluated once we're going to develop the Custom Builder feature, pointing to \r\n // Communities in the meantime. \r\n\r\n default:\r\n return ProductType.Communities.toString();\r\n }\r\n};\r\n\r\nexport default getDefaultProductType;\r\n","import ResultType from '../enums/resultType';\r\n\r\n/**\r\n * The function `getDefaultResultType` returns a default result type based on the input result type.\r\n * @param resultType - The `resultType` parameter is a variable that represents the type of result that\r\n * is being requested.\r\n * @returns The function `getDefaultResultType` returns a string value.\r\n */\r\nconst getDefaultResultType = (resultType) => {\r\n switch (resultType) {\r\n case ResultType.Locations.toString():\r\n case ResultType.Communities.toString():\r\n return ResultType.Communities.toString();\r\n\r\n case ResultType.Homes.toString():\r\n return ResultType.Homes.toString();\r\n\r\n case ResultType.Builders.toString():\r\n return ResultType.Builders.toString();\r\n\r\n default:\r\n return ResultType.Communities.toString();\r\n }\r\n};\r\n\r\nexport default getDefaultResultType;\r\n","/**\r\n * This file is designed only for the events related to search within map. For example, \r\n * when the toogle is activated or not.\r\n * It usually means that the action should have to save information on the store.\r\n */\r\n\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { mapStateActions } from 'features/searchResultsMap';\r\nimport { store } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { geoCoordinates } from '../redux/selectors';\r\n\r\nconst mapSearchEvent = 'Map Search';\r\n\r\n// Created the label with the current search coordinates\r\nfunction getCoordinatesLabel() { \r\n const coordinates = geoCoordinates(store.getState());\r\n const coordinatesLabel = `east: ${coordinates.east}, north: ${coordinates.north}, south: ${coordinates.south}, west: ${coordinates.west}`;\r\n \r\n return coordinatesLabel;\r\n}\r\n\r\n// Fires the event when the search within map functionality is activated. Gets current coordinates.\r\nconst toogleOn = () => { \r\n const customDimensions = {};\r\n\r\n customDimensions[[GoogleAnalyticsCustomDimensions.SearchWithinMapActivated().getName()]] =\r\n 'true';\r\n \r\n return new GoogleAnalyticsEvent(mapSearchEvent, 'Toggle On', getCoordinatesLabel(), customDimensions);\r\n}\r\n\r\n\r\n// Fires the event when the search within map functionality is deactivated. Gets current coordinates.\r\n const toogleOff = () => { \r\n const customDimensions = {};\r\n \r\n customDimensions[[GoogleAnalyticsCustomDimensions.SearchWithinMapActivated().getName()]] =\r\n 'false';\r\n \r\n return new GoogleAnalyticsEvent(mapSearchEvent, 'Toggle Off', getCoordinatesLabel(), customDimensions);\r\n }\r\n\r\n\r\nconst eventsMapper = (action) => {\r\n switch (action.type) {\r\n case mapStateActions.enableSearchWithinMap.type:\r\n return debounceEvent(100, toogleOn);\r\n case mapStateActions.disableSearchWithinMap.type:\r\n return debounceEvent(100, toogleOff);\r\n\r\n default:\r\n return [];\r\n }\r\n };\r\n \r\n const googleTagManager = new GoogleTagManager();\r\n const searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\n addMiddleware(searchResultsGoogleTagManagerMiddleware);","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getCommunitySummaryCard } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves community summary information from a given id.\r\n * @param {Object} communityId - community identifier to query.\r\n * @returns {Observable} - An observable that emits the commuinty summary information.\r\n */\r\nconst getCommunitySummaryCardInformation = (communityId) => {\r\n const url = `${getCommunitySummaryCard}?id=${communityId}`;\r\n \r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n};\r\n\r\nexport default getCommunitySummaryCardInformation;","/**\r\n* This module is designed to seamlessly modify the map's view in response to location changes.\r\n* Such changes can occur during the initial page load or when users utilize the typeahead feature to navigate to \r\n* new locations. The fundamental aim of this module is to elevate user experience by maintaining an ideal zoom level\r\n* on the map. By doing so, users can effortlessly explore all pertinent results within their designated\r\n* area of interest, eliminating the need for manual adjustments.\r\n*/\r\n\r\nimport { updateBoundaries, drawBoundary } from 'libraries/mapLibrary';\r\nimport { store$ } from '@redux/store';\r\nimport { \r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n distinctUntilKeyChanged,\r\n withLatestFrom,\r\n tap,\r\n fromEvent,\r\n combineLatest } from 'rxjs';\r\nimport messageService from 'layout/services/messageService';\r\nimport { LocationType, selectLocation } from \"features/searchResultsFacets\";\r\nimport { isSearchWithinMapEnabled, isMapLibraryLoaded } from '../redux/selectors';\r\nimport { locationSearchParameters } from '../constants/searchParametersConstants';\r\n\r\nconst message$ = messageService.getMessage();\r\nconst boundaryProperties = [\"MinLatitude\", \"MinLongitude\", \"MaxLatitude\", \"MaxLongitude\"];\r\n\r\n/**\r\n * This observable tells us whenever there was a custom event triggered in the document\r\n * indicading the presence of new boundaries shown in the map.\r\n */\r\nconst onNewBoundariesShown$ = fromEvent(document, 'newBoundariesShown');\r\n\r\n/**\r\n * This observable tells us whenever there was a location change in the store.\r\n */\r\nconst newLocation$ = store$\r\n.pipe(\r\n filter(selectLocation),\r\n filter((state) => !isSearchWithinMapEnabled(state)),\r\n filter((state) => locationSearchParameters(state).locationType !== LocationType.RectangularArea.toString()),\r\n map(selectLocation),\r\n distinctUntilChanged()\r\n)\r\n\r\n/**\r\n * This observable tells us whenever the map is ready to receive operations on it.\r\n */\r\nconst onMapLoaded$ = store$\r\n.pipe(\r\n filter(isMapLibraryLoaded),\r\n map(isMapLibraryLoaded),\r\n distinctUntilChanged()\r\n)\r\n\r\n/**\r\n * Subscribing to the messaging service.\r\n * When there are new boundaries that contains a results set, map changes its geoCoordinates to these given boundaries.\r\n * As new boundaries constitute the core observable, the withLatestFrom operator pairs most recent boundaries fetched\r\n * with the latest location information, facilitated by the distinctUntilKeyChanged opertor.\r\n * Consequently, the resulting mapped value consistently represents both the boundaries and the user's current map view.\r\n * This observable will emit if and only if the map is ready, that is why we have a combineLatest operator on both\r\n * observables: on new messages, and on map loaded.\r\n */\r\ncombineLatest([message$, onMapLoaded$])\r\n.pipe(\r\n map(([newMessages]) => newMessages),\r\n withLatestFrom(newLocation$),\r\n map(([newMessages, newLocationSource]) => ({\r\n locations: newLocationSource,\r\n boundaries: newMessages.payload.mapBoundaries,\r\n messageType: newMessages.messageType,\r\n })),\r\n distinctUntilKeyChanged('locations'),\r\n filter((information) => information.messageType === 'mapBoundaries'),\r\n tap((information) => { drawBoundary(information.boundaries?.BoundaryUrl) }),\r\n filter((information) => information.boundaries),\r\n filter((information) => !information.boundaries?.BoundaryUrl)\r\n ).subscribe((information) => setTimeout(updateBoundaries.bind(this, information.boundaries), 0));\r\n\r\n/*\r\n Subscribing to the store.\r\n When search within map is enabled, we have to clean the search boundary since results are\r\n going to be shown outside of it.\r\n The way of cleaning it is to call the function that draws boundaries with a null argument for the boundary url.\r\n*/\r\nstore$\r\n .pipe(\r\n map(isSearchWithinMapEnabled),\r\n distinctUntilChanged()\r\n )\r\n .subscribe((isSearchWithinMap) => {\r\n if (isSearchWithinMap) {\r\n drawBoundary();\r\n }\r\n });\r\n\r\n /**\r\n * Subscribing to the messaging service.\r\n * When there are new boundaries for the auto zoom fit functionality on paid markers, and also there is a\r\n * new boundary shown on the map that shows a visual hint for the location searched, this observable will\r\n * grab both pieces of information and auto fit the map zoom so the boundary and the paid markers are all\r\n * visible on screen.\r\n * This is particular useful for searches like zip codes, where the search type is not exact but radius, so\r\n * information appear outside of the boundary around the interested area.\r\n * This observable will emit if and only if the map is ready, that is why we have a combineLatest operator on both\r\n * observables: on new boundaries, and on map loaded.\r\n */\r\n combineLatest([onNewBoundariesShown$, onMapLoaded$])\r\n .pipe(\r\n map(([newBoundary]) => newBoundary),\r\n withLatestFrom(message$, newLocation$),\r\n map(([newBoundary, newMessage, newLocation]) => {\r\n /*\r\n if there is no marker boundaries, it means either we are showing just basic results, or it could be that\r\n there are no results at all to show based on the user's search criteria. By rule, we don't do auto fit on\r\n basic results. Additionally, in cases where there are no results, there are no subjects to auto-fit on the map.\r\n For these scenarios, we are relying just on the location boundaries (if any) for auto fit the map zoom,\r\n since this is, at the end of the day, the area the user is interested in finding a home.\r\n */\r\n const areThereMarkerBoundaries = newMessage?.payload?.mapBoundaries &&\r\n boundaryProperties.every((property) => Object.hasOwn(newMessage?.payload?.mapBoundaries, property));\r\n\r\n const markerBoundary = areThereMarkerBoundaries\r\n ? newMessage?.payload?.mapBoundaries\r\n : newBoundary?.detail?.boundaries;\r\n\r\n return {\r\n markerBoundary,\r\n locationBoundary: newBoundary?.detail?.boundaries,\r\n locationType: newLocation?.locationType?.toLowerCase(),\r\n }\r\n }),\r\n filter(({ locationBoundary }) =>\r\n boundaryProperties.every((property) => Object.hasOwn(locationBoundary, property))),\r\n map(({ locationBoundary, markerBoundary }) => ({\r\n MinLatitude: Math.min(locationBoundary.MinLatitude, markerBoundary.MinLatitude),\r\n MaxLatitude: Math.max(locationBoundary.MaxLatitude, markerBoundary.MaxLatitude),\r\n MinLongitude: Math.min(locationBoundary.MinLongitude, markerBoundary.MinLongitude),\r\n MaxLongitude: Math.max(locationBoundary.MaxLongitude, markerBoundary.MaxLongitude),\r\n })))\r\n .subscribe((boundaries) => setTimeout(updateBoundaries.bind(this, boundaries), 0));","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getCommunityInteractiveSitePlanMarkers } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves community interactive site plan markers associated with a given community id list.\r\n * @param {Object} payload - The payload containing the list of community ids.\r\n * @returns {Observable} - An observable that emits the community interactive site plans information.\r\n */\r\nconst getCommunityInteractiveSitePlans = (payload) => {\r\n const queryParams = new URLSearchParams({ communityIds: payload.communityIds });\r\n\r\n return fromFetch(`${getCommunityInteractiveSitePlanMarkers}?${queryParams.toString()}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n};\r\n\r\nexport default getCommunityInteractiveSitePlans;","/**\r\n * This service will handle the logic for creating the interactive site plan markers to place on top of\r\n * the site plans in the Search Results Page.\r\n */\r\n\r\nimport { catchError, mergeMap, of } from \"rxjs\";\r\nimport getCommunityInteractiveSitePlans$ from \"../apis/getCommunityInteractiveSitePlans\";\r\nimport { zoomLevelLayersLookup } from \"../constants/sitePlansConstants\";\r\nimport SitePlanLayer from \"../enums/sitePlanLayer\";\r\nimport LotStatus from \"../enums/lotStatus\";\r\n\r\n/**\r\n * assignLotPathId: there are Interactive Site Plans that don't have the lot polygons identified.\r\n * This function is in charge of assigning IDs based on a pixel in the #lots group.\r\n * @param {int} communityId the site plan identifier \r\n */\r\nexport const assignLotPathId = (sitePlanId) => {\r\n const sitePlanSvg = document.querySelector(`[data-site-plan-id=\"${sitePlanId}\"]`);\r\n const polygonsContainer = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n const lotPaths = polygonsContainer?.querySelectorAll('#lot_polygons path:not([id])');\r\n const lotsSvg = sitePlanSvg?.querySelector(`#${SitePlanLayer.Lots.id}`)?.closest('svg');\r\n const lotPixels = lotsSvg?.querySelectorAll('.anchor');\r\n\r\n if (lotPaths.length === 0 || !lotsSvg) {\r\n lotsSvg?.remove();\r\n return;\r\n }\r\n\r\n lotPixels.forEach((pixel) => {\r\n pixel.style.display = \"block\";\r\n const pixelBounds = pixel.getBoundingClientRect(); \r\n const lotPath = Array.from(lotPaths).find((path) => {\r\n const pathBounds = path.getBoundingClientRect();\r\n const shrinkFactor = 0.5;\r\n const shrunkPathBounds = {\r\n left: pathBounds.left + pathBounds.width * (1 - shrinkFactor) / 2,\r\n right: pathBounds.right - pathBounds.width * (1 - shrinkFactor) / 2,\r\n top: pathBounds.top + pathBounds.height * (1 - shrinkFactor) / 2,\r\n bottom: pathBounds.bottom - pathBounds.height * (1 - shrinkFactor) / 2\r\n };\r\n\r\n return !(\r\n shrunkPathBounds.right < pixelBounds.left ||\r\n shrunkPathBounds.left > pixelBounds.right ||\r\n shrunkPathBounds.bottom < pixelBounds.top ||\r\n shrunkPathBounds.top > pixelBounds.bottom);\r\n });\r\n\r\n const lotId = pixel.getAttribute('id').replace('a', 'l');\r\n lotPath?.setAttribute('id', lotId);\r\n pixel.style.display = \"none\";\r\n });\r\n\r\n lotsSvg.remove();\r\n};\r\n\r\n/**\r\n * createMarkerHtmlElement function is in charge of building the HTML node of a single interactive marker.\r\n * @param {Object} marker containing information to build a marker and render it on screen.\r\n * @param {HTML} container to hold the created markers.\r\n * @returns the HTML of the created marker.\r\n */\r\nconst createMarkerHtmlElement = (marker, container) => {\r\n const newMarkerElement = document.createElement('div');\r\n newMarkerElement.innerHTML =\r\n ``;\r\n\r\n container.appendChild(newMarkerElement);\r\n return newMarkerElement;\r\n};\r\n\r\n/**\r\n * addInteractiveSitePlan function will be called whenever a new set of interactive\r\n * markers is added as a layer on top of the map in the Search Results Page.\r\n * @param {Array} markers to be rendered on top of a site plan.\r\n * @param {HTML} container to render the interactive markers in.\r\n * @param {int} communityId to be emited as a custom event when the markers are created. \r\n */\r\nexport const addInteractiveSitePlan = ({ markers, container, communityId }) => {\r\n markers?.filter((marker) =>\r\n marker.Status === LotStatus.Sold.toString() ||\r\n !!marker.HousingUnitId ||\r\n marker.HousePlanIds.length > 0)\r\n .forEach((marker) => createMarkerHtmlElement(marker, container, communityId));\r\n};\r\n\r\n/**\r\n * drawInteractiveSitePlan function draws a set of markers.\r\n * @param {Array} markers to draw on the map.\r\n * @param {HTML} container to hold the created markers.\r\n * @param {int} scale pixels to consider when drawing the map.\r\n */\r\nexport const drawInteractiveSitePlan = ({ markers, container, scale, sitePlanId, communityId }) => {\r\n const smallSizeZoom = 18;\r\n const mediumSizeZoom = 19;\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('interactiveMarkersReady', {\r\n detail: {\r\n communityId,\r\n sitePlanId,\r\n },\r\n })\r\n );\r\n\r\n markers.forEach((marker) => {\r\n const markerElement = container.querySelector(`[data-interactive-marker-id=\"${marker.Id}\"]`);\r\n\r\n if (!markerElement) {\r\n return;\r\n }\r\n\r\n if (!marker.isVisible) {\r\n markerElement.style.display = 'none';\r\n return;\r\n }\r\n\r\n markerElement.className = 'interactive-lot_marker';\r\n markerElement.style.left = `${marker.center.x - scale / 2}px`;\r\n markerElement.style.top = `${marker.center.y - scale / 2}px`;\r\n markerElement.style.display = 'flex';\r\n\r\n if (scale <= smallSizeZoom) {\r\n markerElement.classList.add('small-markers');\r\n } else if (scale <= mediumSizeZoom) {\r\n markerElement.classList.add('medium-markers');\r\n } else {\r\n markerElement.classList.add('big-markers');\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * removeInteractiveSitePlan function removes the container holding a set of interactive markers.\r\n * @param {HTML} container holding the interactive map markers that needs to be removed. \r\n */\r\nexport const removeInteractiveSitePlan = ({container}) => {\r\n container.remove();\r\n}\r\n\r\n/**\r\n * getCommunityInteractiveSitePlanInformation$ will emit a stream of data retrieved from server side\r\n * related to interactive site plan markers to show on top of a community site plan.\r\n * @param {Array} sitePlans array to retrieve their interactive site plan markers from.\r\n * @returns an stream of data containing interactive markers for a set of community site plans.\r\n */\r\nexport const getCommunityInteractiveSitePlanInformation$ = (communityIds) => {\r\n const payload = {\r\n communityIds: [...new Set(communityIds)].join(','),\r\n };\r\n\r\n return getCommunityInteractiveSitePlans$(payload).pipe(\r\n mergeMap((interactiveSitePlans) => of(interactiveSitePlans)),\r\n catchError(() => of([])),\r\n );\r\n};\r\n\r\n/**\r\n * handleInteractiveMapLayersVisibility shows and hides layers of a community interactive map\r\n * based on the current zoom level.\r\n * @param {int} zoomLevel of the current map.\r\n * @param {HTMLElement} sitePlan representation in the map.\r\n */\r\nexport const handleInteractiveMapLayersVisibility = (zoomLevel, sitePlan) => {\r\n const layersToShow = Array.from(zoomLevelLayersLookup.entries())\r\n .filter(([key]) => key <= zoomLevel)\r\n .flatMap(([, layers]) => layers);\r\n\r\n const layersToHide = Array.from(zoomLevelLayersLookup.entries())\r\n .filter(([key]) => key > zoomLevel)\r\n .flatMap(([, layers]) => layers);\r\n\r\n layersToShow.forEach((layer) => {\r\n const path = sitePlan.querySelector(`#${layer.id}`);\r\n path?.removeAttribute('hidden');\r\n path?.removeAttribute('fill');\r\n path?.removeAttribute('stroke');\r\n });\r\n\r\n layersToHide.forEach((layer) => {\r\n const path = sitePlan.querySelector(`#${layer.id}`);\r\n path?.setAttribute('hidden', '');\r\n path?.removeAttribute('fill');\r\n path?.removeAttribute('stroke');\r\n });\r\n};","/**\r\n * This module is the back bone of community interactive site plans in the Search Results Page's map.\r\n * Interactions like showing/hiding markers on top of interactive community site plans are supported here.\r\n */\r\n\r\nimport { store, store$ } from '@redux/store';\r\nimport {\r\n combineLatest,\r\n debounceTime,\r\n distinctUntilChanged,\r\n distinctUntilKeyChanged,\r\n filter,\r\n from,\r\n fromEvent,\r\n map,\r\n merge,\r\n mergeMap,\r\n pairwise,\r\n shareReplay,\r\n skip,\r\n startWith,\r\n switchMap,\r\n tap,\r\n withLatestFrom\r\n} from 'rxjs';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { \r\n createInteractiveSitePlanMarkersOverlay,\r\n setZoomLevel,\r\n removeInteractiveMarkersOverlay,\r\n updateMapCenter,\r\n changeMapCursorPointer,\r\n} from 'libraries/mapLibrary';\r\nimport { \r\n ProductType,\r\n ResultType,\r\n searchParametersActions,\r\n selectAppliedFacets,\r\n selectProductType,\r\n selectResultType,\r\n selectSorting,\r\n SortType,\r\n} from 'features/searchResultsFacets';\r\nimport { selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport {\r\n selectAllPlansAndSpecsIds,\r\n selectSitePlans,\r\n selectFocusedListingAndSitePlans,\r\n selectInteractiveSitePlans,\r\n selectZoomLevel,\r\n selectLotCommunityId,\r\n selectAvailableSpec,\r\n selectedLotSummaryCardStatus,\r\n selectLotId,\r\n selectTrackedInteractiveSitePlans,\r\n selectLotInformation\r\n} from '../redux/selectors';\r\nimport {\r\n addInteractiveSitePlan,\r\n assignLotPathId,\r\n drawInteractiveSitePlan,\r\n getCommunityInteractiveSitePlanInformation$,\r\n handleInteractiveMapLayersVisibility,\r\n removeInteractiveSitePlan\r\n} from '../services/interactiveSitePlan';\r\nimport { interactiveSitePlanSlice, mapStateSlice } from '../redux/slices';\r\nimport { mapContainerClicked$, onZoomChanged$ } from '../redux/observables';\r\nimport { zoomLevelTriggers } from '../constants/sitePlansConstants';\r\nimport LotPolygonType from '../enums/lotPolygonType';\r\nimport { getInteractiveSitePlanLayers } from '../services/sitePlan';\r\nimport LotStatus from '../enums/lotStatus';\r\n\r\nconst actions = {\r\n ...interactiveSitePlanSlice.actions,\r\n ...mapStateSlice.actions,\r\n ...searchParametersActions,\r\n};\r\n\r\n/**\r\n * Basic configuration for a functional experience of Community Interactive Site Plans.\r\n * This contains properties as the zoom triggers for fetching and drawing interactive\r\n * markers to place on top of the site plans.\r\n */\r\nconst configuration = {\r\n previousProductType: null,\r\n previousResultType: null,\r\n markersBuffer: new Set(),\r\n sitePlansBuffer: new Set(),\r\n searchWithinMapCheckbox: document.querySelector('[data-search-within-map-toggle]'),\r\n};\r\n\r\n/**\r\n * getHiddenInteractiveSitePlans: this function filters interactive site plans to include only those that:\r\n * - Have their markers hidden (`!sitePlan.areMarkersShown`).\r\n * - Exist in the list of site plans (`selectSitePlans(state)`).\r\n *\r\n * @param {Object} state - The application state.\r\n * @returns {Array} Filtered interactive site plans.\r\n */\r\nconst getHiddenInteractiveSitePlans = (state) => {\r\n const sitePlans = new Set(selectSitePlans(state).map((sitePlan) => sitePlan.sitePlanId));\r\n\r\n return selectInteractiveSitePlans(state).filter(\r\n (sitePlan) => !sitePlan.areMarkersShown && sitePlans.has(sitePlan.sitePlanId)\r\n );\r\n}\r\n\r\n/**\r\n * addNonInteractiveStateClass: adds the \"non-interactive-state\" to the inactive groups\r\n * when the user exited the interactiveness threshold.\r\n * Important to notice: out of the interactiveness threshold; all the lots look like if they\r\n * were active. When the user enters into the interactiveness threshold: now the inactive lots\r\n * will look disable so the users won't click on them.\r\n */\r\nconst addNonInteractiveStateClass = () => {\r\n const inactiveGroups = document.querySelectorAll(`#lot_polygons #${LotPolygonType.Inactive.toString()}`);\r\n inactiveGroups.forEach((group) => group.classList.add(\"non-interactive-state\"));\r\n};\r\n\r\n/**\r\n * createInteractiveMarkers: will create interactive markers on top of an interactive site plan.\r\n */\r\nconst createInteractiveMarkers = (sitePlan, zoomLevel) => {\r\n const payload = {\r\n markers: sitePlan.markers,\r\n areMarkersShown: zoomLevel >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger,\r\n communityId: sitePlan.communityId,\r\n sitePlanId: sitePlan.sitePlanId,\r\n };\r\n\r\n store.dispatch(actions.setInteractiveSitePlan(payload));\r\n\r\n const markersContainer = document.querySelector(`[data-interactive-markers-container-id=\"${sitePlan.sitePlanId}\"]`);\r\n if (markersContainer) {\r\n return;\r\n }\r\n\r\n const newMarkersContainer = document.createElement('DIV');\r\n newMarkersContainer.dataset.interactiveMarkersContainerId = sitePlan.sitePlanId;\r\n\r\n if (zoomLevel < zoomLevelTriggers.drawInteractiveSitePlanMarkers) {\r\n newMarkersContainer.setAttribute('hidden', '');\r\n }\r\n\r\n const resource = {\r\n communityId: sitePlan.communityId,\r\n sitePlanId: sitePlan.sitePlanId,\r\n onAdd: addInteractiveSitePlan,\r\n onDraw: drawInteractiveSitePlan,\r\n onRemove: removeInteractiveSitePlan,\r\n markers: structuredClone(sitePlan.markers),\r\n container: newMarkersContainer,\r\n };\r\n\r\n createInteractiveSitePlanMarkersOverlay(resource);\r\n};\r\n\r\n/**\r\n * getLotAvailableListings will filter the listings of a given lot based on the current user\r\n * search criteria.\r\n * @param {Array} lotListingIds is an array of the listings represented by the lot.\r\n * @param {Array} listings is an array of the current listings in the store (plan or spec ids).\r\n * @returns an array of the available listing ids in the given lot.\r\n */\r\nconst getLotAvailableListings = (lotListingIds, listings) =>\r\n lotListingIds.filter((listingId) => listings.includes(listingId));\r\n\r\n/**\r\n * handleRemovedInteractiveSitePlans: this function will remove interactive site plans associated\r\n * with removed interactive communities.\r\n * @param {Array} removedInteractiveSitePlans is an array of interactive site plans.\r\n */\r\nconst handleRemovedInteractiveSitePlans = (removedInteractiveSitePlans) => {\r\n const sitePlanIds = new Set([...configuration.markersBuffer, ...configuration.sitePlansBuffer]);\r\n store.dispatch(actions.untrackInteractiveSitePlans());\r\n\r\n sitePlanIds.forEach((id) => {\r\n const sitePlan = removedInteractiveSitePlans.find((plan) => plan.sitePlanId === id);\r\n if (sitePlan) {\r\n configuration.markersBuffer.delete(id);\r\n configuration.sitePlansBuffer.delete(id);\r\n removeInteractiveMarkersOverlay(sitePlan.communityId);\r\n store.dispatch(actions.removeInteractiveSitePlan(id));\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * setInteractiveSitePlanMarkersShownFlag function will change the \"areMarkersShown\" property of\r\n * a given Interactive Site Plan received as argument.\r\n * @param {Object} interactiveSitePlan to change the \"areMarkersShown\" property \r\n * @param {Boolean} areMarkersShown boolean flag to set to the Interactive Site Plan\r\n */\r\nconst setInteractiveSitePlanMarkersShownFlag = (interactiveSitePlan, areMarkersShown) => {\r\n const payload = {\r\n ...interactiveSitePlan,\r\n areMarkersShown,\r\n };\r\n\r\n store.dispatch(actions.setInteractiveSitePlan(payload));\r\n}\r\n \r\n/** disableSearchWithinMap: will disable search within map flags in the store, and will turn off\r\n* the search within map checkbox in the user interface.\r\n*/\r\nconst disableSearchWithinMap = () => {\r\n store.dispatch(actions.disableSearchWithinMap());\r\n configuration.searchWithinMapCheckbox.checked = false;\r\n};\r\n\r\n/**\r\n * dispatchEnterInteractiveSitePlanResults function will dispatch an action to the\r\n * search parameters slice with the payload associated with entering into interactive\r\n * state of ISP.\r\n */\r\nconst dispatchEnterInteractiveSitePlanResults = () => {\r\n disableSearchWithinMap();\r\n\r\n const currentState = store.getState();\r\n const currentProduct = selectProductType(currentState);\r\n\r\n const payload = {};\r\n\r\n if (currentProduct !== ProductType.Homes.toString()) {\r\n configuration.previousProductType = selectProductType(currentState);\r\n configuration.previousResultType = selectResultType(currentState);\r\n \r\n payload.productType = ProductType.Homes.toString();\r\n payload.resultType = ResultType.Homes.toString();\r\n }\r\n\r\n if (Object.keys(payload).length > 0) {\r\n store.dispatch(actions.fetchInteractiveSitePlanResults(payload));\r\n }\r\n}\r\n\r\n/**\r\n * dispatchInteractiveSitePlanSorting: will dispatch the action for sort results based on\r\n * community identifiers.\r\n * @param {int} communityId is a community identifier.\r\n */\r\nconst dispatchInteractiveSitePlanSorting = (communityIds) => {\r\n const currentState = store.getState();\r\n const currentSort = selectSorting(currentState);\r\n const payload = {};\r\n\r\n if (!currentSort?.sortBy || currentSort.sortBy === SortType.CommunityId.toString()) {\r\n payload.sortBy = SortType.CommunityId.toString();\r\n payload.sortOrder = false;\r\n payload.sortFirstBy = communityIds.toString();\r\n }\r\n \r\n if (Object.keys(payload).length > 0) {\r\n store.dispatch(actions.fetchSort(payload));\r\n }\r\n}\r\n\r\n/**\r\n * dispatchExitInteractiveSitePlanResults: will dispatch the action for exiting interactive site\r\n * plans results. This action changes state values like the produc and result type.\r\n */\r\nconst dispatchExitInteractiveSitePlanResults = () => {\r\n const currentState = store.getState();\r\n const currentSort = selectSorting(currentState);\r\n const payload = {};\r\n \r\n if (currentSort?.sortBy === SortType.CommunityId.toString()) {\r\n payload.sorting = {\r\n sortBy: null,\r\n sortOrder: false,\r\n sortFirstBy: null,\r\n };\r\n }\r\n \r\n const productType = selectProductType(currentState);\r\n const resultType = selectResultType(currentState);\r\n const sitePlans = selectSitePlans(currentState)?.filter((sitePlan) => sitePlan.isInteractiveSitePlan);\r\n const isHomeResults = productType === ProductType.Homes.toString();\r\n\r\n payload.productType = (!isHomeResults || (isHomeResults && sitePlans.length === 0))\r\n ? productType\r\n : configuration.previousProductType || productType;\r\n \r\n payload.resultType = (!isHomeResults || (isHomeResults && sitePlans.length === 0)) \r\n ? resultType\r\n : configuration.previousResultType || resultType;\r\n\r\n store.dispatch(actions.fetchInteractiveSitePlanResults(payload));\r\n if (payload.sorting) {\r\n store.dispatch(actions.fetchSort(payload));\r\n }\r\n\r\n configuration.previousProductType = null;\r\n configuration.previousResultType = null;\r\n}\r\n\r\n/**\r\n * removeNonInteractiveStateClass: removes the \"non-interactive-state\" to the inactive groups\r\n * when the user exits the interactiveness threshold.\r\n * Important to notice: out of the interactiveness threshold; all the lots look like if they\r\n * were active. When the user enters into the interactiveness threshold: now the disable lots\r\n * will look disable so the users won't click on them.\r\n */\r\nconst removeNonInteractiveStateClass = () => {\r\n const inactiveGroups = document.querySelectorAll(`#lot_polygons #${LotPolygonType.Inactive.toString()}`);\r\n inactiveGroups.forEach((group) => group.classList.remove(\"non-interactive-state\"));\r\n\r\n const selectedGroups = document.querySelectorAll(`#lot_polygons #${LotPolygonType.Selected.toString()}`);\r\n selectedGroups.forEach((group) => { group.innerHTML = \"\" });\r\n}\r\n\r\n/**\r\n * handleMarkersVisibility will toggle the Interactive Site Plans markers visibility\r\n */\r\nconst handleMarkersVisibility = ({ interactiveSitePlans, zoomLevel }) => {\r\n const visibilityFlag = zoomLevel >= zoomLevelTriggers.drawInteractiveSitePlanMarkers;\r\n\r\n interactiveSitePlans.forEach((sitePlan) => {\r\n const container = document.querySelector(`[data-interactive-markers-container-id=\"${sitePlan.sitePlanId}\"]`);\r\n container?.toggleAttribute('hidden', !visibilityFlag);\r\n });\r\n }\r\n\r\n/**\r\n * removeInteractiveMarkers: will remove the interactive markers of a given array of community site plans.\r\n * @param {Array} interactiveSitePlans to remove. \r\n */\r\nconst removeInteractiveMarkers = (interactiveSitePlans) => {\r\n interactiveSitePlans.forEach((interactiveSitePlan) => {\r\n setInteractiveSitePlanMarkersShownFlag(interactiveSitePlan, false);\r\n removeInteractiveMarkersOverlay(interactiveSitePlan.communityId);\r\n });\r\n}\r\n\r\n/**\r\n * getInteractiveSitePlans function will return the interactive site plans for a community id.\r\n * @param {int} id is the identifier of the community.\r\n * @param {Array} interactiveSitePlans collection to query\r\n * @returns a set of interactive site plans for a community.\r\n */\r\nconst getInteractiveSitePlans = (id, interactiveSitePlans) =>\r\n interactiveSitePlans?.filter((sitePlan) => sitePlan.communityId === id)\r\n\r\n/**\r\n * updateLotPolygon function updates the look and feel of a list of polygons.\r\n */\r\nconst updateLotPolygon = (sitePlanId, groupName, polygons) => {\r\n const sitePlan = document.querySelector(`[data-polygon-container-id='${sitePlanId}']`);\r\n const group = sitePlan?.querySelector(`g#${groupName}`);\r\n group?.append(...polygons);\r\n}\r\n\r\n/**\r\n * removeHighlightedElements function will remove any polygon in the Hovered group of the shown site plans.\r\n */\r\nconst removeHighlightedElements = () => {\r\n const hoveredGroups = document.querySelectorAll(`#lot_polygons #${LotPolygonType.Hovered.toString()}`);\r\n hoveredGroups.forEach((group) => { group.innerHTML = '' });\r\n}\r\n\r\n/**\r\n * handleCursorPointerOnHoveringLots will adjust the map cursor depending on if there is an\r\n * interested lot from the user.\r\n */\r\nconst handleCursorPointerOnHoveringLots = ({ polygonId, polygonGroupId }) => {\r\n const cursor = polygonId && polygonGroupId === LotPolygonType.Active.toString() ? 'pointer' : 'grab';\r\n changeMapCursorPointer(cursor);\r\n};\r\n\r\n/**\r\n * clearSitePlanGroup removes polygons from a given site plan group.\r\n */\r\nconst clearSitePlanGroup = (sitePlanId, group) => {\r\n const sitePlan = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n const selectedGroup = sitePlan.querySelector(`#lot_polygons #${group}`);\r\n selectedGroup.innerHTML = \"\";\r\n}\r\n\r\n/**\r\n * disableSitePlanInteraction function will update the polygons of the\r\n * community site plans shown on screen. After this update, the polygons\r\n * will no longer be interactive. The user will have to zoom in again\r\n * in order to make them interactive.\r\n */\r\nconst disableSitePlanInteraction = (interactiveSitePlans) => {\r\n removeInteractiveMarkers(interactiveSitePlans);\r\n dispatchExitInteractiveSitePlanResults();\r\n changeMapCursorPointer();\r\n removeHighlightedElements();\r\n store.dispatch(actions.removeLotInformation());\r\n\r\n interactiveSitePlans.forEach((interactiveSitePlan) => {\r\n configuration.markersBuffer.delete(interactiveSitePlan.sitePlanId);\r\n const sitePlanMap = document.querySelector(`[data-polygon-container-id=\"${interactiveSitePlan.sitePlanId}\"]`);\r\n const lotPolygons = interactiveSitePlan.markers.map((marker) =>\r\n sitePlanMap?.querySelector(`#${LotPolygonType.Active.toString()} #${marker.Id}, #${LotPolygonType.Selected.toString()} #${marker.Id}`))\r\n .filter(Boolean);\r\n\r\n if (sitePlanMap) {\r\n const hoverGroup = sitePlanMap.querySelector(`#${LotPolygonType.Hovered.toString()}`);\r\n const selectedGroup = sitePlanMap.querySelector(`#${LotPolygonType.Selected.toString()}`);\r\n const activeGroup = sitePlanMap.querySelector(`#${LotPolygonType.Active.toString()}`);\r\n \r\n hoverGroup.innerHTML = \"\";\r\n selectedGroup.innerHTML = \"\";\r\n activeGroup.innerHTML = \"\";\r\n\r\n updateLotPolygon(interactiveSitePlan.sitePlanId, LotPolygonType.Inactive.toString(), lotPolygons);\r\n }\r\n });\r\n };\r\n\r\n /**\r\n * updateActiveLotPolygonStyle will handle previously active and current active\r\n * lot styles after clicking on a lot area.\r\n * @param {Object} previousActiveLot is the lot transtioning from selected to active.\r\n * @param {Object} currentActiveLot is the lot transitioning from active to selected.\r\n */\r\n const updateActiveLotPolygonStyle = (previousActiveLot, currentActiveLot) => {\r\n if (previousActiveLot.lotMarker?.Id && previousActiveLot?.sitePlanId) {\r\n const previousSitePlan = document.querySelector(`[data-polygon-container-id=\"${previousActiveLot.sitePlanId}\"]`);\r\n const selectedGroup = previousSitePlan?.querySelector(`#${LotPolygonType.Selected.toString()}`);\r\n if (selectedGroup) {\r\n selectedGroup.innerHTML = \"\";\r\n }\r\n }\r\n\r\n if (currentActiveLot.lotMarker?.Id && currentActiveLot?.sitePlanId) {\r\n const currentSitePlan = document.querySelector(`[data-polygon-container-id=\"${currentActiveLot.sitePlanId}\"]`);\r\n const lotPolygon = currentSitePlan?.querySelector(`#${currentActiveLot.lotMarker?.Id}`);\r\n if (lotPolygon) {\r\n updateLotPolygon(\r\n currentActiveLot.sitePlanId,\r\n LotPolygonType.Selected.toString(),\r\n [lotPolygon.cloneNode(true)]);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * getLotById: finds and returns the path node representing a lot by a given identifier.\r\n * @param {string} lotId is the lot identifier.\r\n * @param {int} sitePlanId is the site map identifier.\r\n * @returns a path representing a community lot.\r\n */\r\nconst getLotById = (lotId, sitePlanId) => {\r\n const sitePlanSvg = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n return sitePlanSvg?.querySelector(`g#lot_polygons #${lotId}`);\r\n}\r\n\r\n/**\r\n * isInteractiveSitePlanShown validates that both the marker and site plan buffers contain\r\n * a given site plan id. To have these two buffers containing the given Id means that both\r\n * layers are being shown in the Search Results Map and the user is able to interact with\r\n * them.\r\n * @param {int} sitePlanId is the site plan identifier\r\n * @returns a boolean flag indicating if the interactive site plan is ready to be used.\r\n */\r\nconst isInteractiveSitePlanShown = (sitePlanId) =>\r\n configuration.markersBuffer.has(sitePlanId) &&\r\n configuration.sitePlansBuffer.has(sitePlanId);\r\n\r\n/**\r\n * addPolygonToGroup: will add a lot polygon to a given array if the lot is not already\r\n * in the node where the array of lots its going to be appended to. This is to avoid\r\n * unnecesary DOM operation by appending children to a that already have them.\r\n * @param {HTMLElement} lotPolygon is a path representing a lot.\r\n * @param {String} groupId is a type of LotPolygonType.\r\n * @param {Array} array is the array to push the lot polygon.\r\n */\r\nconst addPolygonToGroup = (lotPolygon, groupId, array) => {\r\n if (!lotPolygon.closest(`g#${groupId}`)) {\r\n array.push(lotPolygon);\r\n }\r\n};\r\n\r\n/**\r\n * areFiltersApplied will return a boolean flag indicating if there are filters applied or not.\r\n * @param {Array} filters is an array of the current applied filters.\r\n * @returns a flag indicating if there are filters applied or not.\r\n */\r\nconst areFiltersApplied = (filters) => {\r\n const excludedFilters = [\"sort\"];\r\n const appliedFilters = filters?.filter((appliedFilter) => !excludedFilters.includes(appliedFilter));\r\n return appliedFilters?.length > 0;\r\n};\r\n\r\n/**\r\n * applyLotClassBasedOnStatus will apply a specific class to the lot based on its status.\r\n * @param {LotStatus} status is the lot status\r\n * @param {HTMLElement} lotPolygon is the node representing a polygon\r\n */\r\nconst applyLotClassBasedOnStatus = (status, lotPolygon) => {\r\n if (status === LotStatus.Sold.toString()) {\r\n lotPolygon.classList.add('sold');\r\n }\r\n\r\n if (status === LotStatus.Unreleased.toString()) {\r\n lotPolygon.classList.add('unreleased');\r\n } \r\n}\r\n\r\n/**\r\n * updateLotVisibility is in charge of showing or hidding lot visuals like the lot marker or the lot polygon.\r\n * @param {Array} listings is an array of either plan Ids or spec Ids, depending of the calling control. \r\n * @param {Function} getMarkers is a function that will filter the Interactive Site Plan markers to retrieve either\r\n * plan or specs. Which one to choose depends on the calling control of updateLotVisibility function.\r\n * @param {Function} getAvailability is a function that will filter lot listings depending on their availability\r\n * in terms of the current user search criteria.\r\n */\r\nconst updateLotVisibility = ({ listings, getMarkers, getAvailability }) => {\r\n const currentState = store.getState();\r\n const zoomLevel = selectZoomLevel(currentState);\r\n const productType = selectProductType(currentState);\r\n\r\n if (productType !== ProductType.Homes.toString() || \r\n zoomLevel < zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger) {\r\n return;\r\n }\r\n\r\n const selectedLotId = selectLotId(currentState);\r\n const activeFilters = selectAppliedFacets(currentState);\r\n const areFiltersActive = areFiltersApplied(activeFilters);\r\n\r\n const interactiveSitePlans =\r\n selectInteractiveSitePlans(currentState)\r\n .filter((sitePlan) => isInteractiveSitePlanShown(sitePlan.sitePlanId));\r\n\r\n interactiveSitePlans.forEach((interactiveSitePlan) => {\r\n const filteredMarkers = interactiveSitePlan.markers?.filter(getMarkers);\r\n const activeLots = [];\r\n const inactiveLots = [];\r\n\r\n filteredMarkers?.forEach((marker) => {\r\n const lotPolygon = getLotById(marker.Id, interactiveSitePlan.sitePlanId);\r\n if (!lotPolygon) {\r\n return;\r\n }\r\n\r\n applyLotClassBasedOnStatus(marker.Status, lotPolygon); \r\n const lotIsVisible =\r\n (marker.Status === LotStatus.Sold.toString() && !areFiltersActive) ||\r\n (marker.Status !== LotStatus.Sold.toString() && getAvailability(marker, listings).length > 0);\r\n\r\n const lotMarker = document.querySelector(`[data-interactive-marker-id=\"${marker.Id}\"]`);\r\n lotMarker?.toggleAttribute('hidden', !lotIsVisible); \r\n\r\n const isLotSelected = selectedLotId === marker.Id;\r\n\r\n if (!lotIsVisible) {\r\n addPolygonToGroup(lotPolygon, LotPolygonType.Inactive.toString(), inactiveLots);\r\n if (isLotSelected) {\r\n store.dispatch(actions.removeLotInformation());\r\n }\r\n } else if (!isLotSelected) {\r\n addPolygonToGroup(lotPolygon, LotPolygonType.Active.toString(), activeLots);\r\n }\r\n });\r\n\r\n updateLotPolygon(interactiveSitePlan.sitePlanId, LotPolygonType.Active.toString(), activeLots);\r\n updateLotPolygon(interactiveSitePlan.sitePlanId, LotPolygonType.Inactive.toString(), inactiveLots);\r\n });\r\n};\r\n\r\n/**\r\n * updatePlansVisibility: This function calls the generic updateLotVisibility with plan-specific\r\n * filter and availability logic.\r\n * @param {Array} plans array of the current plans shown in the Search Results Page.\r\n */\r\nconst updatePlansVisibility = ({ plans }) => {\r\n updateLotVisibility({\r\n listings: plans,\r\n getMarkers: (marker) => marker.HousingUnitId === null,\r\n getAvailability: (marker, currentPlans) => getLotAvailableListings(marker.HousePlanIds, currentPlans),\r\n });\r\n};\r\n\r\n/**\r\n * updateSpecsVisibility: This function calls the generic updateLotVisibility with spec-specific\r\n * filter and availability logic.\r\n * @param {Array} specs array of the current specs shown in the Search Results Page.\r\n */\r\nconst updateSpecsVisibility = ({ specs }) => {\r\n updateLotVisibility({\r\n listings: specs,\r\n getMarkers: (marker) => marker.HousingUnitId,\r\n getAvailability: (marker, currentSpecs) => getLotAvailableListings([marker.HousingUnitId], currentSpecs),\r\n });\r\n};\r\n\r\n/**\r\n * dispatchEnterInteractiveSitePlanResults: will dispatch the action for entering interactive site\r\n * plans results. This action changes state values like produc and result type.\r\n */\r\nconst enableSitePlanInteraction = () => {\r\n const currentState = store.getState();\r\n const zoomLevel = selectZoomLevel(currentState);\r\n if (zoomLevel < zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger) {\r\n return;\r\n }\r\n\r\n dispatchEnterInteractiveSitePlanResults();\r\n\r\n const communityIdsForSorting = [];\r\n const interactiveSitePlans = selectInteractiveSitePlans(currentState);\r\n\r\n interactiveSitePlans\r\n .filter((sitePlan) => !sitePlan.areMarkersShown)\r\n .forEach((interactiveSitePlan) => {\r\n createInteractiveMarkers(interactiveSitePlan, zoomLevel);\r\n communityIdsForSorting.push(interactiveSitePlan.communityId);\r\n });\r\n\r\n if (communityIdsForSorting.length > 0) {\r\n dispatchInteractiveSitePlanSorting(communityIdsForSorting);\r\n }\r\n\r\n const currentListingIds = selectAllPlansAndSpecsIds(currentState);\r\n updatePlansVisibility(currentListingIds);\r\n updateSpecsVisibility(currentListingIds);\r\n\r\n removeNonInteractiveStateClass();\r\n}\r\n\r\n/**\r\n * trackLoadedSitePlans: will dispatch the updateInteractiveSitePlanLoadingStatus reducer.\r\n * @param {Array} sitePlans is an array of the site plans to update.\r\n * @param {LoadingStatus} loadingStatus to set in the site plan.\r\n */\r\nconst trackLoadedSitePlans = (communityIds, loadingStatus) => {\r\n if (communityIds.length > 0) {\r\n communityIds.forEach((communityId) => {\r\n const payload = {\r\n communityId,\r\n loadingStatus,\r\n };\r\n \r\n store.dispatch(actions.trackLoadedSitePlans(payload));\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * highlightLotArea: this function will highlight a given set of lots in a community site plan.\r\n * @param {int} id of the hovered card. It could be a plan or a spec id.\r\n * @param {Array} interactiveSitePlans array of Interactive Site Plans\r\n */\r\nconst highlightLotArea = ({ id, interactiveSitePlans }) => { \r\n if (!id || interactiveSitePlans.length === 0) {\r\n return;\r\n }\r\n\r\n const activeLotId = selectLotId(store.getState());\r\n interactiveSitePlans.forEach((sitePlan) => {\r\n const sitePlanMap = document.querySelector(`[data-polygon-container-id=\"${sitePlan.sitePlanId}\"]`);\r\n const polygonLots = sitePlan.markers\r\n .filter((marker) =>\r\n marker.Status !== LotStatus.Sold.toString() &&\r\n marker.Id !== activeLotId &&\r\n (marker.HousePlanIds.some((planId) => planId === id) ||\r\n (marker.HousingUnitId === id && marker.HousingUnitId)))\r\n .map((marker) => sitePlanMap?.querySelector(`#${marker.Id}`)?.cloneNode(true));\r\n\r\n updateLotPolygon(sitePlan.sitePlanId, LotPolygonType.Hovered.toString(), polygonLots);\r\n });\r\n}\r\n\r\n/**\r\n * handleInteractiveMarkerClick: this function handles the behavior of clicking on a interactive\r\n * marker rendered on top of a Interactive Site Plan.\r\n */\r\nconst handleInteractiveMarkerClick = ({ lotMarker, communityId, sitePlanId }) => {\r\n const state = store.getState();\r\n const currentPlans = selectAllPlansAndSpecsIds(state).plans;\r\n\r\n const availableSpec = lotMarker.HousingUnitId;\r\n const availablePlans = getLotAvailableListings(lotMarker.HousePlanIds, currentPlans);\r\n const currentLotCommunityId = selectLotCommunityId(state);\r\n const currentLotSpecId = selectAvailableSpec(state);\r\n const currentLotCardStatus = selectedLotSummaryCardStatus(state);\r\n\r\n const payload = {\r\n availablePlans,\r\n availableSpec,\r\n lotNumber: lotMarker.Label,\r\n lotId: lotMarker.Id,\r\n communityId,\r\n interactiveSitePlanCardStatus: currentLotCardStatus,\r\n lotStatus: lotMarker.Status,\r\n sitePlanId,\r\n };\r\n\r\n const isNewCommunityOrSpec =\r\n currentLotCommunityId !== communityId ||\r\n currentLotSpecId !== availableSpec;\r\n \r\n if (isNewCommunityOrSpec) {\r\n payload.interactiveSitePlanCardStatus = LoadingStatus.Loading.toString();\r\n }\r\n \r\n store.dispatch(actions.setLotInformation(payload));\r\n}\r\n\r\n/**\r\n * handleLayersVisibilityBasedOnZoomLevel: Adjusts the visibility of map layers on community interactive\r\n * site plans based on the zoom level.\r\n * Implements the \"progressive disclosure\" approach to dynamically enrich or simplify map details\r\n * as users zoom in or out.\r\n *\r\n * @param {number} zoomLevel - The current zoom level of the map.\r\n */\r\nconst handleLayersVisibilityBasedOnZoomLevel = async ({ zoomLevel }) => {\r\n const sitePlansNodes = document.querySelectorAll('[data-is-interactive-community=\"true\"] [data-community-map-id]');\r\n const currentState = store.getState();\r\n const sitePlans = selectSitePlans(currentState);\r\n\r\n sitePlansNodes.forEach(async (sitePlanNode) => {\r\n const sitePlan = sitePlans.find((element) => element.sitePlanId === +sitePlanNode.dataset.sitePlanId);\r\n if (sitePlan) {\r\n await getInteractiveSitePlanLayers(zoomLevel, sitePlan.sitePlanLayers, sitePlanNode, sitePlan.communityId);\r\n handleInteractiveMapLayersVisibility(zoomLevel, sitePlanNode);\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * goToInteractiveSitePlan: will place the map in the area where the community site plan\r\n * in interactive state will be shown.\r\n */\r\nconst goToInteractiveSitePlan = ({ latitude, longitude, shouldSwitchToHomeResults }) => {\r\n if (shouldSwitchToHomeResults) {\r\n dispatchEnterInteractiveSitePlanResults();\r\n }\r\n\r\n updateMapCenter({ latitude, longitude });\r\n setZoomLevel(zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger);\r\n}\r\n\r\n/**\r\n * activateInteractiveStateFromLotClicked will check if the current product type is homes,\r\n * if it is not homes, then this function will call the enableSitePlanInteraction in order\r\n * to switch to home results. This functionality is likely to happen when you were seeing an\r\n * ISP and then you switched to community results. Since you are still within the threshold\r\n * for engaging with ISPs, if you click on the actual ISP it will show again the lot polygons\r\n * and enable interaction.\r\n */\r\nconst activateInteractiveStateFromLotClicked = () => {\r\n if (selectProductType(store.getState()) !== ProductType.Homes.toString()) {\r\n enableSitePlanInteraction();\r\n }\r\n}\r\n\r\n/**\r\n * handleInteractiveSitePlanFetchResults will receive the fetch request for site plans\r\n * and dispatch them to the store so they can be use by the interested subscribers.\r\n * @param {Array} interactiveSitePlans of retrieved Interactive Site Plans.\r\n */\r\nconst handleInteractiveSitePlanFetchResults = (interactiveSitePlans) => {\r\n interactiveSitePlans\r\n .filter((sitePlan) => sitePlan.SitePlanLots.length > 0)\r\n .forEach((collection) => {\r\n trackLoadedSitePlans([collection.CommunityId], LoadingStatus.Succeeded.toString());\r\n\r\n const payload = {\r\n markers: collection.SitePlanLots,\r\n areMarkersShown: false,\r\n communityId: collection.CommunityId,\r\n sitePlanId: collection.SitePlanId,\r\n };\r\n \r\n store.dispatch(actions.setInteractiveSitePlan(payload));\r\n });\r\n}\r\n\r\n/**\r\n * onProductTypeChanged$ will emit any change on the current product type.\r\n */\r\nconst onProductTypeChanged$ = store$.pipe(\r\n map(selectProductType),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * onProductTypeDistinctThanHomes$ will emit a value every time the product type changes while a site plan is shown\r\n * in interactive state. The change we target in this observable is any product type distinct than \"Homes\"\r\n */\r\nconst onProductTypeDistinctThanHomes$ = onProductTypeChanged$.pipe(\r\n filter((productType) => productType !== ProductType.Homes.toString()),\r\n withLatestFrom(onZoomChanged$),\r\n filter(([, zoomLevel]) => zoomLevel >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger));\r\n\r\n/**\r\n * onProductTypeHomes$ will emit a value every time the product type changes while a site plan is shown\r\n * in interactive state. The change we target in this observable is product type to be \"Homes\"\r\n */\r\nconst onProductTypeHomes$ = onProductTypeChanged$.pipe(\r\n filter((productType) => productType === ProductType.Homes.toString()),\r\n withLatestFrom(onZoomChanged$),\r\n filter(([, zoomLevel]) => zoomLevel >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger));\r\n\r\n/**\r\n * onSitePlansChanged$ will stream any change within the site plans from the store.\r\n */\r\nconst onSitePlansChanged$ = store$.pipe(\r\n map(selectSitePlans),\r\n distinctUntilChanged(),\r\n filter(Boolean));\r\n\r\n/**\r\n * onNewCommunitiesWithInteractiveSitePlan$ will emit a value every time a new site plan\r\n * with interactive site plan is added in the store.\r\n */\r\nconst onNewCommunitiesWithInteractiveSitePlan$ = onSitePlansChanged$.pipe(\r\n map((sitePlans) => sitePlans.filter((sitePlan) => sitePlan.isInteractiveSitePlan)),\r\n shareReplay(1));\r\n\r\n/**\r\n * onNewInteractiveSitePlans$ will emit values every time an interactive site plan is added or removed.\r\n */\r\nconst onNewInteractiveSitePlans$ = store$.pipe(\r\n map(selectInteractiveSitePlans),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * \r\n */\r\nconst onTrackedInteractiveSitePlansChanged$ = store$.pipe(\r\n map(selectTrackedInteractiveSitePlans),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * onInteractiveSitePlanRemoved$ will stream every time a interactive site plan was removed from the store.\r\n */\r\nconst onInteractiveSitePlanRemoved$ = onSitePlansChanged$.pipe(\r\n pairwise(),\r\n map(([previous, current]) => {\r\n const previousInteractive = previous.filter(sitePlan => sitePlan.isInteractiveSitePlan);\r\n const currentInteractive =\r\n new Set(current.filter(sitePlan => sitePlan.isInteractiveSitePlan).map(sitePlan => sitePlan.sitePlanId));\r\n\r\n const removed = previousInteractive.filter(sitePlan => !currentInteractive.has(sitePlan.sitePlanId));\r\n return removed;\r\n }),\r\n filter(removed => removed.length > 0)\r\n);\r\n\r\n/**\r\n * onDistinctHomesMarkers$ emits the current plan and specs from the store.\r\n */\r\nconst onDistinctHomesMarkers$ = store$.pipe(\r\n filter((state) => selectResultType(state) === ResultType.Homes.toString()),\r\n map(selectAllPlansAndSpecsIds),\r\n distinctUntilChanged(),\r\n filter(({ plans }) => plans),\r\n filter(({ specs }) => specs),\r\n shareReplay(1));\r\n\r\n/**\r\n * onFetchInteractiveSitePlans$ will emit a value every time interactive\r\n * markers should be fetched from the server in order to be drawn on top of a map.\r\n */\r\nconst onFetchInteractiveSitePlans$ = combineLatest([\r\n onNewCommunitiesWithInteractiveSitePlan$,\r\n onZoomChanged$]).pipe(\r\n filter(([, zoomLevel]) => zoomLevel >= zoomLevelTriggers.zoomLevelDrawSitePlansTrigger),\r\n filter(([sitePlans]) => sitePlans.length > 0),\r\n withLatestFrom(onTrackedInteractiveSitePlansChanged$),\r\n map(([[sitePlans], trackedSitePlans]) =>\r\n sitePlans.filter((sitePlan) => \r\n !trackedSitePlans.some((trackedPlan) =>\r\n trackedPlan.communityId === sitePlan.communityId &&\r\n (trackedPlan.loadingStatus === LoadingStatus.Succeeded.toString() ||\r\n trackedPlan.loadingStatus === LoadingStatus.Loading.toString())\r\n )\r\n ).map((sitePlan) => sitePlan.communityId)),\r\n filter((communityIds) => communityIds.length > 0),\r\n tap((communityIds) => trackLoadedSitePlans(communityIds, LoadingStatus.Loading.toString())),\r\n mergeMap((communityIds) => getCommunityInteractiveSitePlanInformation$(communityIds)));\r\n\r\n/**\r\n * onRemoveInteractiveMarkers$ emits a stream of site plans whose interactive markers \r\n * should be removed when the user zooms out past a threshold where these markers are no longer needed. \r\n * This ensures that markers are hidden when the zoom level falls below the required threshold.\r\n */\r\nconst onRemoveInteractiveMarkers$ = onZoomChanged$.pipe(\r\n pairwise(),\r\n filter(([previousZoom, currentZoom]) => \r\n previousZoom === zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger &&\r\n currentZoom < zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger\r\n ),\r\n withLatestFrom(onProductTypeChanged$),\r\n filter(([, productType]) => productType === ProductType.Homes.toString()));\r\n \r\n/**\r\n * onLotClicked$ emits a value when the area of an active lot is clicked.\r\n */\r\nconst onLotClicked$ = fromEvent(document.body, 'lotClicked').pipe(\r\n withLatestFrom(onNewInteractiveSitePlans$, onProductTypeChanged$),\r\n tap(activateInteractiveStateFromLotClicked),\r\n map(([{ detail }, allSitePlans, productType]) => {\r\n const activeLotId = detail.lotPath?.id;\r\n const interactiveSitePlans = getInteractiveSitePlans(Number(detail.communityId), allSitePlans);\r\n const sitePlan = interactiveSitePlans.find((plan) => \r\n plan.markers.some((marker) => marker.Id === activeLotId)\r\n );\r\n const lotMarker = sitePlan?.markers.find((marker) => marker.Id === activeLotId);\r\n\r\n return {\r\n communityId: detail.communityId,\r\n lotMarker,\r\n sitePlanId: sitePlan?.sitePlanId,\r\n productType,\r\n };\r\n }),\r\n filter(({ lotMarker }) => Boolean(document.querySelector(`g#active #${lotMarker?.Id}`))),\r\n startWith({ communityId: null, lotMarker: null, sitePlanId: null, productType: null }),\r\n pairwise(),\r\n filter(([, currentState]) => currentState.productType === ProductType.Homes.toString()),\r\n tap(([previousState, currentState]) => updateActiveLotPolygonStyle(previousState, currentState)),\r\n map(([, currentState]) => currentState));\r\n \r\n/**\r\n * interactiveMarkersReady$ will emit a value everytime a distinct\r\n * set of interactive markers is created.\r\n */\r\nconst interactiveMarkersReady$ = fromEvent(document.body, 'interactiveMarkersReady').pipe(\r\n map((event) => event.detail),\r\n filter(({ sitePlanId }) => !configuration.markersBuffer.has(sitePlanId)),\r\n mergeMap(({ sitePlanId }) => {\r\n configuration.markersBuffer.add(sitePlanId);\r\n return from(configuration.sitePlansBuffer).pipe(\r\n filter((id) => id === sitePlanId),\r\n map(() => sitePlanId)\r\n );\r\n }));\r\n\r\n/**\r\n * sitePlanDrawComplete$ will emit a value everytime a distinct\r\n * site plan is drawn on top of the Search Results Map.\r\n */\r\nconst sitePlanDrawComplete$ = fromEvent(document.body, 'communityMapDrawComplete').pipe(\r\n map((event) => event.detail),\r\n filter(({ sitePlanId }) => !configuration.sitePlansBuffer.has(sitePlanId)),\r\n mergeMap(({ sitePlanId }) => {\r\n configuration.sitePlansBuffer.add(sitePlanId);\r\n return from(configuration.markersBuffer).pipe(\r\n filter((id) => id === sitePlanId),\r\n map(() => sitePlanId)\r\n );\r\n }));\r\n\r\n/**\r\n * onMarkersAndInteractiveMapReady$ will emit a value everytime the combination of\r\n * interactive markers ready and site plan drawn events are emitted.\r\n */\r\nconst onMarkersAndInteractiveMapReady$ = merge(sitePlanDrawComplete$, interactiveMarkersReady$).pipe(\r\n tap(assignLotPathId),\r\n withLatestFrom(onDistinctHomesMarkers$, onProductTypeChanged$),\r\n filter(([, , productType]) => productType === ProductType.Homes.toString()),\r\n map(([, { plans, specs }]) => ({\r\n plans,\r\n specs,\r\n })),\r\n shareReplay(1));\r\n\r\n/**\r\n * onHoveredCardChanged$ will stream a value every time a card enters or stops being hovered.\r\n */\r\nconst onHoveredCardChanged$ = store$.pipe(\r\n filter((state) => selectZoomLevel(state) >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n filter((state) => selectProductType(state) === ProductType.Homes.toString()),\r\n map(selectFocusedListingAndSitePlans),\r\n distinctUntilChanged(),\r\n withLatestFrom(onNewInteractiveSitePlans$, onZoomChanged$),\r\n filter(([,, zoomLevel]) => zoomLevel >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n tap(removeHighlightedElements),\r\n map(([{ focusedListing }, allSitePlans]) => ({\r\n id: Number(focusedListing?.id),\r\n interactiveSitePlans: getInteractiveSitePlans(Number(focusedListing?.communityId), allSitePlans),\r\n communityId: Number(focusedListing?.communityId),\r\n })));\r\n\r\n/**\r\n * onHoveredLot$ will stream values every time the user is hovering on a lot polygon.\r\n */\r\nconst onHoveredLot$ = fromEvent(document.body, 'hoveredLot').pipe(\r\n map(({ detail }) => ({\r\n sitePlanId: detail.sitePlanId,\r\n groupName: LotPolygonType.Hovered.toString(),\r\n polygons: [detail.interestedLotPath?.cloneNode(true)],\r\n polygonId: detail.polygonId,\r\n polygonGroupId: detail.interestedLotPath?.closest('g')?.id,\r\n })),\r\n distinctUntilKeyChanged('polygonId'),\r\n tap(removeHighlightedElements),\r\n tap(handleCursorPointerOnHoveringLots),\r\n filter(({ polygonGroupId }) => polygonGroupId === LotPolygonType.Active.toString()),\r\n filter(({ polygonId }) => polygonId),\r\n withLatestFrom(store$),\r\n filter(([, state]) => selectZoomLevel(state) >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n filter(([, state]) => selectProductType(state) === ProductType.Homes.toString()),\r\n filter(([, state]) => selectLayoutBreakpoint(state).text === LayoutBreakpoint.Big.text),\r\n map(([hoverInformation]) => hoverInformation));\r\n\r\n/**\r\n * onInteractiveSitePlansRemoved$ will emit a value every time a community\r\n * interactive site plans that was in interactive state gets removed from the store.\r\n */\r\nconst onInteractiveSitePlansRemoved$ = onNewCommunitiesWithInteractiveSitePlan$.pipe(\r\n filter((sitePlans) => sitePlans.length === 0));\r\n\r\n/**\r\n * onShowHiddenInteractiveMarkers$ will emit a value every time there are\r\n * Interactive Site Plans with markers not shown while in Homes product type.\r\n */\r\nconst onShowHiddenInteractiveMarkers$ = store$.pipe(\r\n filter((state) => selectZoomLevel(state) >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n filter((state) => selectProductType(state) === ProductType.Homes.toString()),\r\n map(getHiddenInteractiveSitePlans),\r\n distinctUntilChanged((previous, current) => \r\n previous.length === current.length && \r\n previous.every((prevItem, index) => prevItem.sitePlanId === current[index].sitePlanId)\r\n ),\r\n filter((interactiveSitePlans) => interactiveSitePlans.length > 0)\r\n);\r\n\r\n/**\r\n * onExitInteractiveState$ is an observable that will emit a value anytime one\r\n * of its inner observables emit a value too. Once a value is emited, it\r\n * means the interactiveness of the site plan should end.\r\n */\r\nconst onExitInteractiveState$ = merge(\r\n onRemoveInteractiveMarkers$,\r\n onInteractiveSitePlansRemoved$,\r\n onProductTypeDistinctThanHomes$,\r\n).pipe(\r\n withLatestFrom(store$),\r\n map(([, state]) => selectInteractiveSitePlans(state)),\r\n filter((sitePlans) => sitePlans.length > 0),\r\n tap(addNonInteractiveStateClass),\r\n debounceTime(100));\r\n\r\n/** \r\n * onInteractiveCommunitiesZoomChanged$ observable will emit values whenever\r\n * map zoom level changed and there are rendered community interactive markers on it.\r\n */\r\nconst onInteractiveCommunitiesZoomChanged$ = onZoomChanged$.pipe(\r\n withLatestFrom(onNewCommunitiesWithInteractiveSitePlan$),\r\n map(([zoomLevel, sitePlans]) => ({\r\n zoomLevel,\r\n sitePlans,\r\n })));\r\n\r\n/**\r\n * onNewInteractiveSitePlanIds$ observable will emit values whenever the site plan ids change\r\n */\r\nconst onNewInteractiveSitePlanIds$ = onNewCommunitiesWithInteractiveSitePlan$.pipe( \r\n map((interactiveSitePlans) => interactiveSitePlans.map(sitePlan => sitePlan.communityId)), \r\n distinctUntilChanged((previous, current) => { \r\n if (previous.length !== current.length) {\r\n return false;\r\n } \r\n \r\n return previous.every((id, index) => id === current[index]); \r\n }));\r\n\r\n/**\r\n * onZoomEnteringInteractiveState$ observable will emit values whenever the map zoom level\r\n * changed and that zoom level matches the interactive state zoom level threshold.\r\n */\r\nconst onZoomEnteringInteractiveState$ = combineLatest([\r\n onZoomChanged$, \r\n onNewInteractiveSitePlanIds$\r\n]).pipe(\r\n distinctUntilChanged(([prevZoom, prevIds], [currZoom, currIds]) => {\r\n const isZoomUnchanged =\r\n currZoom >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger &&\r\n prevZoom >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger;\r\n const areIdsSame = prevIds.length === currIds.length && prevIds.every((id, index) => id === currIds[index]);\r\n\r\n return isZoomUnchanged && areIdsSame;\r\n }),\r\n pairwise(),\r\n filter(([[prevZoom], [currZoom]]) => currZoom > prevZoom),\r\n filter(([, [zoomLevel]]) => zoomLevel >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n map(([, [, interactiveSitePlans]]) => interactiveSitePlans),\r\n filter((interactiveSitePlans) => interactiveSitePlans.length > 0));\r\n\r\n/**\r\n * onGoToSitePlanButtonCliked$ will emit a value whenever the\r\n * \"Interactive Map\" button in a marker tooltip is clicked.\r\n */\r\nconst onGoToSitePlanButtonCliked$ = mapContainerClicked$.pipe(\r\n map(({ target }) =>\r\n target?.hasAttribute(\"data-interactive-plan-button\")\r\n ? target\r\n : target?.closest('[data-tooltip-container]')?.querySelector('[data-interactive-plan-button]')\r\n ),\r\n filter(Boolean),\r\n withLatestFrom(onProductTypeChanged$),\r\n map(([goToSitePlanButton, productType]) => ({\r\n latitude: +goToSitePlanButton.dataset.latitude,\r\n longitude: +goToSitePlanButton.dataset.longitude,\r\n communityId: +goToSitePlanButton.dataset.communityId,\r\n shouldSwitchToHomeResults: productType !== ProductType.Homes.toString(),\r\n })),\r\n);\r\n\r\n/**\r\n * fetchInteractiveSitePlanFromTooltipClick$ will fetch the Interactive Site Plan associated\r\n * with the tooltip that received the click.\r\n */\r\nconst fetchInteractiveSitePlanFromTooltipClick$ = onGoToSitePlanButtonCliked$.pipe(\r\n withLatestFrom(onTrackedInteractiveSitePlansChanged$),\r\n filter(([{ communityId }, trackedSitePlans]) =>\r\n !trackedSitePlans.some((trackedPlan) =>\r\n trackedPlan.communityId === communityId &&\r\n (trackedPlan.loadingStatus === LoadingStatus.Succeeded.toString() ||\r\n trackedPlan.loadingStatus === LoadingStatus.Loading.toString())\r\n )\r\n ),\r\n map(([{ communityId }]) => communityId),\r\n tap((communityId) => trackLoadedSitePlans([communityId], LoadingStatus.Loading.toString())),\r\n switchMap((communityId) => getCommunityInteractiveSitePlanInformation$([communityId])));\r\n\r\n/**\r\n * onLotInformationChanged$ will stream a value every time changes happen in the lot\r\n * information from the store.\r\n */\r\nconst onLotInformationChanged$ = store$.pipe(\r\n map(selectLotInformation),\r\n distinctUntilChanged(),\r\n skip(1));\r\n\r\n/**\r\n * onLotInformationRemoved$ will stream a value every time lot information is removed from store.\r\n */\r\nconst onLotInformationRemoved$ = onLotInformationChanged$.pipe(\r\n pairwise(),\r\n filter(([previousLot]) => !!previousLot.lotId),\r\n filter(([, currentLot]) => !currentLot.lotId),\r\n map(([previousLot]) => ({\r\n sitePlanId: previousLot.sitePlanId,\r\n polygonId: previousLot.lotId,\r\n })));\r\n\r\n/**\r\n * onEnterInteractiveState$ observable will stream values everytime the map should enter\r\n * interactive state for any of its Interactive Site Plans\r\n */\r\nconst onEnterInteractiveState$ = merge(\r\n onShowHiddenInteractiveMarkers$,\r\n onZoomEnteringInteractiveState$,\r\n onProductTypeHomes$,\r\n onMarkersAndInteractiveMapReady$).pipe(\r\n debounceTime(100)\r\n );\r\n\r\n/**\r\n * handleInteractiveMarkersOnZoomChange$ will stream a value every time a zoom level changes.\r\n * The intention behind this is to show or hide the Interactive Site Plan markers.\r\n */\r\nconst handleInteractiveMarkersOnZoomChange$ = onZoomChanged$.pipe(\r\n withLatestFrom(store$),\r\n map(([zoomLevel, state]) => ({\r\n interactiveSitePlans: selectInteractiveSitePlans(state),\r\n zoomLevel\r\n })),\r\n filter(({ interactiveSitePlans }) => interactiveSitePlans.length > 0));\r\n\r\nconst onWheelScrollOverTooltip$ = fromEvent(document, 'wheel', { passive: false }).pipe(\r\n filter((event) => event.target.closest('[data-tooltip-container]')),\r\n tap((event) => event.preventDefault()));\r\n\r\nonDistinctHomesMarkers$.subscribe(updatePlansVisibility);\r\nonDistinctHomesMarkers$.subscribe(updateSpecsVisibility);\r\nonLotClicked$.subscribe(handleInteractiveMarkerClick);\r\nonHoveredCardChanged$.subscribe(highlightLotArea);\r\nonInteractiveCommunitiesZoomChanged$.subscribe(handleLayersVisibilityBasedOnZoomLevel);\r\nonGoToSitePlanButtonCliked$.subscribe(goToInteractiveSitePlan);\r\nonInteractiveSitePlanRemoved$.subscribe(handleRemovedInteractiveSitePlans);\r\nonExitInteractiveState$.subscribe(disableSitePlanInteraction);\r\nonEnterInteractiveState$.subscribe(enableSitePlanInteraction);\r\nhandleInteractiveMarkersOnZoomChange$.subscribe(handleMarkersVisibility);\r\nonWheelScrollOverTooltip$.subscribe();\r\nfetchInteractiveSitePlanFromTooltipClick$.subscribe(handleInteractiveSitePlanFetchResults);\r\nonFetchInteractiveSitePlans$.subscribe(handleInteractiveSitePlanFetchResults);\r\nonLotInformationRemoved$.subscribe((lotInformation) =>\r\n clearSitePlanGroup(lotInformation.sitePlanId, LotPolygonType.Selected.toString()));\r\nonHoveredLot$.subscribe((hoveredLotInformation) =>\r\n updateLotPolygon(\r\n hoveredLotInformation.sitePlanId,\r\n hoveredLotInformation.groupName,\r\n hoveredLotInformation.polygons));","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\nimport LotStatus from '../../enums/lotStatus';\r\n\r\n/**\r\n * Represents a Paid Interactive Site Plan Summary Card component.\r\n */\r\nexport default class PaidInteractiveSitePlanCommunityCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard, lotNumber, availableSpecCount, availablePlanCount, lotStatus) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.lotNumber = lotNumber;\r\n this.availablePlanCount = availablePlanCount;\r\n this.availableSpecCount = availableSpecCount;\r\n this.lotStatus = lotStatus;\r\n this.errorImage = getRandomLifestyleImage();\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Sets the label for the PaidSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the title of the summary card.\r\n * @returns {string} The title of the summary card.\r\n */\r\n getTitle() {\r\n return `

Lot ${this.lotNumber}

`;\r\n }\r\n\r\n /**\r\n * Gets the sub title of the summary card.\r\n * @returns {string} The sub title of the summary card.\r\n */\r\n getSubTitle() {\r\n const statusToShow = [LotStatus.Sold, LotStatus.Unreleased];\r\n const status = LotStatus.fromKey(this.lotStatus);\r\n const subTitleElements = [];\r\n\r\n if (statusToShow.includes(status)) {\r\n subTitleElements.push(`

${status.toString()}

`);\r\n }\r\n\r\n if (status === LotStatus.Sold) {\r\n return subTitleElements.join('');\r\n }\r\n\r\n const plansLabel = `${this.availablePlanCount} ${this.availablePlanCount === 1 ? 'Plan' : 'Plans'} Available`;\r\n subTitleElements.push(`

${plansLabel}

`);\r\n\r\n return subTitleElements.join('');\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n \r\n `;\r\n }\r\n}\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\nimport LotStatus from '../../enums/lotStatus';\r\n\r\n/**\r\n * Represents a Paid Interactive Site Plan Summary Card component.\r\n */\r\nexport default class PaidInteractiveSitePlanHousingUnitCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard, lotNumber, availableSpecCount, availablePlanCount, lotStatus) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.lotNumber = lotNumber;\r\n this.availablePlanCount = availablePlanCount;\r\n this.availableSpecCount = availableSpecCount;\r\n this.lotStatus = lotStatus;\r\n this.errorImage = getRandomLifestyleImage();\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Sets the label for the PaidSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the title of the summary card.\r\n * @returns {string} The title of the summary card.\r\n */\r\n getTitle() {\r\n return `

Lot ${this.lotNumber}

`;\r\n }\r\n\r\n /**\r\n * Gets the sub title of the summary card.\r\n * @returns {string} The sub title of the summary card.\r\n */\r\n getSubTitle() {\r\n const statusToShow = [LotStatus.Unreleased];\r\n const status = LotStatus.fromKey(this.lotStatus);\r\n const subTitleElements = [];\r\n\r\n if (statusToShow.includes(status)) {\r\n subTitleElements.push(`

${status.toString()}

`);\r\n }\r\n\r\n const specLable = `${this.availableSpecCount} Spec Available`;\r\n subTitleElements.push(`

${specLable}

`);\r\n\r\n return subTitleElements.join('');\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n \r\n `;\r\n }\r\n}\r\n","import { store$, store } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map, fromEvent, merge, withLatestFrom } from 'rxjs';\r\nimport fastdom from 'fastdom';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { distinctUntilKeyChanged, pairwise } from 'rxjs/operators';\r\nimport { ProductType, selectListingCount, selectProductType } from 'features/searchResultsFacets';\r\nimport { interactiveSitePlanSlice } from '../redux/slices';\r\nimport {\r\n selectedLotSummaryCardStatus,\r\n selectedLotSummaryCard,\r\n selectZoomLevel,\r\n selectLotNumber,\r\n selectAvailableSpec,\r\n selectAvailablePlans,\r\n selectLotInformation,\r\n selectLotCommunityIdAndSitePlans,\r\n selectLotStatus,\r\n} from '../redux/selectors';\r\nimport SummaryCardSkeleton from './skeletons/summaryCardSkeleton';\r\nimport { zoomLevelTriggers } from '../constants/sitePlansConstants';\r\nimport PaidInteractiveSitePlanCommunityCard from './summaryCard/paidInteractiveSitePlanCommunityCard';\r\nimport PaidInteractiveSitePlanHousingUnitCard from './summaryCard/paidInteractiveSitePlanHousingUnitCard';\r\nimport CommunityLabel from './summaryCard/communityLabel';\r\nimport HomeLabel from './summaryCard/homeLabel';\r\nimport MarkerType from '../enums/markerType';\r\nimport LotStatus from '../enums/lotStatus';\r\n\r\nconst interactiveSitePlanActions = interactiveSitePlanSlice.actions;\r\nconst summaryCardContainer = document.querySelector('[data-map-carousel]');\r\nconst closeButton = document.querySelector('[data-summary-card-close]');\r\n\r\n/**\r\n * dispatchClearSummaryCardAction function will dispatch an action for clearing\r\n * the lot summary card store related information.\r\n */\r\nconst dispatchClearSummaryCardAction = () => {\r\n store.dispatch(interactiveSitePlanActions.clearInteractiveSitePlanCard());\r\n store.dispatch(interactiveSitePlanActions.removeLotInformation());\r\n};\r\n\r\n/**\r\n * closeLotSummaryCard is in charge of closing the lot listing summary card.\r\n */\r\nconst closeLotSummaryCard = () => {\r\n const cardsContainer = document.querySelector('[data-summary-card]');\r\n if (cardsContainer) {\r\n fastdom.mutate(() => {\r\n cardsContainer.innerHTML = '';\r\n summaryCardContainer.setAttribute('hidden', '');\r\n summaryCardContainer.classList.remove('nhs-u-width--full', 'nhs-u-pointer-events--none');\r\n cardsContainer.classList.remove('nhs-c-carousel__container--lots', 'nhs-mq-carousel__container--lots-medium');\r\n closeButton.classList.remove('nhs-mq-carousel__close--lot-card-medium', 'nhs-u-pointer-events--all');\r\n });\r\n }\r\n\r\n const event = new CustomEvent('interactiveSitePlanSummaryCardClosed');\r\n store.dispatch(interactiveSitePlanActions.removeLotInformation());\r\n setTimeout(() => {\r\n document.dispatchEvent(event);\r\n }, 0);\r\n};\r\n\r\n/**\r\n * closePreviousSummaryCard will close the visible summary card when the store no longer\r\n * has information to keep it opened.\r\n */\r\nconst closePreviousSummaryCard = ({ previousSummaryCard, currentSummaryCard }) => {\r\n if (!currentSummaryCard && previousSummaryCard) {\r\n setTimeout(() => closeLotSummaryCard(currentSummaryCard), 0);\r\n }\r\n};\r\n\r\n/**\r\n * handleSummaryCardSkeleton: Handles the display of a skeleton card while the actual\r\n * summary card data is being loaded.\r\n */\r\nconst handleSummaryCardSkeleton = () => {\r\n const cardsContainer = document.querySelector('[data-summary-card]');\r\n const skeleton = new SummaryCardSkeleton();\r\n\r\n fastdom.mutate(() => {\r\n summaryCardContainer.removeAttribute('hidden');\r\n summaryCardContainer.classList.add('nhs-u-width--full', 'nhs-u-pointer-events--none');\r\n cardsContainer.classList.add('nhs-c-carousel__container--lots', 'nhs-mq-carousel__container--lots-medium');\r\n closeButton.classList.add('nhs-mq-carousel__close--lot-card-medium', 'nhs-u-pointer-events--all');\r\n\r\n cardsContainer.innerHTML = skeleton.getHtml();\r\n });\r\n};\r\n\r\n/**\r\n * onLotSummaryCardLoading$ emits a value when a summary card is loading. This is useful for showing\r\n * a skeleton while the actual information gets rendered.\r\n */\r\nconst onLotSummaryCardLoading$ = store$.pipe(\r\n map(selectedLotSummaryCardStatus),\r\n distinctUntilChanged(),\r\n filter((status) => status === LoadingStatus.Loading.toString())\r\n);\r\n\r\n/**\r\n * onLotSummaryCardNotSucceeded will handle a summary card that was closed before it had\r\n * a server response (LoadingStatus.Idle) or failed server responses (LoadingStatus.Failed).\r\n * In any of this scenarios, this observable will emit a signal so we can remove the skeleton.\r\n */\r\nconst onLotSummaryCardNotSucceeded$ = store$.pipe(\r\n map(selectedLotSummaryCardStatus),\r\n distinctUntilChanged(),\r\n filter((status) => status === LoadingStatus.Idle.toString() || status === LoadingStatus.Failed.toString())\r\n);\r\n\r\n/**\r\n * renderSummaryCard function will prepare the HTML with the information retrieved from the server.\r\n */\r\nconst renderSummaryCard = (summaryCard) => {\r\n const state = store.getState();\r\n const lotNumber = selectLotNumber(state);\r\n const availableSpecCount = selectAvailableSpec(state) ? 1 : 0;\r\n const availablePlanCount = selectAvailablePlans(state)?.length;\r\n const lotStatus = selectLotStatus(state);\r\n\r\n summaryCardContainer.removeAttribute('hidden');\r\n\r\n const container = document.querySelector('[data-summary-card]');\r\n container.classList.add('nhs-c-carousel__container--lots', 'nhs-mq-carousel__container--lots-medium');\r\n\r\n fastdom.mutate(() => {\r\n container.innerHTML = '';\r\n });\r\n\r\n const card =\r\n availableSpecCount === 1 && lotStatus !== LotStatus.Sold.toString()\r\n ? new PaidInteractiveSitePlanHousingUnitCard(summaryCard)\r\n : new PaidInteractiveSitePlanCommunityCard(summaryCard);\r\n\r\n const label = availableSpecCount === 1 ? new HomeLabel() : new CommunityLabel();\r\n\r\n label.setInformation(summaryCard);\r\n card.setInformation(summaryCard, lotNumber, availableSpecCount, availablePlanCount, lotStatus);\r\n card.setLabel(label);\r\n\r\n const fragment = document.createDocumentFragment();\r\n\r\n const html = card.getHtml();\r\n const range = document.createRange();\r\n const documentFragment = range.createContextualFragment(html);\r\n fragment.appendChild(documentFragment);\r\n\r\n fastdom.mutate(() => {\r\n container.appendChild(fragment);\r\n card.bindEvents();\r\n });\r\n};\r\n\r\ncloseButton?.addEventListener('click', dispatchClearSummaryCardAction);\r\n\r\n/**\r\n * selectedLotSummaryCard$ will emit a value on any changes from the store\r\n * related to the lot listings summary card.\r\n */\r\nconst selectedLotSummaryCard$ = store$.pipe(map(selectedLotSummaryCard), distinctUntilChanged());\r\n\r\n/**\r\n * lotSummaryCardSelected$ will stream a value when there is new informatino\r\n * available in the store to build a lot listings summary card.\r\n */\r\nconst lotSummaryCardSelected$ = store$.pipe(map(selectedLotSummaryCard), distinctUntilChanged(), filter(Boolean));\r\n\r\n/**\r\n * onCloseCard$ will emit a value when the actual summary card needs to be\r\n * removed as there is no information in the store to keep it open.\r\n */\r\nconst onCloseCard$ = selectedLotSummaryCard$.pipe(\r\n pairwise(),\r\n map(([previousSummaryCard, currentSummaryCard]) => ({\r\n previousSummaryCard,\r\n currentSummaryCard,\r\n }))\r\n);\r\n\r\n/**\r\n * hamburgerMenuClicked$ will emit values when hamburger menu is clicked.\r\n */\r\nconst hamburgerMenuClicked$ = fromEvent(document.body, 'hamburgerMenuClicked');\r\n\r\n/**\r\n * advancedFiltersClicked$ will emit values when advanced filters are clicked.\r\n */\r\nconst advancedFiltersClicked$ = fromEvent(document.body, 'advancedFiltersClicked');\r\n\r\n/**\r\n * ListViewToggled$ will emit values when list view toggle button is clicked.\r\n */\r\nconst ListViewToggled$ = fromEvent(document.body, 'listViewToggled');\r\n\r\n/**\r\n * cardCloseClick$ will stream a value when users close the lot summary card.\r\n */\r\nconst cardCloseClick$ = fromEvent(document, 'interactiveSitePlanSummaryCardClosed');\r\n\r\n/**\r\n * onExitInteractiveState$ will stream a value when either the whole community exited locked\r\n * state, or a previous lot in locked state exited that state.\r\n */\r\nconst onExitInteractiveState$ = store$.pipe(\r\n map(selectZoomLevel),\r\n distinctUntilChanged(),\r\n filter((zoomLevel) => zoomLevel < zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger)\r\n);\r\n\r\n/**\r\n * onNoResults$ will emit a value every time there are no listings in the store.\r\n */\r\nconst onNoResults$ = store$.pipe(\r\n map(selectListingCount),\r\n distinctUntilChanged(),\r\n filter((listingCount) => listingCount === 0)\r\n);\r\n\r\n/**\r\n * onRemovedInteractiveSitePlan$ will emit every time an Interactive Site Plan, who had an open\r\n * lot summary card, gets removed from the store.\r\n */\r\nconst onRemovedInteractiveSitePlan$ = store$.pipe(\r\n map(selectLotCommunityIdAndSitePlans),\r\n distinctUntilChanged(),\r\n filter(({ lotCommunityId, sitePlans }) => !sitePlans.some((sitePlan) => sitePlan.communityId === lotCommunityId))\r\n);\r\n\r\n/**\r\n * onProductTypeDistinctThanHomes$ will emit a value every time the product type changes while a site plan is shown\r\n * in interactive state. The change we target in this observable is any product type distinct than \"Homes\"\r\n */\r\nconst onProductTypeDistinctThanHomes$ = store$.pipe(\r\n filter((state) => selectZoomLevel(state) >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger),\r\n map(selectProductType),\r\n distinctUntilChanged(),\r\n filter((productType) => productType !== ProductType.Homes.toString())\r\n);\r\n\r\n/**\r\n * onActiveLotChanged$ will validate if the current lot card comes from the same community as\r\n * the previous lot card so we can update the information on screen instead of doing a\r\n * server roundtrip to retrieve the same data.\r\n */\r\nconst onActiveLotChanged$ = store$.pipe(\r\n map(selectLotInformation),\r\n distinctUntilKeyChanged('lotId'),\r\n pairwise(),\r\n filter(\r\n ([previousCard, currentCard]) =>\r\n previousCard.communityId === currentCard.communityId &&\r\n currentCard.summaryCard?.Type === MarkerType.HousingDevelopment.toString() &&\r\n currentCard.summaryCardStatus === LoadingStatus.Succeeded.toString()\r\n ),\r\n map(([, { summaryCard }]) => summaryCard),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * onCloseSummaryCard$ will stream if any of the reassons to clear the lot listing summary card happens.\r\n */\r\nconst onCloseSummaryCard$ = merge(\r\n cardCloseClick$,\r\n hamburgerMenuClicked$,\r\n advancedFiltersClicked$,\r\n ListViewToggled$,\r\n onExitInteractiveState$,\r\n onNoResults$,\r\n onRemovedInteractiveSitePlan$,\r\n onProductTypeDistinctThanHomes$\r\n).pipe(\r\n withLatestFrom(selectedLotSummaryCard$),\r\n filter(([, summaryCard]) => Boolean(summaryCard))\r\n);\r\n\r\nonCloseSummaryCard$.subscribe(dispatchClearSummaryCardAction);\r\nlotSummaryCardSelected$.subscribe(renderSummaryCard);\r\nonCloseCard$.subscribe(closePreviousSummaryCard);\r\nonLotSummaryCardLoading$.subscribe(handleSummaryCardSkeleton);\r\nonActiveLotChanged$.subscribe(renderSummaryCard);\r\nonLotSummaryCardNotSucceeded$.subscribe(closeLotSummaryCard);\r\n","import { createMapInstance, updateMapCenter, updateMinimumZoomLevel } from 'libraries/mapLibrary';\r\nimport { store, store$ } from '@redux/store';\r\nimport { distinctUntilChanged, filter, first, map, skip } from 'rxjs';\r\nimport { LocationType } from \"features/searchResultsFacets\";\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { \r\n isMapLibraryLoaded,\r\n isSearchWithinMapEnabled,\r\n selectIsSearchWithinMapReady,\r\n selectZoomLevel \r\n} from '../redux/selectors';\r\nimport { locationSearchParameters }\r\n from '../constants/searchParametersConstants';\r\nimport { mapStateSlice } from '../redux/slices';\r\n\r\nconst { actions } = mapStateSlice;\r\n\r\n/* The default settings for the map. */\r\nconst defaultMapSettings = {\r\n clickableIcons: false,\r\n disableDefaultUI: true,\r\n disableDoubleClickZoom: false,\r\n gestureHandling: 'cooperative',\r\n minZoom: 5,\r\n maxZoom: 20,\r\n panControl: false,\r\n scrollwheel: true,\r\n zoomControl: true,\r\n zoomControlStyle: 'SMALL',\r\n};\r\n\r\nconst rectangularAreaMapSettings = {\r\n maxZoom: 9,\r\n};\r\n\r\n/* The default zoom level for the map according to the business requirements. */\r\nconst defaultZoomLevels = {\r\n city: 11,\r\n county: 11,\r\n market: 9,\r\n zip: 12,\r\n syntheticGeo: 9,\r\n rectangularArea: 16,\r\n};\r\n\r\nconst mapContainer = document.querySelector('#nhs_map');\r\n\r\n/**\r\n * When the map bounds change, update the coordinates in the Redux store.\r\n *\r\n * The function is called when the map bounds change. The map bounds are the coordinates of the map's\r\n * viewport. The map bounds are passed into the function as an argument. The function gets the north\r\n * east and south west coordinates of the map bounds. The function then dispatches an action to update\r\n * the coordinates in the Redux store.\r\n *\r\n * @param mapBounds - The bounds of the map.\r\n */\r\nconst getBounds = (mapBounds) => {\r\n const northEast = mapBounds.getNorthEast();\r\n const southWest = mapBounds.getSouthWest();\r\n return {\r\n east: northEast.lng(),\r\n north: northEast.lat(),\r\n south: southWest.lat(),\r\n west: southWest.lng(),\r\n }\r\n};\r\n\r\n/**\r\n * dispatchBounds:\r\n * Updates map bounds with east, north, south, and west coordinates.\r\n * @param {number} east - Eastern boundary coordinate\r\n * @param {number} north - Northern boundary coordinate\r\n * @param {number} south - Southern boundary coordinate\r\n * @param {number} west - Western boundary coordinate\r\n */\r\nconst dispatchBounds = ({east, north, south, west}) => {\r\n store.dispatch(\r\n actions.updateCoordinates({\r\n east,\r\n north,\r\n south,\r\n west,\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * expandBounds:\r\n * When the search within the map is enabled and\r\n * we are in a zoom in greater than 16, a slight expansion in miles \r\n * will be made to prevent the community maps from disappearing \r\n * when we move slightly away from their marker.\r\n *\r\n * @param {Object} bounds - The bounds of the map.\r\n * @param {Int} currentZoom - The current map zoom\r\n */\r\nconst expandBounds = (bounds, currentZoom) => {\r\n const zoomNeighborhood = 16\r\n const zoomBlock = 17;\r\n const zoomBuilding = 18;\r\n const zoomRoom = 19;\r\n const zoomDetail = 20;\r\n const roundedZoom = Math.round(currentZoom);\r\n\r\n const zoomMilesMap = {\r\n [zoomDetail]: 1,\r\n [zoomRoom]: 1,\r\n [zoomBuilding]: 1,\r\n [zoomBlock]: 0.6,\r\n [zoomNeighborhood]: 0.5,\r\n };\r\n\r\n const extraMiles = roundedZoom >= zoomNeighborhood ? zoomMilesMap[roundedZoom] : 0;\r\n\r\n const milesToDegreesLat = 0.0145;\r\n const milesToDegreesLng = 0.0180;\r\n\r\n const newNorthEast = {\r\n lat: bounds.north + (extraMiles * milesToDegreesLat),\r\n lng: bounds.east + (extraMiles * milesToDegreesLng),\r\n };\r\n\r\n const newSouthWest = {\r\n lat: bounds.south - (extraMiles * milesToDegreesLat),\r\n lng: bounds.west - (extraMiles * milesToDegreesLng),\r\n };\r\n \r\n return {\r\n north: newNorthEast.lat,\r\n south: newSouthWest.lat,\r\n west: newSouthWest.lng,\r\n east: newNorthEast.lng,\r\n }\r\n};\r\n\r\n/**\r\n * When the map is loaded, set the z-index of the map container to 999.\r\n */\r\nconst onMapLoaded = ({zoom}) => {\r\n mapContainer.style.zIndex = '999';\r\n store.dispatch(actions.updateMapZoomLevel(zoom))\r\n};\r\n\r\n/**\r\n * Dispatch an action to the store to let it know that the search wihtin map is ready to execute.\r\n */\r\nconst onSearchWithinMapReady = () => {\r\n store.dispatch(actions.onSearchWithinMapReady({}));\r\n};\r\n\r\n/**\r\n * When the map bounds change, get the bounds of the map and store them in the state.\r\n * If the search within map is enabled but the search within map is not ready, then dispatch an action\r\n * to indicate the map coordinates has updated and the search within map is ready to execute.\r\n *\r\n * @param mapBounds - The bounds of the map.\r\n */\r\nconst onCoordinatesChanged = (mapBounds) => {\r\n const state = store.getState();\r\n const isSearchWithinMapEnable = isSearchWithinMapEnabled(state);\r\n const isSearchWithinMapReady = selectIsSearchWithinMapReady(state);\r\n const bounds = getBounds(mapBounds); \r\n const currentZoom = selectZoomLevel(state);\r\n const newBounds = expandBounds(bounds, currentZoom)\r\n\r\n dispatchBounds(newBounds);\r\n\r\n if (isSearchWithinMapEnable && !isSearchWithinMapReady) {\r\n onSearchWithinMapReady();\r\n }\r\n};\r\n\r\n/* An object that contains the functions that will be added as listeners to the map instance */\r\nconst mapEvents = {\r\n coordinatesChanged: onCoordinatesChanged,\r\n mapLoaded: onMapLoaded,\r\n};\r\n\r\n/**\r\n * It creates a map instance.\r\n */\r\nconst createMap = () => createMapInstance(mapContainer, defaultMapSettings, mapEvents);\r\n\r\n/**\r\n * If the locationParameters.LocationType is in the defaultZoomLevels object, then set the\r\n * defaultMapSettings.zoom to the value of the key in the defaultZoomLevels object, otherwise set the\r\n * defaultMapSettings.zoom to 12.\r\n *\r\n * Also assigns the center values for the map using the locationParameters object.\r\n * @param locationParameters - an object with the information of the current location.\r\n */\r\nconst setMapSettings = (locationParameters) => {\r\n const zoomLevel = defaultZoomLevels[locationParameters.locationType] ?? 12;\r\n defaultMapSettings.zoom = zoomLevel;\r\n defaultMapSettings.center = {\r\n lat: +locationParameters.originLatitude,\r\n lng: +locationParameters.originLongitude,\r\n };\r\n};\r\n\r\n/**\r\n * Update the minimum zoom level for the map according to the rules for the search within map.\r\n * If the update means the map coordinates are updating, then return without indicating\r\n * the search within map is ready to execute.\r\n *\r\n * @returns Nothing.\r\n */\r\nconst setZoomLevelForRectangularArea = () => {\r\n const areMapCoordinatesUpdating = updateMinimumZoomLevel(rectangularAreaMapSettings.maxZoom);\r\n\r\n if (areMapCoordinatesUpdating) {\r\n return;\r\n }\r\n\r\n onSearchWithinMapReady();\r\n};\r\n\r\n/**\r\n * UpdateMapPosition takes a locationParameters object and returns a newPosition object with the\r\n * latitude and longitude properties of the locationParameters object.\r\n * @param locationParameters - an object with the information of the current location.\r\n */\r\nconst updateMapPosition = (locationParameters) => {\r\n const newPosition = {\r\n latitude: +locationParameters.originLatitude,\r\n longitude: +locationParameters.originLongitude,\r\n };\r\n updateMapCenter(newPosition);\r\n};\r\n\r\n/**\r\n * A function that is called when the search within map is enabled to update the map center and minimum zoom level\r\n */\r\nconst updateMapInRectangularAreaSearch = () => {\r\n setZoomLevelForRectangularArea();\r\n};\r\n\r\n/**\r\n * A function that is called when the search within map is disable to update the map center and minimum zoom level.\r\n */\r\nconst updateMapInNotRectangularAreaSearch = (locationParameters) => {\r\n updateMapPosition(locationParameters);\r\n updateMinimumZoomLevel(defaultMapSettings.minZoom);\r\n};\r\n\r\n/**\r\n * Subscribing to the store and waiting for the map library to load.\r\n * The first time the map library is loaded, it will call the createMap function.\r\n */\r\nstore$.pipe(filter(isMapLibraryLoaded), filter(locationSearchParameters), first()).subscribe(createMap);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * The first time the location search parameters changes, and the location is not a rectangular area,\r\n * it will set the map settings like center and default zoom.\r\n * */\r\nstore$\r\n .pipe(filter(locationSearchParameters), map(locationSearchParameters), first())\r\n .subscribe(setMapSettings);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * If the current location is not a rectangular area, then the map will update its position when the location changes.\r\n */\r\nstore$\r\n .pipe(\r\n filter(isMapLibraryLoaded),\r\n map(locationSearchParameters),\r\n distinctUntilChanged(),\r\n skip(1),\r\n filter((location) => location.locationType !== LocationType.RectangularArea.toString())\r\n )\r\n .subscribe(updateMapInNotRectangularAreaSearch);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the search within map flag is set to true it means the store containing parameters\r\n * for the location information then it will call the setZoomLevelForRectangularArea function to update\r\n * the map zoom level according to the search within map rules.\r\n */\r\nstore$\r\n .pipe(\r\n filter(isMapLibraryLoaded),\r\n map(isSearchWithinMapEnabled),\r\n distinctUntilChanged(),\r\n filter(Boolean))\r\n .subscribe(updateMapInRectangularAreaSearch);\r\n \r\nfunction zoomChangedHandler(event) {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Map Zoom', 'Zoom Changed', event.detail.zoomLevel); \r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n store.dispatch(actions.updateMapZoomLevel(event.detail.zoomLevel));\r\n}\r\n\r\nmapContainer.addEventListener('zoomChanged', zoomChangedHandler);","import { store, store$ } from '@redux/store';\r\nimport {\r\n combineLatest,\r\n debounceTime,\r\n distinctUntilChanged,\r\n filter,\r\n map,\r\n pairwise,\r\n tap,\r\n distinctUntilKeyChanged,\r\n fromEvent,\r\n} from 'rxjs';\r\nimport { paintMarker, removeMarkers, updateMarkersVisibility } from 'libraries/mapLibrary';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { LocationType, ResultType, searchParametersActions, selectResultType } from 'features/searchResultsFacets';\r\nimport { selectIsMarkerAutoScrollFeatureEnabled, selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport {\r\n isFetchingResults,\r\n areMarkersAvailable,\r\n areMapBoundariesDefined,\r\n geoCoordinates,\r\n mapMarkers,\r\n selectHoveredMarker,\r\n selectGeoCoordinatesAndLocation,\r\n selectedMarker,\r\n selectedNearbyListingCarousel,\r\n selectedMarkerAndPage,\r\n selectFocusedListingAndSitePlans,\r\n selectSitePlans,\r\n} from '../redux/selectors';\r\nimport { mapStateSlice } from '../redux/slices';\r\nimport {\r\n factsSearchParameters,\r\n featuresSearchParameters,\r\n locationSearchParameters,\r\n productSearchParameters,\r\n isNotCommunityLocationType,\r\n} from '../constants/searchParametersConstants';\r\nimport { mapContainerClicked$, mapContainerDoubleClicked$ } from '../redux/observables';\r\nimport { isUserInteractingWithSitePlan } from '../services/sitePlan';\r\nimport getClassesToApply from '../services/unitMarkerService';\r\n\r\nconst { actions } = mapStateSlice;\r\nconst mapContainer = document.querySelector('#nhs_map');\r\n\r\n/**\r\n * It takes a marker object as an argument, and dispatches an action to the Redux store that sets the\r\n * selectedMarker property of the state to the marker object\r\n * @param marker - The marker object that was clicked on.\r\n */\r\nconst setActiveMarker = (marker) => {\r\n if (!marker) {\r\n store.dispatch(actions.selectedMarker(marker));\r\n return;\r\n }\r\n\r\n /*\r\n * The selectedMarker in state needs the page number,\r\n * then before to dispach the selectedMarker is necesary set it the page number\r\n * from the mapMarker state.\r\n */\r\n const newSelectedMarker = Object.assign({}, marker);\r\n const state = store.getState();\r\n const { pageNumber, isFeaturedListing } = mapMarkers(state).find((housing) => housing.id === newSelectedMarker.id);\r\n newSelectedMarker.pageNumber = pageNumber;\r\n newSelectedMarker.isFeaturedListing = !!isFeaturedListing;\r\n store.dispatch(actions.selectedMarker(newSelectedMarker));\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('markerPinCLicked', {\r\n detail: {\r\n marker: newSelectedMarker,\r\n },\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * It takes a marker object as an argument, and dispatches an action to the Redux store that sets the\r\n * selectedMarker property of the state to the marker object\r\n * @param marker - The marker object that was clicked on.\r\n */\r\nconst setActiveNearbyListingsCarousel = (listings) => store.dispatch(actions.setActiveNearbyListingsCarousel(listings));\r\n\r\n/**\r\n * setHoveredMarker: this functions stores the hovered marker so other flows interested on it can react and\r\n * act accordingly given a new marker hovered.\r\n * @param {markerInformation} markerInformation is an object with the marker itself and tooltip of the hovered marker.\r\n * @returns\r\n */\r\nconst setHoveredMarker = (markerInformation) => {\r\n if (markerInformation) {\r\n markerInformation.clonedMarker = markerInformation.marker.cloneNode(true);\r\n markerInformation.clonedTooltip = markerInformation.tooltip.cloneNode(true);\r\n }\r\n\r\n store.dispatch(actions.hoveredMarker(markerInformation));\r\n};\r\n\r\n/* Dispatching an action to the store to fetch the markers. */\r\nconst fetchResults = () => {\r\n store.dispatch(\r\n actions.fetchResults({\r\n isFetchingResults: true,\r\n parameters: store.getState().searchParameters,\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * hideNotMainTooltips: hides all the not main tooltips of a marker.\r\n * Since a single marker can represent several other markers sharing a nearby area, that single marker\r\n * is responsible of having the tooltips of all the other markers it represent. When an user is not\r\n * hovering any card, then we make sure to keep not hidden just the main tooltip of the marker in case\r\n * the user hovers that marker directly in the map.\r\n * @param {Array} tooltipArray representing the tooltips a single marker represents.\r\n */\r\nconst hideNotMainTooltips = (tooltipArray) => {\r\n tooltipArray.forEach((tooltip) => tooltip.setAttribute('hidden', ''));\r\n if (tooltipArray[0]) {\r\n tooltipArray[0].removeAttribute('hidden');\r\n }\r\n};\r\n\r\n/**\r\n * Removing active tooltip class and the hovered.\r\n */\r\nconst removeMarkerHovered = () => {\r\n const markerIcon = document.querySelector(`[data-marker-icon][data-hovered=\"true\"]`);\r\n if (!markerIcon) {\r\n return;\r\n }\r\n markerIcon.closest('[data-geographic-key]').removeAttribute('data-marker-hovered');\r\n markerIcon.classList.remove('nhs-mq-marker-hovered--large');\r\n delete markerIcon.dataset.hovered;\r\n\r\n const markerElement = markerIcon?.closest('[data-marker-element]');\r\n markerElement?.classList.remove('marker--active');\r\n};\r\n\r\n/**\r\n * Removing the the tooltip when the summary card link is clicked.\r\n */\r\nfromEvent(document, 'NearbyListingsCardLinkClick').subscribe(removeMarkerHovered);\r\n\r\n/**\r\n * Removing the active class to marker to close the marker card.\r\n */\r\nconst closeMarkerCard = () => {\r\n const markerIcon = document.querySelector(`[data-marker-icon][data-selected]`);\r\n if (!markerIcon) {\r\n return;\r\n }\r\n\r\n const markerElement = markerIcon.closest('[data-marker-element]');\r\n removeMarkerHovered();\r\n const { selected } = getClassesToApply({\r\n isBasic: markerIcon.dataset.isBasic === 'true',\r\n isNoPrice: markerIcon.dataset.isNoPrice === 'true',\r\n isSpotlight: markerIcon.dataset.isSpotlight === 'true',\r\n isSelected: true,\r\n isPriceReduction: markerIcon.dataset.isPriceReduction === 'true',\r\n });\r\n selected.forEach((className) => markerIcon.classList.remove(className));\r\n delete markerIcon.dataset.selected;\r\n markerElement?.classList.remove('active');\r\n markerElement?.classList?.remove('marker--active');\r\n hideNotMainTooltips(markerElement?.querySelectorAll('[data-tooltip]'));\r\n setHoveredMarker(null);\r\n};\r\n\r\n/**\r\n * A function that check if the marker is the active marker.\r\n */\r\nconst isMarkerActive = (marker) => {\r\n const mapState = store?.getState()?.mapState;\r\n return marker.id === mapState?.selectedMarker?.id;\r\n};\r\n\r\n/**\r\n * A function that handler markers according to the user interaction of the map.\r\n */\r\nconst handleMarkerMapChanges = () => {\r\n const state = store.getState();\r\n const isMarkerSelected = !!state.mapState.selectedMarker;\r\n const carousel = selectedNearbyListingCarousel(state);\r\n\r\n if (isMarkerSelected) {\r\n setActiveMarker(null);\r\n }\r\n\r\n if (carousel) {\r\n setActiveNearbyListingsCarousel(null);\r\n }\r\n\r\n closeMarkerCard();\r\n};\r\n\r\n/**\r\n * Add the active class to markert to open the marker card.\r\n */\r\nconst openMarkerCard = (marker) => {\r\n marker.closest('[data-geographic-key]').setAttribute('data-marker-hovered', true);\r\n marker.classList?.add('nhs-mq-marker-hovered--large');\r\n const { selected, viewed } = getClassesToApply({\r\n isBasic: marker.dataset.isBasic === 'true',\r\n isNoPrice: marker.dataset.isNoPrice === 'true',\r\n isSpotlight: marker.dataset.isSpotlight === 'true',\r\n isSelected: true,\r\n isViewed: true,\r\n });\r\n selected.forEach((className) => marker.classList.add(className));\r\n viewed.forEach((className) => marker.classList.add(className));\r\n marker.dataset.selected = true;\r\n marker.dataset.hovered = true;\r\n const markerElement = marker?.closest('[data-marker-element]');\r\n markerElement?.classList?.add('active');\r\n markerElement?.classList?.add('marker--active');\r\n};\r\n\r\n/**\r\n * Opening in new tab the url of the marker.\r\n */\r\nconst openUrl = (marker, event) => {\r\n const interactionType = event.type === 'dblclick' ? 'double_click' : 'slow_double_click';\r\n\r\n // emit custom event with marker data\r\n const customEvent = new CustomEvent('openMarkerUrl', {\r\n detail: {\r\n marker,\r\n interactionType,\r\n },\r\n });\r\n\r\n document.body.dispatchEvent(customEvent);\r\n\r\n const url = marker.url;\r\n window.open(url, '_blank');\r\n};\r\n\r\n/**\r\n * A function that is called when a marker is clicked.\r\n *\r\n * Used to emit a new action set the selectedMarker to the currently active marker object.\r\n */\r\nconst onMarkerClicked = (marker, event) => {\r\n if (event.domEvent.srcElement.hasAttribute(\"data-interactive-plan-button\")) {\r\n return;\r\n }\r\n \r\n const googleAnalyticsDTO = marker.googleAnalyticsClickEvent;\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n if (isMarkerActive(marker)) {\r\n openUrl(marker, event);\r\n removeMarkerHovered();\r\n }\r\n\r\n setActiveMarker(marker);\r\n};\r\n\r\n/**\r\n * adjustPreviousHoveredMarkerStyle: when a new marker is hovered, this function finds the previous hovered\r\n * marker (if any) and returns it to the previous styles it had.\r\n * @param {Object} previousMarkerInfo from the store; it is the previous look and feel of the current hovered marker.\r\n */\r\nconst adjustPreviousHoveredMarkerStyle = ({ previousMarkerInfo }) => {\r\n if (!previousMarkerInfo) {\r\n return;\r\n }\r\n\r\n previousMarkerInfo.marker.innerHTML = previousMarkerInfo.clonedMarker.innerHTML;\r\n previousMarkerInfo.marker.classList = previousMarkerInfo.clonedMarker.classList;\r\n hideNotMainTooltips(previousMarkerInfo.marker.closest('[data-marker-element]').querySelectorAll('[data-tooltip]'));\r\n};\r\n\r\n/**\r\n * adjustCurrentHoveredMarkerStyle: when a new marker is hovered, this function adjust its look and feel so\r\n * it represents the information of the hovered listing in an accurate way.\r\n * @param {Object} currentMarkerInfo is the information of the current hovered marker.\r\n * @returns\r\n */\r\nconst adjustCurrentHoveredMarkerStyle = ({ currentMarkerInfo }) => {\r\n if (!currentMarkerInfo) {\r\n return;\r\n }\r\n\r\n currentMarkerInfo.marker.innerHTML =\r\n currentMarkerInfo?.tooltip?.querySelector('[data-marker-clone] div')?.outerHTML || '';\r\n currentMarkerInfo.marker.classList = '';\r\n currentMarkerInfo.marker.classList.add(...currentMarkerInfo.tooltip.dataset.markerStyles.split(','));\r\n};\r\n\r\n/**\r\n * prioritizeMarkerTooltip: this function prioritizes the marker tooltip to show once a card gets hovered.\r\n * Marker found could not be the one the user is interested since a marker in the map can represent several listings,\r\n * so we make sure that the marker found represents the corresponding listing of the user's point of interest.\r\n * If the marker found is not the same as the user is interested in seeing, then we make sure to set the tooltip\r\n * that represents the interested marker information.\r\n */\r\nconst prioritizeMarkerTooltip = ({ marker, tooltip }) => {\r\n const focusedListingTooltips = marker.closest('[data-marker-element]').querySelectorAll('[data-tooltip]');\r\n focusedListingTooltips.forEach((card) => card.setAttribute('hidden', ''));\r\n tooltip?.removeAttribute('hidden');\r\n};\r\n\r\n/**\r\n * hasExternalRepresentation function will calculate if the marker we are creating has a representation already in\r\n * the map, for instance: a site plan.\r\n * @param {Object} housingLocation the marker to be created.\r\n * @returns a flag indicating wheather the marker has a representation already in the map.\r\n */\r\nconst hasExternalRepresentation = (housingLocation) => {\r\n const state = store.getState();\r\n const sitePlans = selectSitePlans(state);\r\n return sitePlans.some((sitePlan) =>\r\n sitePlan.communityId === housingLocation.communityId);\r\n}\r\n\r\n/**\r\n * CreateMarker takes a housingLocation object and returns a new object with a markerPosition property\r\n * that has a lat and lng property.\r\n * @param housingLocation - the object that contains the Lat and Lng properties\r\n */\r\nconst configureMarker = (housingLocation) => ({\r\n events: {\r\n click: onMarkerClicked,\r\n },\r\n googleAnalyticsClickEvent: housingLocation.getGoogleAnalyticsEventForClicks(),\r\n icon: housingLocation.getIcon(),\r\n id: housingLocation.id,\r\n markerPosition: {\r\n lat: +housingLocation.latitude,\r\n lng: +housingLocation.longitude,\r\n },\r\n type: housingLocation.getType(),\r\n metaData: housingLocation.getHousingLocationMetaData(),\r\n zIndex: housingLocation.zIndex,\r\n url: housingLocation.getDetailUrl(),\r\n description: housingLocation.getDescription(),\r\n ignoreVisibilityUpdates: hasExternalRepresentation(housingLocation),\r\n});\r\n\r\n/**\r\n * It takes the current markers and the new markers, and returns an object with two arrays: one with\r\n * the markers to add, and one with the markers to remove.\r\n *\r\n * The setTimeout is to allow the browser to split the task improving the performance.\r\n */\r\nconst updateMarkers = (markersFromStore) => {\r\n const markers = markersFromStore.map(configureMarker);\r\n setTimeout(() => paintMarker(markers));\r\n setTimeout(() => updateMarkersVisibility());\r\n};\r\n\r\n/**\r\n * requiresMarkerVisibilityChange determines if markers need to update their visibility, meaning: if we need to go\r\n * over ther markers to show/hide them based on the map viewport.\r\n * Function will return true if one of the following conditions happens:\r\n * * User has not changed map location, however the map changed its center, ie: user is dragging the map around.\r\n * * User is searching within map.\r\n * @param stateTransition - contains the output of a pairwise operation that brings previous and current state values.\r\n */\r\nconst requiresMarkerVisibilityChange = (stateTransition) => {\r\n const previousState = stateTransition[0];\r\n const currentState = stateTransition[1];\r\n return (\r\n (previousState.location === currentState.location && previousState.coordinates !== currentState.coordinates) ||\r\n currentState.location.locationType === LocationType.RectangularArea.toString()\r\n );\r\n};\r\n\r\n/**\r\n * Handles the selected marker by adding or removing the 'marker--active' class.\r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction handleSelectedMarker(marker) {\r\n const pastActive = document.querySelector('.marker--active');\r\n\r\n if (pastActive) {\r\n pastActive.classList.remove('marker--active');\r\n }\r\n\r\n if (marker) {\r\n const markers = document.querySelectorAll(`[data-id=\"${marker.id}\"][data-type=\"${marker.type}\"]`);\r\n\r\n markers.forEach((icon) => {\r\n const container = icon?.closest('[data-marker-element]');\r\n container?.classList.add('marker--active');\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Handles a double click event on a map marker element.\r\n * @param {Event} event - The double click event object.\r\n */\r\nfunction handleMarkerMapDoubleClick(event) {\r\n const state = store.getState()?.mapState;\r\n const marker = state?.selectedMarker;\r\n\r\n openUrl(marker, event);\r\n removeMarkerHovered();\r\n}\r\n\r\n/* \r\nSubscribe to the store$ observable to listen for changes. When markers are available, map the results\r\nproperty and compare if the value has changed from the previous execution. Then filters to see if the \r\nmap boundaries are defined. \r\n\r\nThis subscription handles the scenario when the results have changed.\r\n */\r\nstore$\r\n .pipe(filter(areMarkersAvailable), filter(areMapBoundariesDefined), map(mapMarkers), distinctUntilChanged())\r\n .subscribe((markers) => {\r\n const state = store.getState();\r\n const carousel = selectedNearbyListingCarousel(state);\r\n\r\n setTimeout(removeMarkers, 0);\r\n setTimeout(updateMarkers.bind(null, markers), 0);\r\n\r\n // only clear the summary card if available.\r\n if (carousel) {\r\n setActiveNearbyListingsCarousel(null);\r\n }\r\n });\r\n\r\n/* \r\nSubscribe to the store$ observable to listen for changes. When markers the map boundaries are available, \r\nmap the coordinates property and compare if the value has changed from the previous execution.\r\nThen filters to see if there are results defined. \r\n\r\nThis subscription handles the scenario when the map coordinates have changed.\r\n */\r\nstore$\r\n .pipe(\r\n filter(areMapBoundariesDefined),\r\n filter((state) => !isFetchingResults(state)),\r\n filter(areMarkersAvailable),\r\n map(selectGeoCoordinatesAndLocation),\r\n distinctUntilKeyChanged('coordinates'),\r\n pairwise(),\r\n filter(requiresMarkerVisibilityChange)\r\n )\r\n .subscribe(updateMarkersVisibility);\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in facts leaf change, fetch the new results for map.\r\n */\r\nconst facts$ = store$.pipe(map(factsSearchParameters), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in features leaf change, fetch the new results for map.\r\n */\r\nconst features$ = store$.pipe(map(featuresSearchParameters), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in location leaf change, fetch the new results for map.\r\n */\r\nconst location$ = store$.pipe(\r\n filter(isNotCommunityLocationType),\r\n map(locationSearchParameters),\r\n distinctUntilChanged()\r\n);\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in product leaf change, fetch the new results for map.\r\n */\r\nconst product$ = store$.pipe(map(productSearchParameters), distinctUntilChanged());\r\n\r\n/**\r\n * If some stream has changed, fetch the results.\r\n * Don't remove the debounceTime because it helps to prevent duplicate the fetch result request if\r\n * some leaf change at the same time.\r\n */\r\ncombineLatest([facts$, features$, location$, product$]).pipe(debounceTime(100)).subscribe(fetchResults);\r\n\r\n/**\r\n * Subscribing to the store$ observable to listen for changes.\r\n * When the selectedMarker changes, map the selectedMarker and compare if the value has changed to valid value.\r\n * If that is the case run the clearActiveMarker function when the value is truly when an marker is active,\r\n * otherwise run setActiveMarker.\r\n */\r\nconst selectedMarker$ = store$.pipe(map(selectedMarker), distinctUntilChanged());\r\n\r\n/**\r\n * Closes the marker card when the selectedMarker$ observable emits a value.\r\n * This is used to close any previously opened card.\r\n */\r\nselectedMarker$.subscribe(closeMarkerCard);\r\n\r\n/**\r\n * Subscribes to the `selectedMarker$` observable and opens a marker card when a marker with a valid ID is selected.\r\n * The marker icon element is extracted from the marker information and used to open the marker card.\r\n */\r\nselectedMarker$\r\n .pipe(\r\n filter((marker) => Boolean(marker?.icon)),\r\n map((marker) => marker.icon.querySelector('[data-marker-icon]'))\r\n )\r\n .subscribe(openMarkerCard);\r\n\r\n/**\r\n * Subscribing to the store$ observable to listen for changes.\r\n * When the map coordinates have changed, map the coordinates and compare if the value has changed.\r\n * If that is the case run the handleMarkerMapChanges function.\r\n */\r\nstore$.pipe(map(geoCoordinates), distinctUntilChanged()).subscribe(handleMarkerMapChanges);\r\n\r\nstore$.pipe(map(selectedMarker), distinctUntilChanged()).subscribe(handleSelectedMarker);\r\n\r\n/**\r\n * By subscribing to selectFocusedListing, we can effectively monitor changes in the Point of Interest listing.\r\n * This enables us to dynamically apply styles to the relevant marker, providing an intuitive visual indication\r\n * to the user regarding the location of a listing.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectFocusedListingAndSitePlans),\r\n distinctUntilKeyChanged('focusedListing'),\r\n filter(({ focusedListing, sitePlans }) =>\r\n !sitePlans.some((sitePlan) => sitePlan.communityId === focusedListing?.communityId)),\r\n map(({ focusedListing }) => {\r\n const markers = document.querySelectorAll(`[data-geographic-key=\"${focusedListing.geographicKey}\"]`);\r\n\r\n const focusedMarker = Array.from(markers).find(\r\n (pin) =>\r\n pin.getAttribute('data-id') === focusedListing.id ||\r\n pin.getAttribute('data-id') === focusedListing.communityId\r\n );\r\n\r\n const mainMarker = focusedMarker?.closest('[data-marker-element]');\r\n const tooltip =\r\n mainMarker?.querySelector(`[data-tooltip][data-id='${focusedListing.id}']`) ||\r\n mainMarker?.querySelector(`[data-tooltip][data-id='${focusedListing.communityId}']`);\r\n\r\n const marker = mainMarker?.querySelector('[data-marker-icon]');\r\n\r\n return {\r\n marker,\r\n tooltip,\r\n };\r\n }),\r\n tap(closeMarkerCard),\r\n filter(({ marker, tooltip }) => marker && tooltip),\r\n tap(setHoveredMarker),\r\n tap(prioritizeMarkerTooltip),\r\n map(({ marker }) => marker)\r\n )\r\n .subscribe(openMarkerCard);\r\n\r\n/**\r\n * By subscribing to \"selectHoveredMarker\", we are able to find the previous and current hovered markers and apply\r\n * operations to them. The idea of the observable is to work with the hover functionality of listings cards that is\r\n * reflected in highlighting the related markers in the map.\r\n * The selector \"selectHoveredMarker\" provides an object representing a marker and a tooltip of the interested listing,\r\n * both subscriber and \"tap\" operators of the observable are meant to work on style adjustments of this marker\r\n * to represent accurate information to the user that matches with the hovered listing card.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectHoveredMarker),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map((stateTransition) => ({\r\n previousMarkerInfo: stateTransition[0],\r\n currentMarkerInfo: stateTransition[1],\r\n })),\r\n tap(adjustPreviousHoveredMarkerStyle)\r\n )\r\n .subscribe(adjustCurrentHoveredMarkerStyle);\r\n\r\n/**\r\n * An observable that emits when the map container is double-clicked, and the click target is an element with the\r\n * `data-marker-element` attribute.\r\n */\r\nconst markerDoubleClicked$ = mapContainerDoubleClicked$.pipe(\r\n filter((event) => event.target.closest('[data-marker-element]'))\r\n);\r\n\r\n/**\r\n * Listens for a double click event on the map container element and subscribes to the handleMarkerMapDoubleClick\r\n * function. This allows the application to handle double click events on map markers and open the associated URL.\r\n */\r\n\r\nmarkerDoubleClicked$.subscribe(handleMarkerMapDoubleClick);\r\n/**\r\n * Listening for a click event on the map.\r\n */\r\nmapContainer.addEventListener('mapHide', handleMarkerMapChanges);\r\n\r\nmapContainerClicked$\r\n .pipe(\r\n filter((event) => !isUserInteractingWithSitePlan(event)),\r\n filter(({ target }) => !target.closest('[data-marker-icon]'))\r\n )\r\n .subscribe(handleMarkerMapChanges);\r\n\r\n/*\r\n * Observable to raise the fetchPageNumber when the selected marker changed and:\r\n * 1. Isn't a small layout.\r\n * 2. The feature of AutoScroll is enable.\r\n * 3. The selected marker has page number.\r\n * 4. And the page of selected marker is different to the current listing page.\r\n */\r\nstore$\r\n .pipe(\r\n filter((state) => selectLayoutBreakpoint(state).getValue() !== LayoutBreakpoint.Small.getValue()),\r\n filter((state) => selectResultType(state) === ResultType.Communities.toString()),\r\n filter((state) => selectIsMarkerAutoScrollFeatureEnabled(state) === true),\r\n map(selectedMarkerAndPage),\r\n distinctUntilKeyChanged('marker'),\r\n filter(({ marker }) => marker?.pageNumber),\r\n filter(({ marker, page }) => marker.pageNumber !== page)\r\n )\r\n .subscribe(({ marker }) => store.dispatch(searchParametersActions.fetchPageNumber(marker.pageNumber)));\r\n","import { store$ } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { selectedMarker } from '../redux/selectors';\r\nimport { saveViewedMarker } from '../services/markerSessionService';\r\n\r\n/**\r\n * Subscribing to the store$ observable to listen for changes.\r\n * When the selectedMarker changes, map the selectedMarker and compare if the value has changed to valid value.\r\n * If that is the case run the savedViewdMarker function when the value is truly when an marker is active.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectedMarker),\r\n distinctUntilChanged(),\r\n filter(marker => Boolean(marker?.id)))\r\n .subscribe(saveViewedMarker);","import { store$, store } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map, fromEvent, merge, withLatestFrom } from 'rxjs';\r\nimport fastdom from 'fastdom';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectIsMarkerAutoScrollFeatureEnabled, selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport { ResultType, selectResultType } from 'features/searchResultsFacets';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport { pairwise } from 'rxjs/operators';\r\nimport { mapStateSlice } from '../redux/slices';\r\nimport { selectNearbyListingsCarouselStatusAndMarkerData, selectedNearbyListingCarousel } from '../redux/selectors';\r\nimport SummaryCardSkeleton from './skeletons/summaryCardSkeleton';\r\nimport getCard from '../services/processSummaryCard';\r\n\r\nconst { actions } = uiStateSlice;\r\nconst mapActions = mapStateSlice.actions;\r\n\r\n/**\r\n * Removes the carousel from the page.\r\n */\r\nfunction closeNearbyListingsCarousel(carousel) {\r\n const carouselContainer = document.querySelector('[data-map-carousel]');\r\n const cardsContainer = document.querySelector('[data-summary-card]');\r\n\r\n if (cardsContainer) {\r\n fastdom.mutate(() => {\r\n cardsContainer.innerHTML = '';\r\n carouselContainer.setAttribute('hidden', '');\r\n });\r\n }\r\n\r\n const card = document.querySelector('[data-summary-content].active');\r\n const id = card?.getAttribute('data-id');\r\n const type = card?.getAttribute('data-type');\r\n\r\n const activeItem = carousel?.find((item) => item.Id === Number(id));\r\n\r\n const event = new CustomEvent('carouselClose', {\r\n detail: {\r\n activeItem,\r\n type,\r\n },\r\n });\r\n\r\n setTimeout(() => {\r\n document.dispatchEvent(event);\r\n }, 0);\r\n}\r\n\r\nconst onCardCtaClicked$ = fromEvent(document, 'summaryCardCtaClick');\r\nonCardCtaClicked$.subscribe((card) => {\r\n const { type, id, name, url, variation } = card.detail;\r\n store.dispatch(\r\n actions.modalInformation({\r\n type,\r\n id,\r\n name,\r\n url,\r\n variation,\r\n })\r\n );\r\n});\r\n\r\n// Create a new observable to listen for changes in selectedNearbyListingCarousel\r\nconst selectedNearbyListingCarousel$ = store$.pipe(map(selectedNearbyListingCarousel), distinctUntilChanged());\r\n\r\n// Create an observable to listen for the close icon click event\r\nconst cardCloseClick$ = fromEvent(document, 'carouselClose');\r\n\r\nconst hamburgerMenuClicked$ = fromEvent(document.body, 'hamburgerMenuClicked');\r\nconst advancedFiltersClicked$ = fromEvent(document.body, 'advancedFiltersClicked');\r\nconst ListViewToggled$ = fromEvent(document.body, 'listViewToggled');\r\n\r\n// Subscribe to the selectedNearbyListingCarousel$ observable and\r\n// use the pairwise operator to get the previous and current carousel values.\r\nselectedNearbyListingCarousel$.pipe(pairwise()).subscribe(([previousCarousel, currentCarousel]) => {\r\n // If there is no current carousel, close the previous carousel.\r\n if (!currentCarousel && previousCarousel) {\r\n setTimeout(() => closeNearbyListingsCarousel(previousCarousel), 0);\r\n }\r\n});\r\n\r\n/**\r\n * Handles the display of a skeleton card while the actual carousel data is being loaded.\r\n */\r\nfunction handleSummaryCardSkeleton() {\r\n const carouselContainer = document.querySelector('[data-map-carousel]');\r\n const cardsContainer = document.querySelector('[data-summary-card]');\r\n const skeleton = new SummaryCardSkeleton();\r\n\r\n fastdom.mutate(() => {\r\n carouselContainer.removeAttribute('hidden');\r\n cardsContainer.innerHTML = skeleton.getHtml();\r\n });\r\n}\r\n\r\n/**\r\n * Handles the removal of a skeleton card when the ajax call failed.\r\n */\r\nfunction removeSummaryCardSkeletonOnFail() {\r\n const carouselContainer = document.querySelector('[data-map-carousel]');\r\n const container = document.querySelector('[data-summary-card]');\r\n\r\n fastdom.mutate(() => {\r\n container.innerHTML = '';\r\n carouselContainer.setAttribute('hidden', true);\r\n });\r\n}\r\n\r\n/**\r\n * Subscribes to the nearby listings carousel loading status in the Redux store. This ensures that a skeleton\r\n * loading indicator is displayed while the actual carousel data is being loaded.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectNearbyListingsCarouselStatusAndMarkerData),\r\n filter((data) => data?.status === LoadingStatus.Loading.toString() && Boolean(data?.marker?.id)),\r\n distinctUntilChanged(),\r\n filter(() => {\r\n const state = store.getState();\r\n const IsMarkerAutoScrollFeatureEnabled = selectIsMarkerAutoScrollFeatureEnabled(state);\r\n\r\n // if auto scroll feature flag is off, then go ahead and display the skeleton card.\r\n if (!IsMarkerAutoScrollFeatureEnabled) {\r\n return true;\r\n }\r\n\r\n // since auto scroll feature flag is on, we have to calculate if we have to show the skeleton card.\r\n // we show the skeleton for:\r\n // 1. all plans, specs and buildable plan pines on the home results page\r\n const layoutBreakpoint = selectLayoutBreakpoint(state);\r\n const resultType = selectResultType(state);\r\n\r\n return resultType === ResultType.Homes.toString() || layoutBreakpoint.text === LayoutBreakpoint.Small.toString();\r\n })\r\n )\r\n .subscribe(handleSummaryCardSkeleton);\r\n\r\n /**\r\n * Subscribes to the nearby listings carousel loading status in the Redux store. This ensures that a skeleton\r\n * loading indicator is removed when the Ajax call failed.\r\n */\r\nstore$\r\n.pipe(\r\n map(selectNearbyListingsCarouselStatusAndMarkerData),\r\n distinctUntilChanged(),\r\n filter((data) => data?.status === LoadingStatus.Failed.toString()),\r\n)\r\n.subscribe(removeSummaryCardSkeletonOnFail);\r\n\r\nconst nearbyListingsCarouselSelected$ = store$.pipe(\r\n map(selectedNearbyListingCarousel),\r\n distinctUntilChanged(),\r\n filter(Boolean)\r\n);\r\n\r\nfunction bindCloseEvent() {\r\n const closeButton = document.querySelector('[data-summary-card-close]');\r\n\r\n closeButton?.addEventListener('click', () => {\r\n setTimeout(() => {\r\n store.dispatch(mapActions.clearNearbyListingsCarousel(null));\r\n }, 0);\r\n });\r\n}\r\n\r\n/**\r\n * An object that holds the state of the Intersection Observer used to track the visibility of carousel cards.\r\n * @property {IntersectionObserver} instance - The Intersection Observer instance.\r\n * @property {number} previousCardPosition - The position of the previously visible card in the carousel.\r\n * @property {HTMLElement[]} observedElements - The carousel cards being observed by the Intersection Observer.\r\n */\r\nconst observer = {\r\n instance: null,\r\n previousCardPosition: null,\r\n observedElements: [],\r\n};\r\n\r\n/**\r\n * Creates an IntersectionObserver instance to track the visibility of carousel cards.\r\n * The observer callback dispatches a 'carouselScroll' event with information about the card's\r\n * position and direction of scroll when a card becomes visible.\r\n */\r\nfunction createIntersectionObserver() {\r\n const observerOptions = {\r\n root: document.querySelector('[data-summary-card]'),\r\n threshold: 1.0, // Trigger only when 100% of the card is in view\r\n rootMargin: '0px', // Ensure no margin is considered\r\n };\r\n\r\n /**\r\n * Handles the callback for the Intersection Observer, which is used to track the visibility of the carousel cards.\r\n * @param {Array} entries - The array of observed elements and their intersection states.\r\n */\r\n const observerCallback = (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting) {\r\n const state = store.getState();\r\n const card = entry.target;\r\n const currentCardPosition = Array.from(card.parentNode.children).indexOf(card) + 1;\r\n let direction = null;\r\n if (observer.previousCardPosition !== null) {\r\n if (currentCardPosition > observer.previousCardPosition) {\r\n direction = 'right';\r\n } else {\r\n direction = 'left';\r\n }\r\n }\r\n\r\n observer.previousCardPosition = currentCardPosition;\r\n\r\n // if the card is visible, and there's a scroll direction, then\r\n // then dispatch the events and actions to change the highlighted\r\n // listing and to trigger the events.\r\n if (card) {\r\n const cardLatitude = card.getAttribute('data-latitude');\r\n const cardLongitude = card.getAttribute('data-longitude');\r\n const geographicKey = createMarkerHashedKey(cardLatitude, cardLongitude);\r\n const listingId = card.getAttribute('data-id');\r\n const type = card.getAttribute('data-type');\r\n\r\n store.dispatch(\r\n uiStateSlice.actions.focusedListingInformation({\r\n id: card.getAttribute('data-id'),\r\n communityId: card.getAttribute('data-community-id'),\r\n geographicKey,\r\n })\r\n );\r\n\r\n const nearbyListings = selectedNearbyListingCarousel(state);\r\n const activeItem = nearbyListings.find((listing) => listing.Id === Number(listingId));\r\n\r\n // Add active class to the current card\r\n fastdom.mutate(() => {\r\n card.classList.add('active');\r\n });\r\n\r\n // if the card is the first card, and there's no scroll direction, then\r\n // avoid dispatching the swipe event.\r\n if (!direction && currentCardPosition === 1) {\r\n return;\r\n }\r\n\r\n const event = new CustomEvent('carouselScroll', {\r\n detail: {\r\n direction,\r\n currentCardPosition,\r\n nextCardPosition: currentCardPosition + 1,\r\n listingId,\r\n type,\r\n activeItem,\r\n },\r\n });\r\n\r\n setTimeout(() => {\r\n document.dispatchEvent(event);\r\n }, 0);\r\n }\r\n } else {\r\n // Remove active class from the card when it is not visible\r\n const card = entry.target;\r\n fastdom.mutate(() => {\r\n card.classList.remove('active');\r\n });\r\n }\r\n });\r\n };\r\n\r\n observer.instance = new IntersectionObserver(observerCallback, observerOptions);\r\n}\r\n\r\n/**\r\n * Observes the given cards using the Intersection Observer.\r\n * @param {Array} cards - The array of card elements.\r\n */\r\nfunction observeCards(cards) {\r\n // Create the observer if it doesn't exist\r\n if (!observer.instance) {\r\n createIntersectionObserver();\r\n }\r\n\r\n // Unobserve previously observed elements\r\n while (observer.observedElements.length > 0) {\r\n const element = observer.observedElements.shift();\r\n observer.instance.unobserve(element);\r\n }\r\n\r\n // Reset previousCardPosition when observing a new batch of items\r\n observer.previousCardPosition = null;\r\n\r\n // Observe new elements\r\n const elements = cards?.map((card) => card.getElement());\r\n elements?.forEach((card) => {\r\n observer.instance.observe(card);\r\n observer.observedElements.push(card);\r\n });\r\n}\r\n\r\n/**\r\n * Handles the selected marker being selected, displays the carousel\r\n * once the data is fetched from the server.\r\n * @param {Object} listings - The data for the carousel.\r\n */\r\nfunction renderCarousel(listings) {\r\n const container = document.querySelector('[data-summary-card]');\r\n\r\n fastdom.mutate(() => {\r\n container.innerHTML = '';\r\n });\r\n\r\n const cards = listings.map((listing) => getCard(listing));\r\n const fragment = document.createDocumentFragment();\r\n\r\n cards.forEach((card) => {\r\n const html = card.getHtml();\r\n const range = document.createRange();\r\n const documentFragment = range.createContextualFragment(html);\r\n fragment.appendChild(documentFragment);\r\n });\r\n\r\n fastdom.mutate(() => {\r\n container.appendChild(fragment);\r\n\r\n // Bind events to the cards after they are in the DOM\r\n cards.forEach((card) => {\r\n card.bindEvents();\r\n });\r\n\r\n // Observe the new cards\r\n observeCards(cards);\r\n });\r\n}\r\n\r\nbindCloseEvent();\r\n\r\nnearbyListingsCarouselSelected$.subscribe(renderCarousel);\r\n\r\nconst closeNearbyListingsCardOnElementClicked$ = merge(\r\n onCardCtaClicked$,\r\n cardCloseClick$,\r\n hamburgerMenuClicked$,\r\n advancedFiltersClicked$,\r\n ListViewToggled$\r\n);\r\n\r\ncloseNearbyListingsCardOnElementClicked$\r\n .pipe(\r\n withLatestFrom(selectedNearbyListingCarousel$),\r\n filter(([, carousel]) => Boolean(carousel?.length))\r\n )\r\n .subscribe(() => {\r\n store.dispatch(mapActions.clearNearbyListingsCarousel(null));\r\n });\r\n","/**\r\n * This handler is in charge of community site plans in NewHomeSource Search Resul Page's map. It interacts with\r\n * Map Library facade for specific maps operations, like creating or removing the community site plan, however:\r\n * the logic about when to fetch the request to bring Community site plan's information from the server, store\r\n * and render them is responsibility of this handler itself.\r\n */\r\nimport { store, store$ } from '@redux/store';\r\nimport { \r\n BehaviorSubject,\r\n combineLatest,\r\n distinctUntilChanged,\r\n distinctUntilKeyChanged,\r\n filter,\r\n fromEvent,\r\n map,\r\n merge,\r\n pairwise,\r\n switchMap,\r\n tap,\r\n withLatestFrom,\r\n} from 'rxjs';\r\nimport {\r\n createSitePlanOverlay,\r\n getSitePlansOutOfViewport,\r\n hideMarkers,\r\n isSitePlanIntersectingMapBounds,\r\n removeSitePlanOverlay,\r\n showMarkers\r\n} from 'libraries/mapLibrary';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport {\r\n mapMarkers,\r\n selectSitePlansProperties,\r\n selectSitePlans,\r\n selectFocusedListingAndSitePlans,\r\n selectMarkersAndSitePlans,\r\n selectZoomLevel,\r\n} from '../redux/selectors';\r\nimport {\r\n drawSitePlan,\r\n getSitePlan,\r\n getCommunityInteractiveMapContainer,\r\n getCommunityStaticMapContainer,\r\n getSitePlanTooltip,\r\n getDeviceType,\r\n getInteractiveOverlay,\r\n hideSitePlansTooltips,\r\n onDoubleClick$,\r\n onMouseLeave$,\r\n onMouseMove$,\r\n onSingleClick$,\r\n removeActiveSitePlans,\r\n removeSitePlan,\r\n searchSitePlans$,\r\n } from '../services/sitePlan';\r\nimport { mapStateSlice } from '../redux/slices';\r\nimport { zoomLevelTriggers } from '../constants/sitePlansConstants';\r\nimport MarkerType from '../enums/markerType';\r\n\r\nconst { actions } = mapStateSlice;\r\n\r\n/**\r\n * Basic configuration for a functional experience of site plans. It contains properties as the zoom triggers\r\n * for fetching and drawing the site plan, an array of the already fetched resources so they don't need\r\n * to be fetched again, and a loading status for the fetch operations.\r\n */\r\nconst configuration = {\r\n sitePlansReadyToRender: [],\r\n fetchMapsStatus: LoadingStatus.Idle,\r\n fetchStatus$: new BehaviorSubject(LoadingStatus.Idle),\r\n sitePlanHoveredStartTime: null,\r\n hoveredSitePlan: null,\r\n setFetchStatus(value) {\r\n if (this.fetchMapsStatus.name !== value.name) {\r\n this.fetchMapsStatus = value;\r\n this.fetchStatus$.next(value);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * findMarker retrieves a marker filtered by Id and type.\r\n * @param {Array} markers collection where we are going to find a given marker.\r\n * @param {int} markerId identifier for the marker we are querying.\r\n * @returns a marker retrieved by id.\r\n */\r\nconst findMarker = (markers, markerId) => {\r\n const preferredTypes = new Set([\r\n MarkerType.HousingDevelopment.toString(),\r\n MarkerType.BuildablePlan.toString()\r\n ]);\r\n \r\n return markers\r\n .filter(marker => marker.communityId === markerId)\r\n .reduce((bestMarker, marker) => {\r\n if (preferredTypes.has(marker.type)) {\r\n return preferredTypes.has(bestMarker?.type) ? bestMarker : marker;\r\n }\r\n return bestMarker || marker;\r\n }, null);\r\n };\r\n\r\n/**\r\n * onNewMarkers$ observable that would emit every time there are new markers in the store.\r\n */\r\nconst onNewMarkers$ = store$.pipe(\r\n map(selectSitePlansProperties),\r\n filter(({ zoomLevel }) => zoomLevel),\r\n distinctUntilKeyChanged('isFetching'),\r\n filter(({ isFetching }) => !isFetching));\r\n\r\n/**\r\n * onSitePlansChanged$ observable that will emit every time\r\n * there are changes in the site plans in the store.\r\n */\r\nconst onSitePlansChanged$ = store$.pipe(\r\n map(selectSitePlans),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * mapRemovedSitePlans function will map any site plan\r\n * not presented in the markers array.\r\n * @param {Array} markers is the current collection of markers in the map.\r\n * @param {Array} sitePlans is the current collection of site plans in the map.\r\n * @returns a collection of site plans no longer needed as there is no marker for them.\r\n */\r\nconst mapRemovedSitePlans = (markers, sitePlans) =>\r\n sitePlans.filter((sitePlan) =>\r\n !markers.some((marker) => marker.communityId === sitePlan.communityId));\r\n\r\n/**\r\n * onRemoveNonNeededSitePlans$ observable that will emit every time new markers\r\n * are available in order to detect site plans not longer needed.\r\n */\r\nconst onRemoveNonNeededSitePlans$ = onNewMarkers$.pipe(\r\n withLatestFrom(onSitePlansChanged$),\r\n map(([{ markers }, sitePlans]) => mapRemovedSitePlans(markers, sitePlans)));\r\n\r\n/**\r\n * onMapCoordinatesChanged$ observable that would emit every time map coordinates changes in the store.\r\n */\r\nconst onMapCoordinatesChanged$ = store$.pipe(\r\n map(selectSitePlansProperties),\r\n filter(({ zoomLevel }) => !!zoomLevel),\r\n filter(({ isMapLoaded }) => isMapLoaded),\r\n distinctUntilKeyChanged('coordinates'));\r\n\r\n/**\r\n * createSitePlan function invokes map library facade with the site plan configuration to be draw.\r\n * @param {Object} sitePlan assiciated with a visible marker in viewport.\r\n */\r\nconst createSitePlan = (sitePlan) => {\r\n const newSitePlan = {\r\n communityId: sitePlan.communityId,\r\n url: sitePlan.imageUrl,\r\n isInteractiveSitePlan: sitePlan.isInteractiveSitePlan,\r\n sitePlanId: sitePlan.sitePlanId,\r\n sitePlanLayers: sitePlan.sitePlanLayers,\r\n };\r\n\r\n store.dispatch(actions.addSitePlan(newSitePlan));\r\n}\r\n\r\n/**\r\n * draw function is an async function in charge of interacting with Map Library facade by providing it with\r\n * information that will end up in a site plan draw in the map. This information is collected\r\n * from the sitePlansReadyToRender array from this handle's configuration.\r\n */\r\nconst dispatchSitePlans = async () => {\r\n const state = store.getState();\r\n const sitePlans = selectSitePlans(state);\r\n const seenCommunityIds = new Set();\r\n const filteredMarkers = mapMarkers(state)\r\n .filter(element => {\r\n if (seenCommunityIds.has(element.communityId)) {\r\n return false;\r\n }\r\n seenCommunityIds.add(element.communityId);\r\n return true;\r\n })\r\n .filter((marker) => {\r\n const communitySitePlans = configuration.sitePlansReadyToRender\r\n .filter((item) => item.communityId === marker.communityId);\r\n \r\n return communitySitePlans.some(isSitePlanIntersectingMapBounds);\r\n });\r\n\r\n filteredMarkers.forEach((marker) => {\r\n const mapConfigurations =\r\n configuration.sitePlansReadyToRender.filter((item) => item.communityId === marker.communityId);\r\n\r\n if (mapConfigurations.length > 0) {\r\n mapConfigurations.forEach(async (mapConfiguration) => {\r\n const isMapAlreadyShown = sitePlans.findIndex((item) => \r\n item.communityId === mapConfiguration.communityId && item.url === mapConfiguration.imageUrl) !== -1;\r\n\r\n if (isMapAlreadyShown) {\r\n return;\r\n }\r\n\r\n createSitePlan(mapConfiguration);\r\n });\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * drawSitePlans function renders on the map a new site plan.\r\n * @param {Object} sitePlan with the id and url to render a new community site plan.\r\n */\r\nconst drawSitePlans = async ({ sitePlan }) => {\r\n const mapConfiguration = configuration.sitePlansReadyToRender.\r\n find((item) => sitePlan.communityId === item.communityId && sitePlan.url === item.imageUrl);\r\n \r\n const currentZoomLevel = selectZoomLevel(store.getState());\r\n\r\n const promises = [\r\n mapConfiguration.isInteractiveSitePlan\r\n ? getCommunityInteractiveMapContainer(mapConfiguration, currentZoomLevel)\r\n : getCommunityStaticMapContainer(mapConfiguration)\r\n ];\r\n\r\n if (selectLayoutBreakpoint(store.getState()) !== LayoutBreakpoint.Small) {\r\n promises.push(getSitePlanTooltip(mapConfiguration));\r\n }\r\n\r\n const [sitePlanContainer, tooltip] = await Promise.all(promises);\r\n\r\n if (!sitePlanContainer) {\r\n return;\r\n }\r\n\r\n mapConfiguration.container = sitePlanContainer;\r\n mapConfiguration.overlay = getInteractiveOverlay(mapConfiguration);\r\n mapConfiguration.tooltip = tooltip;\r\n mapConfiguration.polygonsContainer =\r\n sitePlanContainer.parentElement.querySelector('[data-polygons-container-community-id]');\r\n\r\n mapConfiguration.onRemove = removeSitePlan;\r\n mapConfiguration.onDraw = drawSitePlan;\r\n mapConfiguration.onSingleClick$ = onSingleClick$(mapConfiguration.overlay);\r\n mapConfiguration.onDoubleClick$ = onDoubleClick$(mapConfiguration.overlay);\r\n mapConfiguration.onMouseMove$ = onMouseMove$(mapConfiguration.overlay);\r\n mapConfiguration.onMouseLeave$ = onMouseLeave$(mapConfiguration.overlay);\r\n\r\n createSitePlanOverlay(mapConfiguration);\r\n};\r\n\r\n/**\r\n * removeSitePlans removes all of the site plans.\r\n */\r\nconst removeSitePlans = () => {\r\n const visibleSitePlans = selectSitePlans(store.getState());\r\n visibleSitePlans.forEach((sitePlan) => {\r\n removeSitePlanOverlay(sitePlan.communityId);\r\n store.dispatch(actions.removeSitePlan(sitePlan));\r\n })\r\n}\r\n\r\n/**\r\n * removeSpecificSitePlans function will take a list of site plans\r\n * and remove them from the store and the layout.\r\n * @param {Array} sitePlans collection of community site plans to remove.\r\n */\r\nconst removeSpecificSitePlans = (sitePlans) => {\r\n sitePlans.forEach((sitePlan) => {\r\n removeSitePlanOverlay(sitePlan.communityId);\r\n store.dispatch(actions.removeSitePlan(sitePlan));\r\n })\r\n}\r\n\r\n/**\r\n * handleSitePlansInformation in a function that will create configuration objects for the retrieved\r\n * site plans from server side.\r\n * This function is async because we need to wait for the site plan's url request to be done before changing our\r\n * fetchMapsStatus property in this handler's configuration.\r\n * @param {Array} sitePlans metadata retrieved needed to render the site plan resources.\r\n */\r\nconst handleSitePlansInformation = ({ sitePlans, markers }) => {\r\n sitePlans.forEach(element => {\r\n const sitePlanConfiguration = {\r\n viewboxHeight: element.ViewBoxHeight,\r\n viewboxWidth: element.ViewBoxWidth,\r\n rotationDegrees: element.Rotation,\r\n svgMask: element.SvgMask,\r\n imageUrl: element.MapImageUrl,\r\n north: element.TopRightLatitude,\r\n south: element.BottomLeftLatitude,\r\n east: element.TopRightLongitude,\r\n west: element.BottomLeftLongitude,\r\n communityId: element.CommunityId,\r\n isInteractiveSitePlan: element.IsInteractiveSitePlan,\r\n sitePlanId: element.SitePlanId,\r\n sitePlanLayers: element.SvgLayers,\r\n };\r\n\r\n const isSitePlanConfigurationAlreadyAdded = configuration.sitePlansReadyToRender.find(sitePlan =>\r\n sitePlan.communityId === sitePlanConfiguration.communityId &&\r\n sitePlan.imageUrl === sitePlanConfiguration.imageUrl\r\n );\r\n\r\n if (!isSitePlanConfigurationAlreadyAdded) {\r\n const marker = findMarker(markers, element.CommunityId);\r\n sitePlanConfiguration.communityId = marker?.communityId;\r\n configuration.sitePlansReadyToRender.push(sitePlanConfiguration);\r\n }\r\n });\r\n\r\n configuration.setFetchStatus(LoadingStatus.Succeeded);\r\n};\r\n\r\n/**\r\n * The `onMapReadyTofetchAfterCoordinatesChanged$` observable emits whenever the zoom level is valid \r\n * for fetching site plan resources. It also checks that \"Search Within Map\" is disabled and ensures \r\n * that the fetching of resources is not currently in progress or has not already been completed \r\n * in a prior interaction.\r\n */\r\nconst onMapReadyTofetchAfterCoordinatesChanged$ = onMapCoordinatesChanged$.pipe(\r\n filter(({ zoomLevel }) => zoomLevel >= zoomLevelTriggers.zoomLevelSitePlansFetchTrigger),\r\n filter(({ isSearchWithinMap }) => !isSearchWithinMap),\r\n filter(({ markers }) => markers && markers.length > 0),\r\n filter(() => configuration.fetchMapsStatus.name !== LoadingStatus.Loading.toString() &&\r\n configuration.fetchMapsStatus.name !== LoadingStatus.Succeeded.toString()));\r\n\r\n/**\r\n * The `onFetchMapsForNewMarkers$` observable emits whenever new markers are loaded into the store.\r\n * It also checks the current map zoom leve, If it meets the criteria for fetching site plan\r\n * resources from the server, the observable will emit.\r\n */\r\nconst onFetchMapsForNewMarkers$ = onNewMarkers$.pipe(\r\n filter(({ zoomLevel }) => zoomLevel >= zoomLevelTriggers.zoomLevelSitePlansFetchTrigger));\r\n\r\n/**\r\n * fetchResults$ is in charge of emiting site plan metadata retrieved after requesting it to the server.\r\n */\r\nconst fetchResults$ = merge(onMapReadyTofetchAfterCoordinatesChanged$, onFetchMapsForNewMarkers$).pipe(\r\n map(({ markers }) => {\r\n const retrievedStaticMapIds = new Set(configuration.sitePlansReadyToRender.map(item => item.communityId));\r\n const uniqueMarkers = new Map();\r\n \r\n markers.forEach(marker => {\r\n if (!retrievedStaticMapIds.has(marker.communityId) && !uniqueMarkers.has(marker.communityId)) {\r\n uniqueMarkers.set(marker.communityId, marker);\r\n }\r\n });\r\n \r\n return Array.from(uniqueMarkers.values());\r\n }),\r\n filter(markers => markers.length > 0),\r\n tap(() => {\r\n configuration.setFetchStatus(LoadingStatus.Loading);\r\n }),\r\n switchMap((markers) => searchSitePlans$(markers))\r\n );\r\n\r\n/**\r\n * onNewListings$ will stream a value every time there are new listings available.\r\n */\r\nconst onNewListings$ = store$.pipe(\r\n map(mapMarkers),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * ondrawSitePlans$ observable would emit a value when there are site plans calculated\r\n * from the server and the map has a zoom level that meets the criteria for rendering those site plans.\r\n */\r\nconst ondrawSitePlans$ = combineLatest([\r\n configuration.fetchStatus$,\r\n onMapCoordinatesChanged$,\r\n onNewListings$\r\n]).pipe(\r\n filter(([, { zoomLevel }]) => zoomLevel >= zoomLevelTriggers.zoomLevelDrawSitePlansTrigger),\r\n filter(([fetchStatus]) => fetchStatus.name === LoadingStatus.Succeeded.toString()));\r\n\r\n/**\r\n * onRemoveSitePlans$ observable would emit a value when the zoom level is in a threshold where we\r\n * preffer to show markers than site plan. When we get to that threshold: then we hide any\r\n * visible site plans and their respective tooltips.\r\n */\r\nconst onRemoveSitePlans$ = combineLatest([\r\n configuration.fetchStatus$,\r\n onMapCoordinatesChanged$\r\n]).pipe(\r\n filter(([, { zoomLevel }]) => zoomLevel < zoomLevelTriggers.zoomLevelDrawSitePlansTrigger),\r\n filter(([fetchStatus]) => fetchStatus.name === LoadingStatus.Succeeded.toString()));\r\n\r\n/**\r\n * hideSitePlanMarkers function will identify amd hide markers that needs to be\r\n * hidden as their site plan was created due to zoom level changes.\r\n * @param {Array} addedSitePlans is the collection of the current shown community site plans.\r\n * @param {Array} markers is the collection of the current shown markers.\r\n */\r\nconst hideSitePlanMarkers = (addedSitePlans, markers) => {\r\n const markersToHide = markers.filter(marker => \r\n addedSitePlans.some(sitePlan => sitePlan.communityId === marker.communityId)\r\n );\r\n\r\n markersToHide.forEach(marker => hideMarkers(marker.communityId));\r\n};\r\n\r\n/**\r\n * showSitePlanMarkers function will identify amd show markers that needs to be\r\n * shown as their site plan was removed due to zoom level changes.\r\n * @param {Array} removedSitePlans is the collection of the removed community site plans.\r\n * @param {Array} markers is the collection of the current shown markers.\r\n */\r\nconst showSitePlanMarkers = (removedSitePlans, markers) => {\r\n const markersToShow = markers.filter(marker => \r\n removedSitePlans.some(sitePlan => sitePlan.communityId === marker.communityId)\r\n );\r\n\r\n markersToShow.forEach(marker => showMarkers(marker.communityId));\r\n};\r\n\r\n/**\r\n * removeSitePlansNotInViewPort$ function will identify and remove from the map\r\n * those site plans that are no longer within the user viewport.\r\n */\r\nconst removeSitePlansNotInViewPort$ = ({sitePlans}) => {\r\n const mapsNotInViewPort = getSitePlansOutOfViewport();\r\n\r\n /**\r\n * there are site plans composed with separated pieces. If some of these pieces is not in the\r\n * viewport, it could be weird to remove part of the community representation. This is why we\r\n * are making sure to remove maps only if all of the pieces that represent a community\r\n * are not in the viewport.\r\n */\r\n const filteredSitePlans = mapsNotInViewPort.filter((sitePlan) => {\r\n const visibleSitePlans =\r\n sitePlans.filter((visibleMap) => visibleMap.communityId === sitePlan.communityId).length;\r\n const notVisibleSitePlans =\r\n mapsNotInViewPort.filter((NotVisibleMap) => NotVisibleMap.communityId === sitePlan.communityId).length;\r\n\r\n return visibleSitePlans === notVisibleSitePlans;\r\n });\r\n\r\n removeSpecificSitePlans(filteredSitePlans);\r\n}\r\n\r\n/**\r\n * dispatchZoomChangedInformation triggers a custom event with the rendered site plans and\r\n * the zoom gesture from the latest user interaction in the map.\r\n * @param {String} zoomGesture represents if the zoom was a zoom out or zoom in.\r\n * @param {int} zoomLevel represents the current map zoom level.\r\n * @param {Array} sitePlans is a collection of rendered site plans.\r\n */\r\nconst dispatchZoomChangedInformation = ({ zoomGesture, sitePlans, zoomLevel }) => {\r\n sitePlans.forEach((communityMap) => {\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapZoom', {\r\n detail: {\r\n communityMap,\r\n zoomGesture,\r\n deviceType: getDeviceType(),\r\n zoomLevel,\r\n },\r\n })\r\n );\r\n })\r\n}\r\n\r\n/**\r\n * handleHoverStartOrSwitch function will track the moment where a hover over gesture\r\n * started in a site plan.\r\n * @param {boolean} isMouseMovingOnMap is flag indicating if mouse is hovering over site plan. \r\n * @param {Object} sitePlan being hovered by the user.\r\n */\r\nconst handleHoverStartOrSwitch = ({ isMouseMovingOnMap, sitePlan, deviceType }) => {\r\n if (isMouseMovingOnMap && configuration.sitePlanHoveredStartTime == null) {\r\n // Start timing for the current site plan\r\n configuration.sitePlanHoveredStartTime = Date.now();\r\n configuration.hoveredSitePlan = sitePlan;\r\n } else if (isMouseMovingOnMap && configuration.hoveredSitePlan.communityId !== sitePlan.communityId) {\r\n // Emit hover duration for the previous site plan\r\n const hoverDuration = Date.now() - configuration.sitePlanHoveredStartTime;\r\n const sitePlanToEmit = Object.assign({}, configuration.hoveredSitePlan);\r\n\r\n // Restart timing for the new map\r\n configuration.sitePlanHoveredStartTime = Date.now();\r\n configuration.hoveredSitePlan = sitePlan;\r\n\r\n // Dispatch the hover duration event\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapHover', {\r\n detail: {\r\n communityMap: sitePlanToEmit,\r\n hoverDuration,\r\n deviceType,\r\n },\r\n }));\r\n }\r\n};\r\n\r\n/**\r\n * handleHoverEnd function track the time when hover experience finished on a site plan.\r\n */\r\nconst handleHoverEnd = ({ deviceType }) => {\r\n // Emit hover duration for the last map hovered over\r\n const hoverDuration = Date.now() - configuration.sitePlanHoveredStartTime;\r\n const sitePlan = Object.assign({}, configuration.hoveredSitePlan);\r\n\r\n // Reset timing\r\n configuration.sitePlanHoveredStartTime = null;\r\n configuration.hoveredSitePlan = null;\r\n\r\n // Dispatch the hover duration event\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapHover', {\r\n detail: {\r\n communityMap: sitePlan,\r\n hoverDuration,\r\n deviceType,\r\n },\r\n }));\r\n};\r\n\r\n/**\r\n * handleFocusedListingOnSitePlan function will add the active class to the site plans\r\n * focused by the user. It could be in interactions like the active carousel nearby listing in mobile, or the\r\n * hovered listing card in the grid view.\r\n * @param {int} communityId is the identifier of the site plans to apply the active class.\r\n * @param {HTML} currentTooltip html representing current tooltip.\r\n * @param {HTML} previousTooltip html representing previous tooltip.\r\n */\r\nconst handleFocusedListingOnSitePlan = ({ communityId, currentTooltip, previousTooltip }) => {\r\n const { isInInteractiveState } = getSitePlan({ communityId });\r\n\r\n if (isInInteractiveState) {\r\n return;\r\n }\r\n\r\n removeActiveSitePlans();\r\n\r\n const newActiveSitePlan = document.querySelector(`[data-community-map-wrapper-id=\"${communityId}\"]`);\r\n newActiveSitePlan?.classList.add('site-plan_image-active');\r\n\r\n if (currentTooltip) {\r\n currentTooltip.removeAttribute('hidden');\r\n }\r\n\r\n if (previousTooltip) {\r\n previousTooltip.setAttribute('hidden', '');\r\n }\r\n}\r\n \r\n/**\r\n * The `onHoveredCard$` observable emits a value when a hovered card in the grid view corresponds \r\n * to a community that has a representation on the map with a site plan. \r\n * \r\n * This observable is useful for displaying the hover state on the map when the user hovers \r\n * over its associated card.\r\n */\r\nconst onHoveredCard$ = store$.pipe(\r\n map(selectFocusedListingAndSitePlans),\r\n distinctUntilKeyChanged('focusedListing'),\r\n filter(({ sitePlans }) => sitePlans?.length > 0),\r\n pairwise(),\r\n map(([previousMarkerInfo, currentMarkerInfo]) => {\r\n const previousCommunityId = previousMarkerInfo?.focusedListing?.communityId;\r\n const currentCommunityId = currentMarkerInfo?.focusedListing?.communityId;\r\n\r\n const tooltipInformation = {\r\n previousTooltip: previousCommunityId && document.querySelector(`[data-community-map-tooltip-id=\"${previousCommunityId}\"]`),\r\n currentTooltip: currentCommunityId && document.querySelector(`[data-community-map-tooltip-id=\"${currentCommunityId}\"]`),\r\n communityId: +currentCommunityId,\r\n };\r\n\r\n return tooltipInformation;\r\n }));\r\n\r\n/**\r\n * onNewCommunitySitePlans$ observable emits a value indicating new site plans added in the store.\r\n */\r\nconst onNewCommunitySitePlans$ = store$.pipe(\r\n map(selectMarkersAndSitePlans),\r\n distinctUntilKeyChanged('sitePlans'),\r\n pairwise(),\r\n map(([previousState, currentState]) => {\r\n const newSitePlan = currentState.sitePlans.find(\r\n (sitePlan) => \r\n !previousState.sitePlans.some((previousMap) =>\r\n previousMap.communityId === sitePlan.communityId && previousMap.url === sitePlan.url)\r\n );\r\n \r\n return {\r\n marker: newSitePlan && findMarker(currentState.markers, newSitePlan.communityId),\r\n sitePlan: newSitePlan,\r\n };\r\n }),\r\n filter(({ sitePlan }) => !!sitePlan));\r\n\r\n/**\r\n * onZoomChanged$ observable will emit a value every time the zoom changes and there are community\r\n * maps rendered in the Search Results Map.\r\n */\r\nconst onZoomChanged$ = store$.pipe(\r\n map(selectSitePlansProperties),\r\n distinctUntilKeyChanged('zoomLevel'),\r\n filter(({ sitePlans }) => sitePlans.length > 0),\r\n filter(({ zoomLevel }) => zoomLevel >= zoomLevelTriggers.zoomLevelDrawSitePlansTrigger),\r\n pairwise(),\r\n map(([previousState, currentState]) => {\r\n const zoomGesture = previousState.zoomLevel > currentState.zoomLevel ? \"zoomOut\" : \"zoomIn\";\r\n\r\n return {\r\n zoomGesture,\r\n zoomLevel: currentState.zoomLevel,\r\n sitePlans: Array.from(\r\n new Map(\r\n currentState.sitePlans.map((sitePlan) => [sitePlan.communityId, sitePlan])\r\n ).values()\r\n ),\r\n }\r\n })\r\n)\r\n\r\n/**\r\n * subscribing to the store. By mapping markers and site plans, we are able to toggle markers and community\r\n * maps visibility depending on the current map zoom level.\r\n */\r\nstore$.pipe(\r\n map(selectMarkersAndSitePlans),\r\n distinctUntilKeyChanged('sitePlans'),\r\n pairwise(),\r\n map(([previousState, currentState]) => ({\r\n removedSitePlans: previousState.sitePlans.filter(previous =>\r\n !currentState.sitePlans.includes(previous)),\r\n addedSitePlans: currentState.sitePlans,\r\n markers: currentState.markers,\r\n })),\r\n tap(({ removedSitePlans, markers }) => {\r\n showSitePlanMarkers(removedSitePlans, markers);\r\n }),\r\n tap(({ addedSitePlans, markers }) => {\r\n hideSitePlanMarkers(addedSitePlans, markers);\r\n })).subscribe();\r\n\r\n/**\r\n * This observable will calculate how many lasted the hovered gesture from an user in a site plan.\r\n * It will emit both the site plan hovered, and the duration of that hovering.\r\n */\r\nfromEvent(document.body, 'communityMapMouseOver').pipe(\r\n map(event => ({\r\n isMouseMovingOnMap: event.detail.isMouseMovingOnMap,\r\n sitePlan: event.detail.communityMap,\r\n deviceType: event.detail.deviceType,\r\n })),\r\n tap(handleHoverStartOrSwitch),\r\n filter(({ isMouseMovingOnMap }) => !isMouseMovingOnMap),\r\n filter(() => configuration.sitePlanHoveredStartTime !== null),\r\n tap(handleHoverEnd)\r\n ).subscribe();\r\n\r\nonHoveredCard$.subscribe(handleFocusedListingOnSitePlan);\r\nondrawSitePlans$.subscribe(dispatchSitePlans);\r\nonRemoveSitePlans$.subscribe(removeSitePlans);\r\nfetchResults$.subscribe(handleSitePlansInformation);\r\nonRemoveNonNeededSitePlans$.subscribe(removeSpecificSitePlans);\r\nonMapCoordinatesChanged$.subscribe(removeSitePlansNotInViewPort$);\r\nonNewCommunitySitePlans$.subscribe(drawSitePlans);\r\nonZoomChanged$.subscribe(dispatchZoomChangedInformation);\r\nonZoomChanged$.subscribe(hideSitePlansTooltips);","/**\r\n * Represents a summary card skeleton component.\r\n */\r\nexport default class SummaryCardSkeleton {\r\n /**\r\n * Creates an instance of SummaryCardSkeleton.\r\n */\r\n constructor() {\r\n this.id = 'summaryCardSkeleton';\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","/**\r\n * Represents a community label component.\r\n */\r\nexport default class CommunityLabel {\r\n /**\r\n * Creates an instance of CommunityLabel.\r\n */\r\n constructor() {\r\n this.id = 'summaryCardLabel';\r\n }\r\n\r\n /**\r\n * Sets the information for the label.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.IsFeaturedListing = summaryCard.IsFeaturedListing;\r\n this.CommunityType = summaryCard.CommunityType;\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n getClassVariation() {\r\n const isFeaturedListing = this.IsFeaturedListing;\r\n\r\n if (isFeaturedListing) {\r\n return 'nhs-c-listing-status--spotlight';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Retrieves the text for the community label based on the community type and featured listing status.\r\n * @returns {string} The text for the community label.\r\n */\r\n getText() {\r\n const isFeaturedListing = this.IsFeaturedListing;\r\n\r\n if (isFeaturedListing) {\r\n return 'Spotlight';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n const text = this.getText();\r\n\r\n if (!text) {\r\n return '';\r\n }\r\n\r\n return `${this.getText()}`;\r\n }\r\n}\r\n","/**\r\n * Represents a home label component.\r\n */\r\nexport default class HomeLabel {\r\n /**\r\n * Creates an instance of HomeLabel.\r\n */\r\n constructor() {\r\n this.id = 'summaryCardLabel';\r\n }\r\n\r\n /**\r\n * Sets the information for the label.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.Status = summaryCard.Status;\r\n this.IsFeaturedListing = summaryCard.IsFeaturedListing;\r\n }\r\n\r\n getClassVariation() {\r\n const isFeaturedListing = this.IsFeaturedListing;\r\n\r\n if (isFeaturedListing) {\r\n return 'nhs-c-listing-status--spotlight';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the text for the home label based on the status and featured listing flag.\r\n * @returns {string} The text for the home label.\r\n */\r\n getText() {\r\n const isFeaturedListing = this.IsFeaturedListing;\r\n\r\n if (isFeaturedListing) {\r\n return 'Spotlight';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n const text = this.getText();\r\n\r\n if (!text) {\r\n return '';\r\n }\r\n\r\n return `${this.getText()}`;\r\n }\r\n}\r\n","import { TypeaheadLocationType } from 'features/searchResultsFacets';\r\n\r\n/**\r\n * This function returns true if the product type is homes\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isProductTypeHomes = (state) => state?.searchParameters?.product?.productType === 'homes';\r\n\r\n/**\r\n * If the state has a searchParameters property, and that property has a Location property, and the location type is\r\n * different than rectangular area return true, otherwise false.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isSearchWithinMapDisabled = (state) =>\r\n state?.searchParameters?.location?.locationType !== 'rectangularArea';\r\n\r\n/**\r\n * If the state has a searchParameters property, and that property has a Location property, return\r\n * that property. Otherwise, return undefined.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const locationSearchParameters = (state) => state?.searchParameters?.location;\r\n\r\n/**\r\n * returns true is the current location type is community\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isNotCommunityLocationType = (state) =>\r\n state?.searchParameters?.location?.locationType !== TypeaheadLocationType.Community.toString();\r\n\r\n/**\r\n * If the state has a searchParameters property return that property with informaiton of the facts return it.\r\n * Otherwise, return undefined.\r\n * It refers to the type of facts of the housing unit, for example, price, bedrooms, etc.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const factsSearchParameters = (state) => state?.searchParameters?.facts;\r\n\r\n/**\r\n * If the state has a searchParameters property that has information about the product to display return it.\r\n * Otherwise, return undefined.\r\n * It refers to the type of product to display, for example, homes, communities, custom.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const productSearchParameters = (state) => state?.searchParameters?.product;\r\n\r\n/**\r\n * If the state has a searchParameters property with information of the features return it.\r\n * Otherwise, return undefined.\r\n *\r\n * It Refers to the type of features from the housing development, for example, pool, waterfront, etc.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const featuresSearchParameters = (state) => state?.searchParameters?.features;\r\n","/**\r\n * Constant values to be used in the modules related to rendering community interactive and dinamic site plans.\r\n */\r\n\r\nimport SitePlanLayer from \"../enums/sitePlanLayer\";\r\n\r\n/**\r\n * There are zoom levels that triggers different functionalities in the community site plans. Place them in this\r\n * structure so we have them in a single source of truth.\r\n */\r\nexport const zoomLevelTriggers = {\r\n zoomLevelEnterInteractiveStateTrigger: 17,\r\n drawInteractiveSitePlanMarkers: 18,\r\n zoomLevelSitePlansFetchTrigger: 11,\r\n zoomLevelDrawSitePlansTrigger: 14,\r\n}\r\n\r\n/**\r\n * This look up structure is meant for community interactive maps. They represent which layers to show based\r\n * on the map zoom level. The key of the structure is an integer representing map zoom levels, the value are\r\n * the layers to show on each of those levels.\r\n * Progressive disclosure, where the approach is to dynamically enrich or simplify map details as users zoom\r\n * in or out, is supported by the layers and zoom levels of this look up.\r\n */\r\nexport const zoomLevelLayersLookup = new Map([\r\n [ 17, [ SitePlanLayer.StreetNames ]],\r\n [ 16, [ SitePlanLayer.Walkway ]],\r\n [ 15, [ SitePlanLayer.Water, SitePlanLayer.Golf ]],\r\n [ 14, [ SitePlanLayer.Grass, SitePlanLayer.Ground, SitePlanLayer.Street ]],\r\n [ 0, [ SitePlanLayer.Lots, SitePlanLayer.LotPolygons ]],\r\n]);","import { priceReducedIconSvg, callForPriceCommunityIconSvg, callForPriceHomeIconSvg } from 'constants/svg-assets';\r\nimport {\r\n callForPriceCommunityActiveIconSvg,\r\n callForPriceHomeActiveIconSvg,\r\n markerArrowHoverIconSvg,\r\n markerArrowIconSvg,\r\n ratingStartIconSvg,\r\n} from 'constants/svg-assets.b1';\r\n\r\nconst parser = new DOMParser();\r\n\r\nexport const priceReducedSvgElement = parser.parseFromString(priceReducedIconSvg, 'image/svg+xml').documentElement;\r\n\r\n/* Returns the SVG element to use as an icon for call for price in a community. */\r\nexport const callForPriceCommunitySvgElement = parser.parseFromString(\r\n callForPriceCommunityIconSvg,\r\n 'image/svg+xml'\r\n).documentElement;\r\n\r\nexport const callForPriceCommunityActiveSvgElement = parser.parseFromString(\r\n callForPriceCommunityActiveIconSvg,\r\n 'image/svg+xml'\r\n).documentElement;\r\n\r\n/* Returns the SVG element to use as an icon for call for price in a home. */\r\nexport const callForPriceHomeSvgElement = parser.parseFromString(\r\n callForPriceHomeIconSvg,\r\n 'image/svg+xml'\r\n).documentElement;\r\n\r\nexport const callForPriceHomeActiveSvgElement = parser.parseFromString(\r\n callForPriceHomeActiveIconSvg,\r\n 'image/svg+xml'\r\n).documentElement;\r\n\r\nexport const ratingStarSvgElement = parser.parseFromString(ratingStartIconSvg, 'image/svg+xml').documentElement;\r\n\r\nexport const markerArrowSvgElement = parser.parseFromString(markerArrowIconSvg, 'image/svg+xml').documentElement;\r\n\r\nexport const markerArrowHoverSvgElement = parser.parseFromString(\r\n markerArrowHoverIconSvg,\r\n 'image/svg+xml'\r\n).documentElement;\r\n","/**\r\n * Represents the possible lot polygons to support on top of Community Interactive Site Plans.\r\n */\r\nexport default class LotPolygonType {\r\n\r\n /**\r\n * Selected option for lots that received a click/tap.\r\n */\r\n static get Selected() { \r\n return this.getInstance('selected');\r\n }\r\n\r\n /**\r\n * Active option for lots that represents an area where there are plans or specs\r\n * matching the user search criteria.\r\n */\r\n static get Active() {\r\n return this.getInstance('active');\r\n }\r\n\r\n /**\r\n * Hovered option for lots that needs to be highlighted based on hover interaction.\r\n */\r\n static get Hovered() {\r\n return this.getInstance('hovered');\r\n }\r\n\r\n /**\r\n * Inactive option for those lots that don't have any plan or spec matching the user\r\n * search criteria. Inactive lots should have the base map color.\r\n */\r\n static get Inactive() {\r\n return this.getInstance('inactive');\r\n }\r\n\r\n static fromKey(key) {\r\n const map = {\r\n active: LotPolygonType.Active,\r\n default: LotPolygonType.Selected,\r\n hovered: LotPolygonType.Hovered,\r\n empty: LotPolygonType.Inactive,\r\n };\r\n return map[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new LotPolygonType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(LotPolygonType, 'instances', { value: {} });\r\n","/**\r\n * Represents the possible statuses for an Interactive Site Plan lot.\r\n */\r\nexport default class LotStatus {\r\n /**\r\n * Sold lot status\r\n */\r\n static get Sold() {\r\n const configuration = {\r\n name: 'Sold',\r\n id: 'Sold',\r\n };\r\n return this.getInstance('Sold', configuration);\r\n }\r\n \r\n static get QuickMoveIn() {\r\n const configuration = {\r\n name: 'Quick Move In',\r\n id: 'QuickMoveIn',\r\n };\r\n return this.getInstance('QuickMoveIn', configuration);\r\n }\r\n\r\n static get Inventory() {\r\n const configuration = {\r\n name: 'Inventory',\r\n id: 'Inventory',\r\n };\r\n return this.getInstance('Inventory', configuration);\r\n }\r\n\r\n static get Unreleased() {\r\n const configuration = {\r\n name: 'Unreleased',\r\n id: 'Unreleased',\r\n };\r\n return this.getInstance('Unreleased', configuration);\r\n }\r\n\r\n static fromKey(key) {\r\n const map = {\r\n Sold: LotStatus.Sold,\r\n QuickMoveIn: LotStatus.QuickMoveIn,\r\n Inventory: LotStatus.Inventory,\r\n Unreleased: LotStatus.Unreleased,\r\n };\r\n\r\n return map[key];\r\n }\r\n\r\n static getInstance(key, configuration) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new LotStatus(configuration);\r\n }\r\n\r\n return this.instances[key];\r\n }\r\n \r\n constructor(configuration) {\r\n this.name = configuration.name;\r\n this.id = configuration.id;\r\n }\r\n \r\n toString() {\r\n return `${this.name}`;\r\n }\r\n }\r\n \r\n Object.defineProperty(LotStatus, 'instances', { value: {} });\r\n ","/**\r\n * Represents the possible markers located on the map to show.\r\n */\r\nexport default class MarkerType {\r\n \r\n /**\r\n * It represents the Buildable Plan Pin on the map.\r\n */\r\n static get BuildablePlan() {\r\n return this.getInstance('buildeablePlan');\r\n }\r\n\r\n /**\r\n * It represents the Housing Development Pins, also called as Community Pins.\r\n */\r\n static get HousingDevelopment() {\r\n return this.getInstance('community');\r\n }\r\n\r\n /**\r\n * It represents the Plan Unit Pins.\r\n */\r\n static get PlanUnit() {\r\n return this.getInstance('plan');\r\n }\r\n\r\n /**\r\n * It represents the Spec Unit Pins.\r\n */\r\n static get SpecUnit() {\r\n return this.getInstance('spec');\r\n }\r\n\r\n static fromKey(key) {\r\n const map = {\r\n buildeablePlan: MarkerType.BuildablePlan,\r\n community: MarkerType.HousingDevelopment,\r\n plan: MarkerType.PlanUnit,\r\n spec: MarkerType.SpecUnit\r\n };\r\n return map[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new MarkerType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(MarkerType, 'instances', { value: {} });\r\n","/**\r\n * Represents the possible site plan layers to support on top of Community Interactive Site Plans.\r\n */\r\nexport default class SitePlanLayer {\r\n static get LotNumbers() {\r\n const configuration = {\r\n name: 'LotNumbers',\r\n id: 'lot_numbers',\r\n };\r\n return this.getInstance('LotNumbers', configuration);\r\n }\r\n \r\n static get StreetNames() {\r\n const configuration = {\r\n name: 'StreetNames',\r\n id: 'street_names',\r\n };\r\n return this.getInstance('StreetNames', configuration);\r\n }\r\n \r\n static get Walkway() {\r\n const configuration = {\r\n name: 'Walkway',\r\n id: 'walkway',\r\n };\r\n return this.getInstance('Walkway', configuration);\r\n }\r\n \r\n static get Grass() {\r\n const configuration = {\r\n name: 'Grass',\r\n id: 'grass',\r\n };\r\n return this.getInstance('Grass', configuration);\r\n }\r\n\r\n static get Ground() {\r\n const configuration = {\r\n name: 'Ground',\r\n id: 'ground',\r\n };\r\n return this.getInstance('Ground', configuration);\r\n }\r\n\r\n static get LotPolygons() {\r\n const configuration = {\r\n name: 'LotPolygons',\r\n id: 'lot_polygons',\r\n };\r\n return this.getInstance('LotPolygons', configuration);\r\n }\r\n\r\n static get Street() {\r\n const configuration = {\r\n name: 'Street',\r\n id: 'street',\r\n };\r\n return this.getInstance('Street', configuration);\r\n }\r\n\r\n static get Lots() {\r\n const configuration = {\r\n name: 'MainLots',\r\n id: 'lots',\r\n };\r\n return this.getInstance('MainLots', configuration);\r\n }\r\n\r\n static get Water() {\r\n const configuration = {\r\n name: 'Water',\r\n id: 'water',\r\n };\r\n return this.getInstance('Water', configuration);\r\n }\r\n\r\n static get Golf() {\r\n const configuration = {\r\n name: 'Golf',\r\n id: 'golf',\r\n };\r\n return this.getInstance('Golf', configuration);\r\n }\r\n \r\n static fromKey(key) {\r\n const map = {\r\n LotNumbers: SitePlanLayer.LotNumbers,\r\n StreetNames: SitePlanLayer.StreetNames,\r\n Walkway: SitePlanLayer.Walkway,\r\n Grass: SitePlanLayer.Grass,\r\n Ground: SitePlanLayer.Ground,\r\n LotPolygons: SitePlanLayer.LotPolygons,\r\n Street: SitePlanLayer.Street,\r\n MainLots: SitePlanLayer.Lots,\r\n Water: SitePlanLayer.Water,\r\n Golf: SitePlanLayer.Golf,\r\n };\r\n \r\n return map[key];\r\n }\r\n \r\n static getInstance(key, configuration) {\r\n configuration.name = key;\r\n \r\n if (!this.instances[key]) {\r\n this.instances[key] = new SitePlanLayer(configuration);\r\n }\r\n return this.instances[key];\r\n }\r\n \r\n constructor(configuration) {\r\n this.name = configuration.name;\r\n this.id = configuration.id;\r\n }\r\n \r\n toString() {\r\n return `${this.name}`;\r\n }\r\n }\r\n \r\n Object.defineProperty(SitePlanLayer, 'instances', { value: {} });\r\n ","/*\r\n * getMapPoints module is in charge of returning a fromFetch observable to the calling control.\r\n * This observable represents a promise build around fetch javascript API. The result\r\n * of this promise holds an array of markers to paint in the map, so by returning the control\r\n * to the calling module, we will achieve to see those retrieved markers on screen as a\r\n * result of the observable promise returned.\r\n */\r\n\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { mapGetCommunitiesPoints, mapGetHomesPoints } from 'constants/routes';\r\n\r\nexport const getCommunityMapPoints$ = function (payload) {\r\n const requestObject = {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n selector: (response) => response.json(),\r\n };\r\n\r\n return fromFetch(mapGetCommunitiesPoints, requestObject);\r\n};\r\n\r\nexport const getHomeMapPoints$ = function (payload) {\r\n const requestObject = {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...payload,\r\n },\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n selector: (response) => response.json(),\r\n };\r\n\r\n return fromFetch(mapGetHomesPoints, requestObject);\r\n};\r\n","import { of } from 'rxjs';\r\nimport { MoveInDate, PlanStatus, ProductType, ResultType, SpecStatus } from 'features/searchResultsFacets';\r\nimport { getCommunityMapPoints$, getHomeMapPoints$ } from '../apis/getMarkers';\r\n\r\nconst hasAvailableNow = (homeStatus) => {\r\n const statusArray = homeStatus?.split?.(',');\r\n\r\n return statusArray?.some(\r\n (key) => PlanStatus.fromKey(key) === PlanStatus.AvailableNow || SpecStatus.fromKey(key) === SpecStatus.AvailableNow\r\n );\r\n};\r\n\r\nconst getDefaultEndpoints = (parameters) => ({\r\n communities: getCommunityMapPoints$(parameters),\r\n homes: getHomeMapPoints$(parameters),\r\n});\r\n\r\n/*\r\n* getEndpointsByFacts\r\n* validates conditions in the \"facts\" leaf that will provoke to output an empty array of markers\r\n* in either communities or homes marker endpoint.\r\n*/\r\nconst getEndpointsByFacts = (facts) => {\r\n // Avoid returning buildable plan when whe have move in date and home status active\r\n if (\r\n facts.moveInDateRange === MoveInDate.OneToTwoMonths.toString() ||\r\n facts.moveInDateRange === MoveInDate.ThreeToSixMonths.toString()\r\n ) {\r\n return { communities: of([]) };\r\n }\r\n\r\n if (hasAvailableNow(facts.homeStatus)) {\r\n return { communities: of([]) };\r\n }\r\n\r\n return {};\r\n};\r\n\r\n/*\r\n* getEndpointsByProduct\r\n* validates conditions in the \"product\" leaf that will provoke to output an empty array of markers\r\n* in either communities or homes marker endpoint.\r\n*/\r\nconst getEndpointsByProduct = (product) => {\r\n const endpoints = {};\r\n if (product.productType !== ProductType.Homes.toString()) {\r\n endpoints.homes = of([]);\r\n }\r\n\r\n if (\r\n product.productType === ProductType.Custom.toString() ||\r\n product.productType === ProductType.BuildOnYourLot.toString()\r\n ) {\r\n endpoints.communities = of([]);\r\n }\r\n\r\n return endpoints;\r\n};\r\n\r\n/*\r\n* getEndpointsByResult\r\n* validates conditions in the \"results\" leaf that will provoke to output an empty array of markers\r\n* in either communities or homes marker endpoint.\r\n*/\r\nconst getEndpointsByResult = (result) => {\r\n const endpoints = {};\r\n if (result.resultType === ResultType.Builders.toString()) {\r\n endpoints.homes = of([]);\r\n endpoints.communities = of([]);\r\n }\r\n\r\n return endpoints;\r\n};\r\n\r\nexport default (parameters) => {\r\n const defaultEndpoints = getDefaultEndpoints(parameters);\r\n const endpointsByFacts = getEndpointsByFacts(parameters.facts);\r\n const endpointsByProduct = getEndpointsByProduct(parameters.product);\r\n const endpointsByResult = getEndpointsByResult(parameters.results);\r\n\r\n // Hack caused by inconsistent values for MoveInDate for communities\r\n if (\r\n parameters.product.productType !== ProductType.Homes.toString() &&\r\n parameters.product.productType !== ProductType.Custom.toString() &&\r\n parameters.product.productType !== ProductType.BuildOnYourLot.toString()\r\n ) {\r\n endpointsByProduct.communities = defaultEndpoints.communities;\r\n }\r\n\r\n return Object.assign({}, defaultEndpoints, endpointsByFacts, endpointsByProduct, endpointsByResult);\r\n};\r\n","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getCommunityNearbyListingsInfo } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves additional information for a community summary card.\r\n * @param {Object} payload - The payload containing the community id.\r\n * @returns {Observable} - An observable that emits the additional marker information.\r\n */\r\nfunction getCommunityNearbyListings(payload) {\r\n const url = `${getCommunityNearbyListingsInfo}?ids=${payload.communityIds}`;\r\n\r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'image/webp',\r\n }\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n}\r\n\r\nexport default getCommunityNearbyListings;","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getBuildablePlanNearbylistingsInfo } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves additional information for a buildable plan nearby listings carousel.\r\n * @param {Object} payload - The payload containing the community id.\r\n * @returns {Observable} - An observable that emits the additional marker information.\r\n */\r\nfunction getBuildablePlanNearbyListings(payload) {\r\n const {id, showPlanCards} = payload;\r\n const url = `${getBuildablePlanNearbylistingsInfo}?id=${id}`;\r\n\r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'image/webp',\r\n }\r\n }).pipe(\r\n switchMap(async (response) => {\r\n const data = await response.json();\r\n const { community, plans } = data;\r\n\r\n // get a combined list with the community being the first item\r\n // then a list of the community plans if showPlanCards is true.\r\n // if showPlanCards is false, just return the community.\r\n // this is avoid displaying multiple cards on desktop devices.\r\n return showPlanCards ? [...community, ...plans] : [...community];\r\n \r\n })\r\n );\r\n}\r\n\r\nexport default getBuildablePlanNearbyListings;","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getPlanNearbyListingsInfo } from 'constants/routes'\r\nimport { combineAndSortListings } from '../services/processSummaryCard';\r\n\r\n/**\r\n * Retrieves additional information for a plan nearby listings carousel.\r\n * @param {Object} payload - The payload containing the plan Id.\r\n * @param {string} payload.id - The ID of the marker.\r\n * @returns {Observable} - An observable that emits the additional marker information.\r\n */\r\nfunction getPlanNearbyListings(payload) {\r\n const url = `${getPlanNearbyListingsInfo}?plans=${payload.planIds}&specs=${payload.specIds}`;\r\n\r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'image/webp',\r\n }\r\n }).pipe(\r\n switchMap(async (response) => {\r\n const data = await response.json();\r\n const sortedListings = combineAndSortListings(data, payload.sortOrder);\r\n\r\n return sortedListings;\r\n \r\n })\r\n );\r\n}\r\n\r\nexport default getPlanNearbyListings;","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getSpecNearbyListingsInfo } from 'constants/routes'\r\nimport { combineAndSortListings } from '../services/processSummaryCard';\r\n\r\n/**\r\n * Retrieves additional marker information for a Spec nearby listings carousel.\r\n *\r\n * @param {Object} payload - The payload containing the spec Id.\r\n * @param {string} payload.id - The ID of the marker.\r\n * @returns {Observable} - An observable that emits the additional marker information.\r\n */\r\nfunction getSpecNearbyListings(payload) {\r\n const url = `${getSpecNearbyListingsInfo}?specs=${payload.specIds}&plans=${payload.planIds}`;\r\n\r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'image/webp',\r\n }\r\n }).pipe(\r\n switchMap(async (response) => {\r\n const data = await response.json();\r\n const sortedListings = combineAndSortListings(data, payload.sortOrder);\r\n\r\n return sortedListings;\r\n \r\n })\r\n );\r\n}\r\n\r\nexport default getSpecNearbyListings;","/**\r\n * Converts an angle in degrees to the equivalent angle in radians.\r\n *\r\n * @param {number} deg - The angle in degrees.\r\n * @returns {number} The angle in radians.\r\n */\r\nexport default function convertDegreesToRadians(deg) {\r\n return deg * (Math.PI / 180);\r\n}","import convertDegreesToRadians from \"./degressToradians\";\r\n\r\n/**\r\n * Calculates the distance in miles between two geographic coordinates.\r\n *\r\n * @param {number} originLatitude - The latitude of the first coordinate in degrees.\r\n * @param {number} originLongitude - The longitude of the first coordinate in degrees.\r\n * @param {number} targetLatitude - The latitude of the second coordinate in degrees.\r\n * @param {number} targetLongitude - The longitude of the second coordinate in degrees.\r\n * @returns {number} The distance in miles between the two coordinates.\r\n */\r\nexport default function getDistanceBetweenCoordinates(\r\n originLatitude, \r\n originLongitude, \r\n targetLatitude, \r\n targetLongitude\r\n ) {\r\n const earthRadius = 3959; // Radius of the earth in miles\r\n const deltaLatitude = convertDegreesToRadians(targetLatitude - originLatitude);\r\n const deltaLongitude = convertDegreesToRadians(targetLongitude - originLongitude);\r\n\r\n /**\r\n * Calculates an intermediate value used in the distance calculation between two geographic coordinates.\r\n *\r\n */\r\n const haversineFormula = \r\n Math.sin(deltaLatitude / 2) * Math.sin(deltaLatitude / 2) +\r\n Math.cos(convertDegreesToRadians(originLatitude)) * Math.cos(convertDegreesToRadians(targetLatitude)) *\r\n Math.sin(deltaLongitude / 2) * Math.sin(deltaLongitude / 2);\r\n const centralAngle = 2 * Math.atan2(Math.sqrt(haversineFormula), Math.sqrt(1 - haversineFormula));\r\n const distance = earthRadius * centralAngle; // Distance in miles\r\n return distance;\r\n}","import getDistanceBetweenCoordinates from \"utils/getDistanceBetweenCoordinates\";\r\nimport parsePrice from \"utils/parsePriceString\";\r\n\r\n/**\r\n * Sorts an array of markers by distance from a target marker, and then by price.\r\n * \r\n * @param {Object} a - The first marker object to compare.\r\n * @param {Object} b - The second marker object to compare.\r\n * @returns {number} A negative value if a should come before b,\r\n * a positive value if a should come after b, or zero if they are equal.\r\n */\r\nconst sortByDistanceAndPrice = (a, b) => {\r\n if (a.distance === b.distance) {\r\n return a.price - b.price;\r\n }\r\n return a.distance - b.distance;\r\n};\r\n\r\n/**\r\n * Finds the nearby pins within a specified maximum distance from a target pin.\r\n *\r\n * @param {Marker} targetPin - The target pin to find nearby pins from.\r\n * @param {Array} markers - The array of marker objects to search.\r\n * @param {number} radiusInMiles - The maximum distance in miles to include pins.\r\n * @param {Object} coordinates - The bounding coordinates to filter pins.\r\n * @param {number} pagination - The number of pins to return.\r\n * @returns {Array} The array of nearby pins sorted by distance from the target pin.\r\n */\r\nexport default function findNearbyPins(targetPin, markers, coordinates, pagination) {\r\n\r\n // Ensure the targetPin is the first element\r\n const targetPinWithDistance = {\r\n ...targetPin,\r\n distance: 0 // Distance to itself is 0\r\n };\r\n\r\n if (pagination === 1) {\r\n return [targetPinWithDistance];\r\n }\r\n\r\n // Filter out the targetPin from the markers array\r\n const filteredMarkers = markers.filter(pin => pin.id !== targetPin.id);\r\n const { east, north, south, west } = coordinates;\r\n\r\n // Filter markers within the specified coordinates\r\n const markersWithinCoordinates = filteredMarkers.filter(pin => \r\n parseFloat(pin.latitude) <= north &&\r\n parseFloat(pin.latitude) >= south &&\r\n parseFloat(pin.longitude) <= east &&\r\n parseFloat(pin.longitude) >= west\r\n );\r\n\r\n // Calculate distances between itself and the target pin for all markers within coordinates\r\n const nearbyMarkers = markersWithinCoordinates.map(pin => ({\r\n ...pin,\r\n distance: getDistanceBetweenCoordinates(\r\n parseFloat(targetPin.markerPosition.lat),\r\n parseFloat(targetPin.markerPosition.lng),\r\n parseFloat(pin.latitude),\r\n parseFloat(pin.longitude)\r\n ),\r\n price: parsePrice(pin.price) // Convert priceLow to a number\r\n }));\r\n\r\n // Separate markers into basic and paid groups\r\n const basicMarkers = nearbyMarkers.filter(pin => pin.isBasic);\r\n const paidMarkers = nearbyMarkers.filter(pin => !pin.isBasic);\r\n\r\n const sortedBasicMarkers = basicMarkers.sort(sortByDistanceAndPrice);\r\n const sortedPaidMarkers = paidMarkers.sort(sortByDistanceAndPrice);\r\n\r\n // Combine the sorted groups\r\n const sortedMarkers = [...sortedPaidMarkers, ...sortedBasicMarkers];\r\n\r\n return [targetPinWithDistance, ...sortedMarkers].slice(0, pagination);\r\n}","/**\r\n * Parses a price string and returns the numeric value.\r\n *\r\n * @param {string} priceStr - The price string to parse.\r\n * @returns {number} The numeric value of the price.\r\n */\r\n\r\nexport default function parsePrice(priceStr) {\r\n // Remove currency symbol and commas, then parse as a number\r\n const price = parseFloat(priceStr?.replace(/[$,]/g, ''));\r\n return price;\r\n};","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getHousingUnitSummaryCard } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves an interactive site plan housing unit summary card..\r\n * @param {int} specId - The payload containing the spec id.\r\n * @returns {Observable} - An observable that emits the spec summary card information.\r\n */\r\nconst getHousingUnitSummaryCardInformation = (specId) => {\r\n const url = `${getHousingUnitSummaryCard}?id=${specId}`;\r\n \r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n};\r\n\r\nexport default getHousingUnitSummaryCardInformation;","import { catchError, forkJoin, of, switchMap, tap, filter, map, distinctUntilChanged } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport messageService from 'layout/services/messageService';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { ResultType, searchParametersActions, selectResultType } from 'features/searchResultsFacets';\r\nimport { selectIsMarkerAutoScrollFeatureEnabled, selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport getMarkersLoaderEndpoints from '../services/markersEndpointSelector';\r\nimport { mapStateSlice, interactiveSitePlanSlice } from './slices';\r\nimport { \r\n geoCoordinates,\r\n mapMarkers,\r\n selectedLotSummaryCard,\r\n selectedNearbyListingCarousel,\r\n selectedNearbyListingsCarouselStatus,\r\n} from './selectors';\r\nimport getCommunityNearbyListings from '../apis/getCommunityNearbyListings';\r\nimport getBuildablePlanNearbyListings from '../apis/getBuildablePlanNearbyListings';\r\nimport getPlanNearbyListings from '../apis/getPlanNearbyListings';\r\nimport getSpecNearbyListings from '../apis/getSpecNearbyListings';\r\nimport findNearbyPins from '../services/geoLocationService';\r\nimport MarkerType from '../enums/markerType';\r\nimport getHousingUnitSummaryCardInformation from '../apis/getHousingUnitSummaryCard';\r\nimport getCommunitySummaryCard from '../apis/getCommunitySummaryCard';\r\n\r\nconst actions = {\r\n ...mapStateSlice.actions,\r\n ...uiStateSlice.actions,\r\n ...interactiveSitePlanSlice.actions,\r\n};\r\n\r\nexport default (action$) =>\r\naction$.pipe(\r\n ofType(actions.fetchResults.type),\r\n switchMap((action) => {\r\n const apiRequests = getMarkersLoaderEndpoints(action.payload.parameters);\r\n return forkJoin(apiRequests).pipe(\r\n switchMap((data) => of(actions.fetchResultsFulfilled({ parameters: action.payload.parameters, ...data }))),\r\n tap((data) => {\r\n messageService.sendMessage({\r\n messageType: 'mapBoundaries',\r\n payload: {\r\n mapBoundaries: data.payload.communities?.MapBoundaries || data.payload.homes?.MapBoundaries,\r\n },\r\n });\r\n }),\r\n catchError((err) => of(actions.fetchResultsError(err)))\r\n );\r\n })\r\n);\r\n\r\n/*\r\n * Epic to refresh the page number of each marker when the sort event o pagesize event is raised. \r\n * Is those events ths listing is refreshed, but the marker not.\r\n */\r\nexport const updateMarkersPageNumberEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(\r\n searchParametersActions.fetchSort.type,\r\n searchParametersActions.fetchPageSize.type,\r\n ),\r\n // When the Layout is small the page numbers shouldn't be updated \r\n filter(() => selectLayoutBreakpoint(state$.value).getValue() !== LayoutBreakpoint.Small.getValue()),\r\n switchMap(() => {\r\n const parameters = state$.value.searchParameters;\r\n const apiRequests = getMarkersLoaderEndpoints(parameters);\r\n return forkJoin(apiRequests).pipe(\r\n switchMap((data) => of(actions.fetchResultsPagesNumbers({ parameters, ...data }))),\r\n );\r\n })\r\n );\r\n \r\n/**\r\n * Epic that clears the summary card when the search parameters change, \r\n * the search within map is disabled, or the search within map is enabled.\r\n * @param {Observable} action$ - Observable stream of actions.\r\n * @returns {Observable} - Observable stream of actions.\r\n */\r\nexport const clearNearbyListingsCarouselOnMapChangesEpic = (action$) =>\r\n action$.pipe(\r\n ofType(\r\n actions.disableSearchWithinMap.type,\r\n actions.enableSearchWithinMap.type\r\n ),\r\n map(selectedNearbyListingCarousel),\r\n filter((carousel) => Boolean(carousel?.Id)),\r\n switchMap(() => of(actions.clearNearbyListingsCarousel()))\r\n );\r\n\r\n /**\r\n * Epic for retrieving additional information for a community marker.\r\n * @param {Observable} action$ - Observable stream of actions.\r\n * @returns {Observable} - Observable stream of actions.\r\n */\r\nexport const getCommunityNearbyListingsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.selectedMarker.type),\r\n filter(() => {\r\n const IsMarkerAutoScrollFeatureEnabled = selectIsMarkerAutoScrollFeatureEnabled(state$.value);\r\n\r\n // if auto scroll feature flag is off, then go ahead and fetch the summary card\r\n if (!IsMarkerAutoScrollFeatureEnabled) {\r\n return true;\r\n }\r\n\r\n // since auto scroll feature flag is on, we have to calculate if we have to show the summary card.\r\n // we fetch the summary card for:\r\n // 1. every community in small size devices either in /communities/ or /homes/\r\n // 2. buildable plans in /homes/.\r\n const layoutBreakpoint = selectLayoutBreakpoint(state$.value);\r\n const resultType = selectResultType(state$.value);\r\n\r\n return resultType === ResultType.Homes.toString() ||\r\n layoutBreakpoint.text === LayoutBreakpoint.Small.toString();\r\n }),\r\n filter((action) => \r\n action.payload?.type?.toLowerCase() === MarkerType.HousingDevelopment.toString()\r\n ),\r\n switchMap((action) => { \r\n // get all the markers from the state, then filter the nearby pins by a 25 mile radius.\r\n const allMarkers = mapMarkers(state$.value).filter((pin) => \r\n pin.type === MarkerType.HousingDevelopment.toString());\r\n const coordinates = geoCoordinates(state$.value);\r\n // Communities is only displayed on smaller devices, so we only want to show 7 results\r\n const pagination = 7; \r\n const nearbyPins = findNearbyPins(action.payload, allMarkers, coordinates, pagination);\r\n\r\n // the backend expects a list of community ids to fetch, so we grab just the IDs\r\n const ids = nearbyPins.map((pin) => pin.id).join(','); \r\n return getCommunityNearbyListings({communityIds: ids}).pipe(\r\n switchMap((data) => of(actions.getNearbyListingsCarouselFulfilled(data))),\r\n catchError((error) => of(actions.getNearbyListingsCarouselFailed(error)))\r\n );\r\n }));\r\n\r\n /**\r\n * Epic for retrieving additional information for a community marker.\r\n * @param {Observable} action$ - Observable stream of actions.\r\n * @returns {Observable} - Observable stream of actions.\r\n */\r\nexport const getBuildablePlanNearbyListingsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.selectedMarker.type),\r\n filter((action) => \r\n action.payload?.type === MarkerType.BuildablePlan.toString()\r\n ),\r\n switchMap((action) => {\r\n const id = action.payload?.id;\r\n const layoutBreakpoint = selectLayoutBreakpoint(state$.value).getValue();\r\n const showPlanCards = layoutBreakpoint === LayoutBreakpoint.Small.getValue();\r\n\r\n return getBuildablePlanNearbyListings({\r\n id,\r\n showPlanCards\r\n }).pipe(\r\n switchMap((data) => of(actions.getNearbyListingsCarouselFulfilled(data))),\r\n catchError((error) => of(actions.getNearbyListingsCarouselFailed(error)))\r\n )\r\n })\r\n );\r\n\r\n/**\r\n * Epic for retrieving additional marker information for a plan marker.\r\n *\r\n * @param {Observable} action$ - The stream of actions.\r\n * @returns {Observable} Observable stream of actions\r\n */\r\nexport const getPlanNearbyListingsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.selectedMarker.type),\r\n filter((action) => action.payload?.type === MarkerType.PlanUnit.toString()),\r\n switchMap((action) => {\r\n // get all the markers from the state, then the north, south, east, and west coordinates\r\n // and finally all the visible markers that belong to either a plan detail or a spec detail.\r\n const allMarkers = mapMarkers(state$.value);\r\n const coordinates = geoCoordinates(state$.value);\r\n const homeMarkers = allMarkers.filter((pin) => pin.type !== MarkerType.BuildablePlan.toString());\r\n\r\n // get the screen size\r\n const layoutBreakpoint = selectLayoutBreakpoint(state$.value).getValue();\r\n\r\n // if larger devices, we will only display 1 card, otherwise we will display 7\r\n const pagination = layoutBreakpoint === LayoutBreakpoint.Small.getValue() ? 7 : 1;\r\n\r\n // get the nearby pins, sorted by distance from the marker.\r\n const nearbyPins = findNearbyPins(action.payload, homeMarkers, coordinates, pagination);\r\n\r\n // the backend expects a list of plan ids to fetch, so we grab just the IDs\r\n const planIds = nearbyPins.filter(pin => \r\n pin.type !== MarkerType.SpecUnit.toString()).map((pin) => pin.id).join(','); \r\n const specIds = nearbyPins.filter(pin => \r\n pin.type === MarkerType.SpecUnit.toString()).map((pin) => pin.id).join(','); \r\n\r\n // we need this for the sort order, since we get plans and specs separately, we need to merge them in the\r\n // previously sorted order.\r\n const sortOrder = nearbyPins.map((pin) => pin.id).join(',');\r\n\r\n return getPlanNearbyListings({\r\n planIds,\r\n specIds,\r\n sortOrder\r\n }).pipe(\r\n switchMap((data) => of(actions.getNearbyListingsCarouselFulfilled(data))),\r\n catchError((error) => of(actions.getNearbyListingsCarouselFailed(error)))\r\n )\r\n })\r\n );\r\n\r\n/**\r\n * Epic for retrieving additional marker information for a spec.\r\n *\r\n * @param {Observable} action$ - The stream of actions.\r\n * @returns {Observable} The stream of actions for retrieving additional marker information.\r\n */\r\nexport const getSpecNearbyListingsEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.selectedMarker.type),\r\n filter((action) => action.payload?.type === MarkerType.SpecUnit.toString()),\r\n switchMap((action) => {\r\n // get all the markers from the state, then the north, south, east, and west coordinates\r\n // and finally all the visible markers that belong to either a plan detail or a spec detail.\r\n const allMarkers = mapMarkers(state$.value);\r\n const coordinates = geoCoordinates(state$.value);\r\n const homeMarkers = allMarkers.filter((pin) => pin.type !== MarkerType.BuildablePlan.toString());\r\n \r\n // get the screen size\r\n const layoutBreakpoint = selectLayoutBreakpoint(state$.value).getValue();\r\n\r\n // if larger devices, we will only display 1 card, otherwise we will display 7\r\n const pagination = layoutBreakpoint === LayoutBreakpoint.Small.getValue() ? 7 : 1;\r\n const nearbyPins = findNearbyPins(action.payload, homeMarkers, coordinates, pagination);\r\n \r\n // the backend expects separate lists of plans and spec details, so we grab just the IDs\r\n const planIds = nearbyPins.filter(pin => \r\n pin.type === MarkerType.PlanUnit.toString()).map((pin) => pin.id).join(','); \r\n const specIds = nearbyPins.filter(pin => \r\n pin.type !== MarkerType.PlanUnit.toString()).map((pin) => pin.id).join(','); \r\n\r\n // we need this for the sort order, since we get plans and specs separately, we need to merge them in the\r\n // previously sorted order.\r\n const sortOrder = nearbyPins.map((pin) => pin.id).join(',');\r\n\r\n return getSpecNearbyListings({\r\n specIds,\r\n planIds,\r\n sortOrder\r\n }).pipe(\r\n switchMap((data) => of(actions.getNearbyListingsCarouselFulfilled(data))),\r\n catchError((error) => of(actions.getNearbyListingsCarouselFailed(error)))\r\n )\r\n })\r\n );\r\n\r\n /**\r\n * Clears the summary card information when a listing is focused.\r\n *\r\n * @param {Observable} action$ - The stream of actions.\r\n * @returns {Observable} The stream of actions to be dispatched.\r\n */\r\n export const clearNearbyListingsCarouselEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.focusedListingInformation.type, searchParametersActions.fetchResultsType.type),\r\n map(selectedNearbyListingsCarouselStatus),\r\n filter((status) => {\r\n const summaryCard = selectedNearbyListingCarousel(state$.value);\r\n\r\n // check that the card exists\r\n return Boolean(summaryCard?.Id) &&\r\n status !== LoadingStatus.Idle.toString()\r\n }),\r\n switchMap(() => of(actions.clearNearbyListingsCarousel()))\r\n )\r\n\r\n /**\r\n * Removes the focused listing information when the carousel of nearby results closes.\r\n * \r\n * @param {Observable} action$ - The stream of actions.\r\n * @returns {Observable} The stream of actions to be dispatched.\r\n */\r\n export const clearFocusedListingOnNearbyCarouselClosedEpic = (action$) =>\r\n action$.pipe(\r\n ofType(\r\n actions.clearNearbyListingsCarousel.type,\r\n ),\r\n switchMap(() => of(actions.focusedListingInformation(null)))\r\n );\r\n\r\n/**\r\n * fetchSummaryCardForInteractiveSitePlanEpic epic is meant to\r\n * retrieve a summary card after an interactive site plan\r\n * lot is selected by the user.\r\n * @returns {Observable} The stream of actions to be dispatched.\r\n */\r\nexport const fetchSummaryCardForInteractiveSitePlanEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.setLotInformation.type),\r\n map((action) => ({\r\n communityId: action.payload?.communityId,\r\n specId: action.payload?.availableSpec,\r\n })),\r\n distinctUntilChanged((previous, current) => {\r\n if (!selectedLotSummaryCard(state$.value)) {\r\n return false;\r\n }\r\n\r\n return previous.communityId === current.communityId &&\r\n previous.specId === current.specId;\r\n }),\r\n filter(({ communityId, specId }) => Boolean(communityId) || Boolean(specId)),\r\n switchMap(({ communityId, specId }) => {\r\n const getSummaryCard$ = specId\r\n ? getHousingUnitSummaryCardInformation(specId)\r\n : getCommunitySummaryCard(communityId);\r\n\r\n return getSummaryCard$.pipe(\r\n switchMap((data) => of(actions.getInteractiveSitePlanCardFulfilled(data))),\r\n catchError((error) => of(actions.getInteractiveSitePlanCardFailed(error)))\r\n );\r\n })\r\n );\r\n\r\n\r\n/**\r\n * removeInteractiveSitePlanEpic will react to community maps removed in order to remove\r\n * the interactive site plan information related to them, if any.\r\n * @param {Observable} action$ - The stream of actions.\r\n * @returns {Observable} The stream of actions to be dispatched.\r\n */\r\nexport const removeInteractiveSitePlanEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.removeCommunityMap.type),\r\n map((action) => actions.removeInteractiveSitePlan(action.payload))\r\n );","import { epic$, store, store$ } from '@redux/store';\r\nimport loadGoogleMaps from 'libraries/mapLibrary';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { locationSearchParameters } from './constants/searchParametersConstants';\r\nimport { zoomLevelLayersLookup, zoomLevelTriggers } from './constants/sitePlansConstants';\r\nimport fetchMapResultsEpic, {\r\n getCommunityNearbyListingsEpic,\r\n getPlanNearbyListingsEpic,\r\n getSpecNearbyListingsEpic,\r\n clearNearbyListingsCarouselEpic,\r\n clearNearbyListingsCarouselOnMapChangesEpic,\r\n getBuildablePlanNearbyListingsEpic,\r\n updateMarkersPageNumberEpic,\r\n fetchSummaryCardForInteractiveSitePlanEpic,\r\n } from './redux/epics';\r\n\r\n import { mapContainerDoubleClicked$, mapContainerClicked$ } from './redux/observables';\r\n\r\nimport { mapStateSlice, interactiveSitePlanSlice } from './redux/slices';\r\nimport {\r\n isSearchWithinMapEnabled,\r\n geoCoordinates,\r\n isMapIdle,\r\n isMapLibraryFetching,\r\n selectSearchMapTrackingCommonProperties,\r\n selectedMarkerAndPage,\r\n isMapLibraryLoaded,\r\n isFetchingResults,\r\n selectMapLibraryStatus,\r\n selectedMarker,\r\n selectedNearbyListingCarousel,\r\n} from './redux/selectors';\r\nimport MarkerType from './enums/markerType';\r\n\r\n\r\nconst { actions, reducer } = mapStateSlice;\r\nconst { reducer: interactiveSitePlanReducer } = interactiveSitePlanSlice\r\n\r\nconst onMapsLibraryLoaded = () => store.dispatch(actions.mapLibraryLoaded());\r\nconst onMapsLibraryErrored = (value) => store.dispatch(actions.mapLibraryErrored(value));\r\n\r\nepic$.next(fetchMapResultsEpic);\r\nepic$.next(getCommunityNearbyListingsEpic);\r\nepic$.next(getPlanNearbyListingsEpic);\r\nepic$.next(getSpecNearbyListingsEpic);\r\nepic$.next(getBuildablePlanNearbyListingsEpic);\r\nepic$.next(clearNearbyListingsCarouselEpic);\r\nepic$.next(updateMarkersPageNumberEpic);\r\nepic$.next(clearNearbyListingsCarouselOnMapChangesEpic);\r\nepic$.next(fetchSummaryCardForInteractiveSitePlanEpic);\r\n\r\nstore.injectReducer('mapState', reducer);\r\nstore.injectReducer('interactiveSitePlanState', interactiveSitePlanReducer)\r\n\r\nstore$\r\n .pipe(map(isMapLibraryFetching), distinctUntilChanged(), filter(Boolean))\r\n .subscribe(() => loadGoogleMaps(onMapsLibraryLoaded, onMapsLibraryErrored));\r\n\r\nexport const createMap = () => store.dispatch(mapStateSlice.actions.mapLibraryFetch());\r\nexport const getGeoCoordinates = () => geoCoordinates(store.getState());\r\nexport {\r\n fetchMapResultsEpic,\r\n actions as mapStateActions,\r\n reducer as mapStateReducers,\r\n locationSearchParameters,\r\n isSearchWithinMapEnabled,\r\n isMapIdle,\r\n geoCoordinates,\r\n selectMapLibraryStatus,\r\n selectSearchMapTrackingCommonProperties,\r\n isMapLibraryLoaded,\r\n isFetchingResults as isMapResultsFetching,\r\n selectedMarker,\r\n selectedNearbyListingCarousel,\r\n MarkerType,\r\n selectedMarkerAndPage,\r\n mapContainerDoubleClicked$,\r\n mapContainerClicked$,\r\n zoomLevelLayersLookup,\r\n zoomLevelTriggers,\r\n};\r\n\r\nrequire('./components/map');\r\nrequire('./components/marker');\r\nrequire('./components/nearbyListingsCarousel');\r\nrequire('./components/sitePlansHandler');\r\nrequire('./components/interactiveSitePlansHandler');\r\nrequire('./analytics/searchWithinMap');\r\nrequire('./components/boundaries');\r\nrequire('./components/markerSessionHandler');\r\nrequire('./components/lotSummaryCard');","/**\r\n * This file will export observables that could be reused among map feature components.\r\n */\r\n\r\nimport { distinctUntilChanged, filter, fromEvent, map } from \"rxjs\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { selectZoomLevel } from \"./selectors\";\r\n\r\nconst mapContainer = document.querySelector('#nhs_map');\r\n\r\nexport const mapContainerDoubleClicked$ = fromEvent(mapContainer, 'dblclick');\r\nexport const mapContainerClicked$ = fromEvent(mapContainer, 'click');\r\nexport const mapClicked$ = fromEvent(mapContainer, 'mapClick');\r\nexport const mapDragStart$ = fromEvent(mapContainer, 'mapDragStart');\r\nexport const mapDragEnd$ = fromEvent(mapContainer, 'mapDragEnd');\r\n\r\n/**\r\n * onZoomChanged$ will emit a stream every time map zoom level changes.\r\n */\r\nexport const onZoomChanged$ = store$.pipe(\r\n map(selectZoomLevel),\r\n distinctUntilChanged(),\r\n filter(Boolean));","import { createSelector } from '@reduxjs/toolkit';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectLocation, selectPage } from 'features/searchResultsFacets';\r\nimport MarkerType from '../enums/markerType';\r\n\r\n/**\r\n * Returns true if search within map flag is on.\r\n * @param state - The state of the redux store\r\n */\r\nexport const selectIsSearchWithinMapReady = (state) => state?.mapState?.isSearchWithinMapReady;\r\n\r\n/**\r\n * Returns the geolocation of the point of interest listing.\r\n * @param state - The state of the redux store\r\n */\r\nexport const selectFocusedGeographicKey = (state) => state?.uiState?.focusedListing?.geographicKey;\r\n\r\n/**\r\n * Returns the Id of the listing being hovered.\r\n * @param state - The state of the redux store\r\n */\r\nexport const selectFocusedListingId = (state) => state?.uiState?.focusedListing?.id;\r\n\r\n/**\r\n * Returns the community Id of the listing being hovered.\r\n * @param state - The state of the redux store\r\n */\r\nexport const selectFocusedCommunityId = (state) => state?.uiState?.focusedListing?.communityId;\r\n\r\n/**\r\n * Returns true if the Geo Coordinates object has been defined.\r\n * @param state - The state of the redux store\r\n */\r\nexport const areMapBoundariesDefined = (state) => !!state?.mapState?.geoCoordinates;\r\n\r\n/**\r\n * If the state has a mapState property, and that property has a HomeResults property, then return true.\r\n * Otherwise, return false\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const areMarkersAvailable = (state) => !!state?.mapState?.results;\r\n\r\n/**\r\n * It returns the Geo Coordinates from the mapState in the Redux store.\r\n * @param state - The state of the redux store\r\n */\r\nexport const geoCoordinates = (state) => state?.mapState?.geoCoordinates;\r\n\r\n/**\r\n * Returns true if the map is not fetching results from the server.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isMapIdle = (state) => !state?.mapState?.isFetchingResults;\r\n\r\n/**\r\n * Returns true if the map is fetching results from the server.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isFetchingResults = (state) => state?.mapState?.isFetchingResults;\r\n\r\n/**\r\n * Returns the map library status.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const selectMapLibraryStatus = (state) => state?.mapState?.mapLibraryStatus;\r\n\r\n/**\r\n * Returns true if the map library is fetching.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isMapLibraryFetching = (state) => state?.mapState?.mapLibraryStatus === LoadingStatus.Loading.toString();\r\n\r\n/**\r\n * Returns true if the map library has been loaded.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isMapLibraryLoaded = (state) => state?.mapState?.mapLibraryStatus === LoadingStatus.Succeeded.toString();\r\n\r\n/**\r\n * If the state has a mapState property,and the property has a isSearchWithinMap property, return that property.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isSearchWithinMapEnabled = (state) => state?.mapState?.isSearchWithinMap;\r\n\r\n/**\r\n * It returns the results from the mapState in the Redux store.\r\n * @param state - The state of the redux store\r\n */\r\nexport const mapMarkers = (state) => state?.mapState?.results;\r\n\r\n/**\r\n * Returns an array representing all of the current plan identifiers.\r\n * @param state - The state of the redux store\r\n */\r\nexport const selectAllPlansIds = (state) => state?.mapState?.allPlanIds;\r\n\r\n/**\r\n * If the user click a marker, it is store in this property.\r\n */\r\nexport const selectedMarker = (state) => state?.mapState?.selectedMarker;\r\n\r\n/**\r\n * the summary card information.\r\n */\r\nexport const selectedNearbyListingCarousel = (state) => state?.mapState?.nearbyListingsCarousel;\r\n\r\n/**\r\n * the summary card status information.\r\n */\r\nexport const selectedNearbyListingsCarouselStatus = (state) => state?.mapState?.nearbyListingsCarouselStatus;\r\n\r\n/**\r\n * the current map zoom level.\r\n */\r\nexport const selectZoomLevel = (state) => state?.mapState?.zoomLevel;\r\n\r\n/**\r\n * selects community site plans information.\r\n */\r\nexport const selectSitePlans = (state) => state?.mapState?.sitePlans;\r\n\r\n/**\r\n * selects interactive site plan information.\r\n */\r\nexport const selectInteractiveSitePlans = (state) => state?.interactiveSitePlanState?.interactiveSitePlans;\r\n\r\n/**\r\n * selects interactive site plan tracking information to understand which one are loaded.\r\n */\r\nexport const selectTrackedInteractiveSitePlans = (state) =>\r\n state?.interactiveSitePlanState?.loadedInteractiveSitePlans;\r\n\r\n/**\r\n * selects the lot number clicked by the user\r\n */\r\nexport const selectLotNumber = (state) => state?.interactiveSitePlanState?.lotNumber;\r\n\r\n/**\r\n * selects the lot identifier\r\n */\r\nexport const selectLotId = (state) => state?.interactiveSitePlanState?.lotId;\r\n\r\n/**\r\n * selects the community id of the current active lot\r\n */\r\nexport const selectLotCommunityId = (state) => state?.interactiveSitePlanState?.communityId;\r\n\r\n/**\r\n * select the available plans that can be built in a selected lot\r\n */\r\nexport const selectAvailablePlans = (state) => state?.interactiveSitePlanState?.availablePlans;\r\n\r\n/**\r\n * select the spec built in a selected lot\r\n */\r\nexport const selectAvailableSpec = (state) => state?.interactiveSitePlanState?.availableSpec;\r\n\r\n/**\r\n * select the active lot status of an interactive site plan\r\n */\r\nexport const selectLotStatus = (state) => state?.interactiveSitePlanState?.lotStatus;\r\n\r\n/**\r\n * selects information about lot summary card.\r\n */\r\nexport const selectedLotSummaryCard = (state) =>\r\n state?.interactiveSitePlanState?.interactiveSitePlanCard;\r\n\r\n/**\r\n * selects information about active lot, specifically: site plan id.\r\n */\r\nexport const selectedLotSitePlanId = (state) =>\r\n state?.interactiveSitePlanState?.sitePlanId;\r\n\r\n/**\r\n * selects the status of the lot listings carousel.\r\n */\r\nexport const selectedLotSummaryCardStatus = (state) =>\r\n state?.interactiveSitePlanState?.interactiveSitePlanCardStatus;\r\n\r\n/**\r\n * Gets the data for the summary card, and the marker that triggered\r\n */\r\nexport const selectNearbyListingsCarouselStatusAndMarkerData = createSelector(\r\n selectedNearbyListingsCarouselStatus,\r\n selectedMarker,\r\n (status, marker) => ({ status, marker })\r\n);\r\n\r\n/**\r\n * Gets data related to lot information.\r\n */\r\nexport const selectLotInformation = createSelector(\r\n selectLotId,\r\n selectLotCommunityId,\r\n selectedLotSummaryCard,\r\n selectedLotSummaryCardStatus,\r\n selectedLotSitePlanId,\r\n (\r\n lotId,\r\n communityId,\r\n summaryCard,\r\n summaryCardStatus,\r\n sitePlanId) => ({\r\n lotId,\r\n communityId,\r\n summaryCard,\r\n summaryCardStatus,\r\n sitePlanId\r\n })\r\n);\r\n\r\n/**\r\n * Gets the community id of the opened lot summary card along with the site plans.\r\n */\r\nexport const selectLotCommunityIdAndSitePlans = createSelector(\r\n selectLotCommunityId,\r\n selectSitePlans,\r\n (\r\n lotCommunityId,\r\n sitePlans) => ({\r\n lotCommunityId,\r\n sitePlans,\r\n })\r\n);\r\n\r\n/**\r\n * If the state has a mapState property, and the property has a hoveredMarker property, return that property.\r\n *\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const selectHoveredMarker = (state) => state?.mapState?.hoveredMarker;\r\n\r\n\r\n/**\r\n * It returns the point of interest hovered by the user\r\n */\r\nexport const selectFocusedListing = createSelector(\r\n selectFocusedListingId,\r\n selectFocusedCommunityId,\r\n selectFocusedGeographicKey,\r\n (id, communityId, geographicKey) => ({\r\n id,\r\n communityId,\r\n geographicKey,\r\n })\r\n);\r\n\r\n/**\r\n * It returns the current map geo coordinates along with the current location.\r\n */\r\nexport const selectGeoCoordinatesAndLocation = createSelector(\r\n geoCoordinates,\r\n selectLocation,\r\n (coordinates, location) => ({\r\n coordinates,\r\n location,\r\n })\r\n);\r\n\r\nexport const selectSearchMapTrackingCommonProperties = createSelector(\r\n isSearchWithinMapEnabled,\r\n (isSearchWithinMap) => ({ isSearchWithinMap })\r\n);\r\n\r\nexport const selectedMarkerAndPage = createSelector(\r\n selectedMarker,\r\n selectPage,\r\n (marker, page) => (\r\n {\r\n marker, \r\n page\r\n }\r\n )\r\n);\r\n\r\n/**\r\n * selector that will retrieve information related with current map zoom level, map geo coordinates,\r\n * search within map status and map markers.\r\n */\r\nexport const selectSitePlansProperties = createSelector(\r\n selectZoomLevel,\r\n geoCoordinates,\r\n isSearchWithinMapEnabled,\r\n mapMarkers,\r\n isFetchingResults,\r\n isMapLibraryLoaded,\r\n selectSitePlans,\r\n (zoomLevel, coordinates, isSearchWithinMap, markers, isFetching, isMapLoaded, sitePlans) => (\r\n {\r\n zoomLevel,\r\n coordinates,\r\n isSearchWithinMap,\r\n markers,\r\n isFetching,\r\n isMapLoaded,\r\n sitePlans,\r\n }\r\n )\r\n);\r\n\r\n/**\r\n * selector that will retrieve information related with map markers and community site plans.\r\n */\r\nexport const selectMarkersAndSitePlans = createSelector(\r\n mapMarkers,\r\n selectSitePlans,\r\n (markers, sitePlans) => (\r\n {\r\n markers,\r\n sitePlans,\r\n }\r\n )\r\n);\r\n\r\n/**\r\n * selector that will retrieve information related with the focused listing card and community site plans.\r\n */\r\nexport const selectFocusedListingAndSitePlans = createSelector(\r\n selectFocusedListing,\r\n selectSitePlans,\r\n (focusedListing, sitePlans) => (\r\n {\r\n focusedListing,\r\n sitePlans,\r\n }\r\n )\r\n);\r\n\r\n/**\r\n * selector that will retrieve all specs and plans represented in the current results page.\r\n */\r\nexport const selectAllPlansAndSpecsIds = createSelector(\r\n mapMarkers,\r\n selectAllPlansIds,\r\n (markers, allPlans) => ({\r\n specs: markers?.filter((marker) => marker.type === MarkerType.SpecUnit.toString()).map((spec) => spec.id) || [],\r\n plans: allPlans || [],\r\n })\r\n);\r\n\r\n","import LoadingStatus from 'enums/loadingStatus';\r\nimport { LocationType } from 'features/searchResultsFacets';\r\n\r\nconst searchCommandElement = document.querySelector(\"[data-component='search-command-data']\");\r\nconst searchCommandData = JSON.parse(searchCommandElement.innerHTML);\r\n\r\nconst isSearchWithinMapOn = () => searchCommandData.Location.LocationType === LocationType.RectangularArea.name;\r\n\r\nexport default {\r\n isSearchWithinMapReady: false,\r\n mapLibraryStatus: LoadingStatus.Idle.toString(),\r\n isSearchWithinMap: isSearchWithinMapOn(),\r\n selectedMarker: null,\r\n sitePlans: [],\r\n};","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport { interactiveSitePlanSvg } from 'constants/svg-assets';\r\nimport { callForPriceCommunitySvgElement, priceReducedSvgElement } from '../constants/svgIcons';\r\nimport MarkerType from '../enums/markerType';\r\nimport { isHousingDevelopmentViewed } from '../services/markerSessionService';\r\nimport {\r\n callForPriceCommunityActiveSvgElement,\r\n markerArrowHoverSvgElement,\r\n markerArrowSvgElement,\r\n} from '../constants/svgIcons.b1';\r\nimport getClassesToApply from '../services/unitMarkerService';\r\n\r\n/* Creates a new instance of a housing development that will be plotted in the map as a marker.\r\n */\r\nexport default class HousingDevelopmentMarker {\r\n constructor(housingInformation) {\r\n this.geoId = housingInformation.GeoId;\r\n this.detailText = housingInformation.DetailText;\r\n this.type = MarkerType.HousingDevelopment.toString();\r\n this.id = housingInformation.Id;\r\n this.communityId = housingInformation.Id;\r\n this.isBasic = housingInformation.IsBasic;\r\n this.latitude = housingInformation.Latitude;\r\n this.longitude = housingInformation.Longitude;\r\n // TODO: NewHomeSource Rebrand\r\n // Change the class on the backend.\r\n this.priceText = housingInformation.PriceText.replace('small--text', 'nhs-c-tooltip__price-label--small');\r\n this.shortPrice = housingInformation.ShortPrice;\r\n this.title = housingInformation.Title;\r\n this.totalPlans = housingInformation.TotalPlans;\r\n this.priceReducedText = housingInformation.PriceReducedText;\r\n this.isPriceReduction = !!housingInformation.PriceReducedText;\r\n this.priceReducedTrackingLabel = housingInformation.PriceReducedTrackingLabel;\r\n this.communityName = housingInformation.Title;\r\n this.builderId = housingInformation.BuilderId;\r\n this.isFeaturedListing = housingInformation.IsFeaturedListing;\r\n this.isCallForPrice = housingInformation.IsCallForPrice;\r\n this.isViewed = isHousingDevelopmentViewed(housingInformation.Id);\r\n this.pageNumber = housingInformation.Page;\r\n this.priceLow = housingInformation.PriceLow;\r\n this.priceHigh = housingInformation.PriceHigh;\r\n this.hasInteractiveSitePlan = housingInformation.HasInteractiveSitePlan;\r\n this.sitePlanCenterlatitude = housingInformation.SitePlanCenterLatitude;\r\n this.sitePlanCenterlongitude = housingInformation.SitePlanCenterLongitude;\r\n\r\n if (this.isBasic) {\r\n this.zIndex = 1;\r\n } else if (this.isFeaturedListing) {\r\n this.zIndex = 4;\r\n } else {\r\n this.zIndex = 2;\r\n }\r\n }\r\n\r\n /**\r\n * getMarkerText: gets the text the marker is going to show once rendered.\r\n * @returns a text to show on the map once rendered.\r\n */\r\n getMarkerText() {\r\n if (!this.isCallForPrice) {\r\n return this.shortPrice;\r\n }\r\n return '';\r\n }\r\n\r\n /**\r\n * @returns The name of the extend marker type.\r\n */\r\n getType() {\r\n return this.type;\r\n }\r\n\r\n /**\r\n * getInteractiveSitePlanSection: adds a

with the information needed to reach\r\n * the interactive site plan of the marker, if any.\r\n */\r\n getInteractiveSitePlanSection() {\r\n if (!this.hasInteractiveSitePlan) {\r\n return '';\r\n }\r\n\r\n return `\r\n ${interactiveSitePlanSvg} Interactive Map\r\n `;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing development marker.\r\n */\r\n getCardElement() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n

${this.priceText}
\r\n

${this.title}

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker. This card has\r\n * the peculiarity to show price reduction information.\r\n */\r\n getCardElementWithPriceReduction() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n
${this.priceText}
\r\n

${this.title}

\r\n

\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n ${this.priceReducedText}\r\n

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n\r\n return hoverCard;\r\n }\r\n\r\n getFacts() {\r\n if (this.isCallForPrice) {\r\n return '';\r\n }\r\n\r\n return `

${this.detailText}

`;\r\n }\r\n\r\n /**\r\n * It returns a string that is the url to the detail page of the community\r\n * @returns The string `/communitydetail/community-${this.id}`\r\n */\r\n getDetailUrl() {\r\n return `/communitydetail/builder-${this.builderId}/community-${this.id}`;\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action, and\r\n * event label set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class.\r\n */\r\n getGoogleAnalyticsEventForClicks() {\r\n const customDimensions = {\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: this.priceReducedTrackingLabel,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()]: this.communityName,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()]: this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()]: !this.isBasic,\r\n };\r\n\r\n const url = this.getDetailUrl();\r\n return new GoogleAnalyticsEvent('Map-Pin-Clicks', 'Communities: SRP-Map-Comm-Clicks', url, customDimensions);\r\n }\r\n\r\n /**\r\n * This function returns a new meta data object with the required information based on the map pin data.\r\n * @returns A new instance of the meta data object.\r\n */\r\n getHousingLocationMetaData() {\r\n return {\r\n priceReducedTrackingLabel: this.priceReducedTrackingLabel,\r\n communityName: this.communityName,\r\n communityId: this.id,\r\n isPaid: !this.isBasic,\r\n priceLow: this.priceLow,\r\n priceHigh: this.priceHigh,\r\n hasInteractiveSitePlan: this.hasInteractiveSitePlan,\r\n };\r\n }\r\n\r\n /**\r\n * This function returns the HTML in charge of build the hover card of a given marker\r\n * @returns hover card HTML\r\n */\r\n getCard() {\r\n if (this.priceReducedText) {\r\n return this.getCardElementWithPriceReduction();\r\n }\r\n\r\n return this.getCardElement();\r\n }\r\n\r\n /**\r\n * @returns The complete HTML that represent the housing development marker as an icon and a card with details.\r\n */\r\n getIcon() {\r\n const parentElement = document.createElement('div');\r\n const htmlPinElement = this.getHtmlPinElement();\r\n const cardElement = this.getCard();\r\n\r\n parentElement.appendChild(htmlPinElement);\r\n parentElement.appendChild(cardElement);\r\n parentElement.classList.add('nhs-c-advance-marker', 'nhs-c-tooltip-hide', 'nhs-mq-tooltip-show--large');\r\n\r\n return parentElement;\r\n }\r\n\r\n /**\r\n * getMarkerIcon: gets the html in charge of representing the marker icon given some important attribute of it,\r\n * like being a price reduction marker, call for price marker, among others.\r\n * @returns a html string representing the marker icon.\r\n */\r\n getMarkerIcon() {\r\n if (this.isCallForPrice) {\r\n return `\r\n
\r\n
${callForPriceCommunitySvgElement.cloneNode(true).outerHTML}
\r\n
${callForPriceCommunityActiveSvgElement.cloneNode(true).outerHTML}
\r\n
`;\r\n }\r\n\r\n if (this.priceReducedText) {\r\n return `
${priceReducedSvgElement.cloneNode(true).outerHTML}
`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * getShortPriceIconSection: gets a div with the short price to show in the marker icon.\r\n * @returns a div with the short price to show in the marker icon.\r\n */\r\n getShortPriceIconSection() {\r\n return this.getMarkerText()\r\n ? `
${this.getMarkerText()}
`\r\n : '';\r\n }\r\n\r\n /**\r\n * getDescription: returns a description that will help screen readers\r\n * provide a better explanation about the marker itself.\r\n * @returns a description for the marker.\r\n */\r\n getDescription() {\r\n if (this.shortPrice) {\r\n return `Homes from ${this.shortPrice}`;\r\n }\r\n\r\n return this.title;\r\n }\r\n\r\n /**\r\n * getMarkerStyles function is in charge of returning an array with the classes to use for the map marker.\r\n * @returns an array representing all the classes we should apply to the map marker in terms of its characteristics.\r\n */\r\n getMarkerStyles() {\r\n const { base, viewed } = getClassesToApply({\r\n isBasic: this.isBasic,\r\n isNoPrice: this.isCallForPrice,\r\n isSpotlight: this.isFeaturedListing,\r\n isViewed: this.isViewed,\r\n isPriceReduction: this.isPriceReduction,\r\n });\r\n\r\n const classesToApply = [...base, ...viewed].filter(Boolean);\r\n return classesToApply;\r\n }\r\n\r\n /**\r\n * setMarkerInformation: this callback takes the marker node and sets the data attributes needed to\r\n * identifying the marker and render it in the right map spot.\r\n * @param {HTMLDivElement} marker that will hold the information this callback sets.\r\n */\r\n setMarkerInformation(marker) {\r\n marker.dataset.id = this.id;\r\n marker.dataset.type = this.getType();\r\n marker.dataset.geographicKey = createMarkerHashedKey(this.latitude, this.longitude);\r\n marker.dataset.priceReducedTrackingLabel = this.priceReducedTrackingLabel;\r\n marker.dataset.isSpotlight = this.isFeaturedListing;\r\n marker.dataset.isNoPrice = this.isCallForPrice;\r\n marker.dataset.viewed = this.isViewed;\r\n marker.dataset.isPriceReduction = this.isPriceReduction;\r\n marker.dataset.qa = 'marker_container';\r\n\r\n if (this.isBasic) {\r\n marker.dataset.isBasic = true;\r\n } else {\r\n marker.dataset.isPaid = true;\r\n }\r\n }\r\n\r\n /**\r\n * Creates a HTML element representing a pin marker of housing development.\r\n * @returns the HTML Element that can represent the marker in the map.\r\n */\r\n getHtmlPinElement() {\r\n const element = document.createElement('div');\r\n element.dataset.markerIcon = true;\r\n element.classList.add(...this.getMarkerStyles());\r\n this.setMarkerInformation(element);\r\n\r\n if (this.isBasic) {\r\n return element;\r\n }\r\n\r\n const arrow = markerArrowSvgElement.cloneNode(true);\r\n arrow.classList.add('nhs-c-marker__arrow--default');\r\n\r\n const hoverArrow = markerArrowHoverSvgElement.cloneNode(true);\r\n hoverArrow.classList.add('nhs-c-marker__arrow--hover');\r\n\r\n element.innerHTML = `\r\n
\r\n ${this.getMarkerIcon()}\r\n ${this.getShortPriceIconSection()}\r\n ${arrow.outerHTML}\r\n ${hoverArrow.outerHTML}\r\n
\r\n `;\r\n\r\n return element;\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport { interactiveSitePlanSvg } from 'constants/svg-assets';\r\nimport { priceReducedSvgElement } from '../constants/svgIcons';\r\nimport MarkerType from '../enums/markerType';\r\nimport { isHousingDevelopmentViewed } from '../services/markerSessionService';\r\nimport getClassesToApply from '../services/unitMarkerService';\r\nimport { markerArrowHoverSvgElement, markerArrowSvgElement } from '../constants/svgIcons.b1';\r\n\r\n/* Creates a new instance of a housing unit that will be plotted in the map as a marker. */\r\nexport default class BuildablePlanMarker {\r\n constructor(housingInformation) {\r\n this.geoId = housingInformation.GeoId;\r\n this.detailText = housingInformation.DetailText;\r\n this.type = MarkerType.BuildablePlan.toString();\r\n this.id = housingInformation.Id;\r\n this.communityId = housingInformation.Id;\r\n this.isBasic = housingInformation.IsBasic || housingInformation.IsBl;\r\n this.latitude = housingInformation.Latitude;\r\n this.longitude = housingInformation.Longitude;\r\n // TODO: NewHomeSource Rebrand\r\n // Change the class on the backend.\r\n this.priceText = housingInformation.PriceText.replace('small--text', 'nhs-c-tooltip__price-label--small');\r\n this.shortPrice = housingInformation.ShortPrice;\r\n this.title = housingInformation.Title;\r\n this.totalPlans = +housingInformation.TotalPlans;\r\n this.priceReducedText = housingInformation.PriceReducedText;\r\n this.priceReducedTrackingLabel = housingInformation.PriceReducedTrackingLabel;\r\n this.zIndex = 2;\r\n this.builderId = housingInformation.BuilderId;\r\n this.isCallForPrice = housingInformation.IsCallForPrice;\r\n this.isFeaturedListing = housingInformation.IsFeaturedListing;\r\n this.isViewed = isHousingDevelopmentViewed(housingInformation.Id);\r\n this.priceLow = housingInformation.PriceLow;\r\n this.priceHigh = housingInformation.PriceHigh;\r\n this.hasInteractiveSitePlan = housingInformation.HasInteractiveSitePlan;\r\n this.sitePlanCenterlatitude = housingInformation.SitePlanCenterLatitude;\r\n this.sitePlanCenterlongitude = housingInformation.SitePlanCenterLongitude;\r\n\r\n if (this.isBasic) {\r\n this.zIndex = 1;\r\n } else if (this.isFeaturedListing) {\r\n this.zIndex = 4;\r\n } else {\r\n this.zIndex = 3;\r\n }\r\n }\r\n\r\n /**\r\n * @returns The name of the extend marker type.\r\n */\r\n getType() {\r\n return this.type;\r\n }\r\n\r\n /**\r\n * getMarkerText: gets the text the marker is going to show once rendered.\r\n * @returns a text to show on the map once rendered.\r\n */\r\n getMarkerText() {\r\n return this.totalPlans + ' Plans';\r\n }\r\n\r\n /**\r\n * getInteractiveSitePlanSection: adds a

with the information needed to reach\r\n * the interactive site plan of the marker, if any.\r\n */\r\n getInteractiveSitePlanSection() {\r\n if (!this.hasInteractiveSitePlan) {\r\n return '';\r\n }\r\n\r\n return `\r\n ${interactiveSitePlanSvg} Interactive Map\r\n `;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker.\r\n */\r\n getCardElement() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n

${this.priceText}
\r\n

${this.title}

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker. This card has\r\n * the peculiarity to show price reduction information.\r\n */\r\n getCardElementWithPriceReduction() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n
\r\n ${this.priceText}\r\n
\r\n

${this.title}

\r\n

\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n ${this.priceReducedText}\r\n

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n\r\n return hoverCard;\r\n }\r\n\r\n getFacts() {\r\n if (this.isCallForPrice) {\r\n return '';\r\n }\r\n\r\n return `

${this.detailText}

`;\r\n }\r\n\r\n /**\r\n * This function returns a string that is the url to the detail page for the community.\r\n * @returns The string `/communitydetail/builder-${this.builderId}/community-${this.id}`\r\n */\r\n getDetailUrl() {\r\n return `/communitydetail/builder-${this.builderId}/community-${this.id}`;\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action, and\r\n * event label set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class.\r\n */\r\n getGoogleAnalyticsEventForClicks() {\r\n const customDimensions = {\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: this.priceReducedTrackingLabel,\r\n };\r\n\r\n const url = this.getDetailUrl();\r\n return new GoogleAnalyticsEvent('Map-Pin-Clicks', 'Homes: SRP-Map-Home-Clicks', url, customDimensions);\r\n }\r\n\r\n /**\r\n * This function returns a new meta data object with the required information based on the map pin data.\r\n * @returns A new instance of the meta data object.\r\n */\r\n getHousingLocationMetaData() {\r\n return {\r\n priceReducedTrackingLabel: this.priceReducedTrackingLabel,\r\n communityName: this.title,\r\n communityId: this.id,\r\n isPaid: !this.isBasic,\r\n priceLow: this.priceLow,\r\n priceHigh: this.priceHigh,\r\n hasInteractiveSitePlan: this.hasInteractiveSitePlan,\r\n };\r\n }\r\n\r\n /**\r\n * This function returns the HTML in charge of build the hover card of a given marker\r\n * @returns hover card HTML\r\n */\r\n getCard() {\r\n if (this.priceReducedText) {\r\n return this.getCardElementWithPriceReduction();\r\n }\r\n\r\n return this.getCardElement();\r\n }\r\n\r\n /**\r\n * @returns The complete HTML that represent the housing unit marker as an icon and a card with details.\r\n */\r\n getIcon() {\r\n const parentElement = document.createElement('div');\r\n const htmlPinElement = this.getHtmlPinElement();\r\n const cardElement = this.getCard();\r\n\r\n parentElement.appendChild(htmlPinElement);\r\n parentElement.appendChild(cardElement);\r\n parentElement.classList.add('nhs-c-advance-marker', 'nhs-c-tooltip-hide', 'nhs-mq-tooltip-show--large');\r\n\r\n return parentElement;\r\n }\r\n\r\n /**\r\n * getDescription: returns a description that will help screen readers\r\n * provide a better explanation about the marker itself.\r\n * @returns a description for the marker.\r\n */\r\n getDescription() {\r\n if (this.shortPrice) {\r\n return `Plans from ${this.shortPrice}`;\r\n }\r\n\r\n return this.title;\r\n }\r\n\r\n /**\r\n * getMarkerTextNode: gets the html node to represent the marker text\r\n * @returns a string representing the html node to render a marker text\r\n */\r\n getMarkerTextNode() {\r\n if (this.getMarkerText()) {\r\n return `
\r\n ${this.getMarkerText()}\r\n
`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * getMarkerStyles function is in charge of returning an array with the classes to use for the map marker.\r\n * @returns an array representing all the classes we should apply to the map marker in terms of its characteristics.\r\n */\r\n getMarkerStyles() {\r\n const { base, viewed } = getClassesToApply({\r\n isBasic: this.isBasic,\r\n isSpotlight: this.isFeaturedListing,\r\n isViewed: this.isViewed,\r\n });\r\n\r\n const classesToApply = [...base, ...viewed].filter(Boolean);\r\n return classesToApply;\r\n }\r\n\r\n /**\r\n * setMarkerInformation: this callback takes the marker node and sets the data attributes needed to\r\n * identifying the marker and render it in the right map spot.\r\n * @param {HTMLDivElement} marker that will hold the information this callback sets.\r\n */\r\n setMarkerInformation(marker) {\r\n marker.dataset.id = this.id;\r\n marker.dataset.type = this.getType();\r\n marker.dataset.geographicKey = createMarkerHashedKey(this.latitude, this.longitude);\r\n marker.dataset.priceReducedTrackingLabel = this.priceReducedTrackingLabel;\r\n marker.dataset.isSpotlight = this.isFeaturedListing;\r\n marker.dataset.isNoPrice = this.isCallForPrice;\r\n marker.dataset.viewed = this.isViewed;\r\n marker.dataset.qa = 'marker_container';\r\n\r\n if (this.isBasic) {\r\n marker.dataset.isBasic = true;\r\n } else {\r\n marker.dataset.isPaid = true;\r\n }\r\n }\r\n\r\n /**\r\n * Creates a HTML element representing a pin marker of buildable plan.\r\n * @returns the HTML Element that can represent the marker in the map.\r\n */\r\n getHtmlPinElement() {\r\n const element = document.createElement('div');\r\n element.dataset.markerIcon = true;\r\n element.classList.add(...this.getMarkerStyles());\r\n this.setMarkerInformation(element);\r\n\r\n if (this.isBasic) {\r\n return element;\r\n }\r\n\r\n const arrow = markerArrowSvgElement.cloneNode(true);\r\n arrow.classList.add('nhs-c-marker__arrow--default');\r\n\r\n const hoverArrow = markerArrowHoverSvgElement.cloneNode(true);\r\n hoverArrow.classList.add('nhs-c-marker__arrow--hover');\r\n\r\n element.innerHTML = `\r\n
\r\n ${this.getMarkerTextNode()}\r\n ${arrow.outerHTML}\r\n ${hoverArrow.outerHTML}\r\n
\r\n `;\r\n\r\n return element;\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport { interactiveSitePlanSvg } from 'constants/svg-assets';\r\nimport { callForPriceHomeSvgElement, priceReducedSvgElement } from '../constants/svgIcons';\r\nimport MarkerType from '../enums/markerType';\r\nimport { isPlanViewed } from '../services/markerSessionService';\r\nimport {\r\n callForPriceHomeActiveSvgElement,\r\n markerArrowHoverSvgElement,\r\n markerArrowSvgElement,\r\n} from '../constants/svgIcons.b1';\r\nimport getClassesToApply from '../services/unitMarkerService';\r\n\r\n/* Creates a new instance of a housing unit that will be plotted in the map as a marker. */\r\nexport default class PlanUnitMarker {\r\n constructor(housingInformation) {\r\n const totalPlans = housingInformation.TotalPlans ?? 1;\r\n this.geoId = housingInformation.GeoId;\r\n this.detailText = housingInformation.DetailText;\r\n this.type = MarkerType.PlanUnit.toString();\r\n this.id = housingInformation.Id;\r\n this.communityId = housingInformation.CommunityId;\r\n this.isBasic = housingInformation.IsBasic || housingInformation.IsBl;\r\n this.latitude = housingInformation.Latitude;\r\n this.longitude = housingInformation.Longitude;\r\n // TODO: NewHomeSource Rebrand\r\n // Change the class on the backend.\r\n this.priceText = housingInformation.PriceText.replace('small--text', 'nhs-c-tooltip__price-label--small');\r\n this.shortPrice = housingInformation.ShortPrice;\r\n this.title = housingInformation.Title;\r\n this.totalPlans = +totalPlans;\r\n this.priceReducedText = housingInformation.PriceReducedText;\r\n this.isPriceReduction = !!housingInformation.PriceReducedText;\r\n this.previousPriceText = housingInformation.PreviousPriceText;\r\n this.priceReducedTrackingLabel = housingInformation.PriceReducedTrackingLabel;\r\n this.isFeaturedListing = housingInformation.IsFeaturedListing;\r\n this.isCallForPrice = housingInformation.IsCallForPrice;\r\n this.isViewed = isPlanViewed(housingInformation.Id);\r\n this.price = housingInformation.Price;\r\n this.hasInteractiveSitePlan = housingInformation.HasInteractiveSitePlan;\r\n this.sitePlanCenterlatitude = housingInformation.SitePlanCenterLatitude;\r\n this.sitePlanCenterlongitude = housingInformation.SitePlanCenterLongitude;\r\n\r\n if (this.isBasic) {\r\n this.zIndex = 1;\r\n } else if (this.isFeaturedListing) {\r\n this.zIndex = 4;\r\n } else {\r\n this.zIndex = 2;\r\n }\r\n }\r\n\r\n /**\r\n * getMarkerText: gets the text the marker is going to show once rendered.\r\n * @returns a text to show on the map once rendered.\r\n */\r\n getMarkerText() {\r\n return this.shortPrice;\r\n }\r\n\r\n /**\r\n * getMarkerTextNode: gets the html node to represent the marker text\r\n * @returns a string representing the html node to render a marker text\r\n */\r\n getMarkerTextNode() {\r\n if (this.shortPrice && !this.isCallForPrice) {\r\n return `
\r\n ${this.shortPrice}\r\n
`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * @returns The name of the extend marker type.\r\n */\r\n getType() {\r\n return this.type;\r\n }\r\n\r\n /**\r\n * getInteractiveSitePlanSection: adds a

with the information needed to reach\r\n * the interactive site plan of the marker, if any.\r\n */\r\n getInteractiveSitePlanSection() {\r\n if (!this.hasInteractiveSitePlan) {\r\n return '';\r\n }\r\n\r\n return `\r\n ${interactiveSitePlanSvg} Interactive Map\r\n `;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker.\r\n */\r\n getCardElementDefault() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n

${this.shortPrice || this.priceText}
\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker. This card has\r\n * the peculiarity to show price reduction information.\r\n */\r\n getCardElementWithPriceReduction() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n
\r\n ${this.shortPrice || this.priceText}\r\n \r\n ${this.previousPriceText}\r\n \r\n
\r\n

\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n ${this.priceReducedText}\r\n

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n return hoverCard;\r\n }\r\n\r\n getFacts() {\r\n if (this.isCallForPrice) {\r\n return '';\r\n }\r\n\r\n return `

${this.detailText}

`;\r\n }\r\n\r\n /**\r\n * It returns a string that is the url to the detail page of the home plan\r\n * @returns The string `/homedetail/planid-${this.id}`\r\n */\r\n getDetailUrl() {\r\n return `/homedetail/planid-${this.id}`;\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action, and\r\n * event label set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class.\r\n */\r\n getGoogleAnalyticsEventForClicks() {\r\n const customDimensions = {\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: this.priceReducedTrackingLabel,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()]: this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()]: !this.isBasic,\r\n };\r\n const url = this.getDetailUrl();\r\n return new GoogleAnalyticsEvent('Map-Pin-Clicks', 'Homes: SRP-Map-Home-Clicks', url, customDimensions);\r\n }\r\n\r\n /**\r\n * This function returns a new meta data object with the required information based on the map pin data.\r\n * @returns A new instance of the meta data object.\r\n */\r\n getHousingLocationMetaData() {\r\n return {\r\n priceReducedTrackingLabel: this.priceReducedTrackingLabel,\r\n planId: this.id,\r\n isPaid: !this.isBasic,\r\n priceLow: this.price,\r\n hasInteractiveSitePlan: this.hasInteractiveSitePlan,\r\n communityId: this.communityId,\r\n };\r\n }\r\n\r\n /**\r\n * This function returns the HTML in charge of build the hover card of a given marker\r\n * @returns hover card HTML\r\n */\r\n getCard() {\r\n if (this.priceReducedText) {\r\n return this.getCardElementWithPriceReduction();\r\n }\r\n\r\n return this.getCardElementDefault();\r\n }\r\n\r\n /**\r\n * @returns The complete HTML that represent the housing unit marker as an icon and a card with details.\r\n */\r\n getIcon() {\r\n const parentElement = document.createElement('div');\r\n const htmlPinElement = this.getHtmlPinElement();\r\n const cardElement = this.getCard();\r\n\r\n parentElement.appendChild(htmlPinElement);\r\n parentElement.appendChild(cardElement);\r\n parentElement.classList.add('nhs-c-advance-marker', 'nhs-c-tooltip-hide', 'nhs-mq-tooltip-show--large');\r\n\r\n return parentElement;\r\n }\r\n\r\n /**\r\n * getMarkerIcon: gets the html in charge of representing the marker icon given some important attribute of it,\r\n * like being a price reduction marker, call for price marker, among others.\r\n * @returns a html string representing the marker icon.\r\n */\r\n getMarkerIcon() {\r\n if (this.isCallForPrice) {\r\n return `\r\n
\r\n
${callForPriceHomeSvgElement.cloneNode(true).outerHTML}
\r\n
${callForPriceHomeActiveSvgElement.cloneNode(true).outerHTML}
\r\n
`;\r\n }\r\n\r\n if (this.priceReducedText) {\r\n return `
${priceReducedSvgElement.cloneNode(true).outerHTML}
`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * getDescription: returns a description that will help screen readers\r\n * provide a better explanation about the marker itself.\r\n * @returns a description for the marker.\r\n */\r\n getDescription() {\r\n if (this.shortPrice) {\r\n return `Plan from ${this.shortPrice}`;\r\n }\r\n\r\n return this.title;\r\n }\r\n\r\n /**\r\n * getMarkerStyles function is in charge of returning an array with the classes to use for the map marker.\r\n * @returns an array representing all the classes we should apply to the map marker in terms of its characteristics.\r\n */\r\n getMarkerStyles() {\r\n const { base, viewed } = getClassesToApply({\r\n isBasic: this.isBasic,\r\n isNoPrice: this.isCallForPrice,\r\n isSpotlight: this.isFeaturedListing,\r\n isViewed: this.isViewed,\r\n isPriceReduction: this.isPriceReduction,\r\n });\r\n\r\n const classesToApply = [...base, ...viewed].filter(Boolean);\r\n return classesToApply;\r\n }\r\n\r\n /**\r\n * setMarkerInformation: this callback takes the marker node and sets the data attributes needed to\r\n * identifying the marker and render it in the right map spot.\r\n * @param {HTMLDivElement} marker that will hold the information this callback sets.\r\n */\r\n setMarkerInformation(marker) {\r\n marker.dataset.id = this.id;\r\n marker.dataset.type = this.getType();\r\n marker.dataset.geographicKey = createMarkerHashedKey(this.latitude, this.longitude);\r\n marker.dataset.priceReducedTrackingLabel = this.priceReducedTrackingLabel;\r\n marker.dataset.isSpotlight = this.isFeaturedListing;\r\n marker.dataset.isNoPrice = this.isCallForPrice;\r\n marker.dataset.viewed = this.isViewed;\r\n marker.dataset.isPriceReduction = this.isPriceReduction;\r\n marker.dataset.qa = 'marker_container';\r\n\r\n if (this.isBasic) {\r\n marker.dataset.isBasic = true;\r\n } else {\r\n marker.dataset.isPaid = true;\r\n }\r\n }\r\n\r\n /**\r\n * Creates a HTML element representing a pin marker of plan unit.\r\n * @returns the HTML Element that can represent the marker in the map.\r\n */\r\n getHtmlPinElement() {\r\n const element = document.createElement('div');\r\n element.dataset.markerIcon = true;\r\n element.classList.add(...this.getMarkerStyles());\r\n this.setMarkerInformation(element);\r\n\r\n if (this.isBasic) {\r\n return element;\r\n }\r\n\r\n const arrow = markerArrowSvgElement.cloneNode(true);\r\n arrow.classList.add('nhs-c-marker__arrow--default');\r\n\r\n const hoverArrow = markerArrowHoverSvgElement.cloneNode(true);\r\n hoverArrow.classList.add('nhs-c-marker__arrow--hover');\r\n\r\n element.innerHTML = `\r\n
\r\n ${this.getMarkerIcon()}\r\n ${this.getMarkerTextNode()}\r\n ${arrow.outerHTML}\r\n ${hoverArrow.outerHTML}\r\n
\r\n `;\r\n\r\n return element;\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport { interactiveSitePlanSvg } from 'constants/svg-assets';\r\nimport { callForPriceHomeSvgElement, priceReducedSvgElement } from '../constants/svgIcons';\r\nimport MarkerType from '../enums/markerType';\r\nimport { isSpecViewed } from '../services/markerSessionService';\r\nimport {\r\n callForPriceHomeActiveSvgElement,\r\n markerArrowHoverSvgElement,\r\n markerArrowSvgElement,\r\n} from '../constants/svgIcons.b1';\r\nimport getClassesToApply from '../services/unitMarkerService';\r\n\r\n/* Creates a new instance of a housing unit that will be plotted in the map as a marker. */\r\nexport default class SpecUnitMarker {\r\n constructor(housingInformation) {\r\n const totalPlans = housingInformation.TotalPlans ?? 1;\r\n this.geoId = housingInformation.GeoId;\r\n this.detailText = housingInformation.DetailText;\r\n this.type = MarkerType.SpecUnit.toString();\r\n this.id = housingInformation.Id;\r\n this.communityId = housingInformation.CommunityId;\r\n this.isBasic = housingInformation.IsBasic || housingInformation.IsBl;\r\n this.latitude = housingInformation.Latitude;\r\n this.longitude = housingInformation.Longitude;\r\n // TODO: NewHomeSource Rebrand\r\n // Change the class on the backend.\r\n this.priceText = housingInformation.PriceText.replace('small--text', 'nhs-c-tooltip__price-label--small');\r\n this.shortPrice = housingInformation.ShortPrice;\r\n this.title = housingInformation.Title;\r\n this.totalPlans = +totalPlans;\r\n this.priceReducedText = housingInformation.PriceReducedText;\r\n this.isPriceReduction = !!housingInformation.PriceReducedText;\r\n this.previousPriceText = housingInformation.PreviousPriceText;\r\n this.priceReducedTrackingLabel = housingInformation.PriceReducedTrackingLabel;\r\n this.isFeaturedListing = housingInformation.IsFeaturedListing;\r\n this.isCallForPrice = housingInformation.IsCallForPrice;\r\n this.isViewed = isSpecViewed(housingInformation.Id);\r\n this.price = housingInformation.Price;\r\n this.hasInteractiveSitePlan = housingInformation.HasInteractiveSitePlan;\r\n this.sitePlanCenterlatitude = housingInformation.SitePlanCenterLatitude;\r\n this.sitePlanCenterlongitude = housingInformation.SitePlanCenterLongitude;\r\n\r\n if (this.isBasic) {\r\n this.zIndex = 1;\r\n } else if (this.isFeaturedListing) {\r\n this.zIndex = 4;\r\n } else {\r\n this.zIndex = 3;\r\n }\r\n }\r\n\r\n /**\r\n * getMarkerText: gets the text the marker is going to show once rendered.\r\n * @returns a text to show on the map once rendered.\r\n */\r\n getMarkerText() {\r\n return this.shortPrice;\r\n }\r\n\r\n /**\r\n * getMarkerTextNode: gets the html node to represent the marker text\r\n * @returns a string representing the html node to render a marker text\r\n */\r\n getMarkerTextNode() {\r\n if (this.shortPrice && !this.isCallForPrice) {\r\n return `
\r\n ${this.shortPrice}\r\n
`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * @returns The name of the extend marker type.\r\n */\r\n getType() {\r\n return this.type;\r\n }\r\n\r\n /**\r\n * getInteractiveSitePlanSection: adds a

with the information needed to reach\r\n * the interactive site plan of the marker, if any.\r\n */\r\n getInteractiveSitePlanSection() {\r\n if (!this.hasInteractiveSitePlan) {\r\n return '';\r\n }\r\n\r\n return `\r\n ${interactiveSitePlanSvg} Interactive Map\r\n `;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker.\r\n */\r\n getCardElementDefault() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n

${this.shortPrice || this.priceText}
\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * @returns The HTML for the card element to be associated to this housing unit marker. This card has\r\n * the peculiarity to show price reduction information.\r\n */\r\n getCardElementWithPriceReduction() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.classList.add('nhs-c-tooltip--map');\r\n hoverCard.dataset.id = this.id;\r\n hoverCard.dataset.tooltip = true;\r\n hoverCard.dataset.markerStyles = this.getMarkerStyles();\r\n\r\n hoverCard.innerHTML = `\r\n
\r\n ${this.shortPrice || this.priceText}\r\n \r\n ${this.previousPriceText}\r\n \r\n
\r\n

\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML} \r\n ${this.priceReducedText}\r\n

\r\n ${this.getFacts()}\r\n ${this.getInteractiveSitePlanSection()}\r\n `;\r\n return hoverCard;\r\n }\r\n\r\n getFacts() {\r\n if (this.isCallForPrice) {\r\n return '';\r\n }\r\n\r\n return `

${this.detailText}

`;\r\n }\r\n\r\n /**\r\n * It returns a string that is the url to the detail page for the spec home\r\n * @returns The string `/homedetail/specid-${this.id}`\r\n */\r\n getDetailUrl() {\r\n return `/homedetail/specid-${this.id}`;\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action, and\r\n * event label set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class.\r\n */\r\n getGoogleAnalyticsEventForClicks() {\r\n const customDimensions = {\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: this.priceReducedTrackingLabel,\r\n [GoogleAnalyticsCustomDimensions.SpecId().getName()]: this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()]: !this.isBasic,\r\n };\r\n const url = this.getDetailUrl();\r\n return new GoogleAnalyticsEvent('Map-Pin-Clicks', 'Homes: SRP-Map-Home-Clicks', url, customDimensions);\r\n }\r\n\r\n /**\r\n * This function returns a new meta data object with the required information based on the map pin data.\r\n * @returns A new instance of the meta data object.\r\n */\r\n getHousingLocationMetaData() {\r\n return {\r\n priceReducedTrackingLabel: this.priceReducedTrackingLabel,\r\n specId: this.id,\r\n isPaid: !this.isBasic,\r\n priceLow: this.price,\r\n hasInteractiveSitePlan: this.hasInteractiveSitePlan,\r\n communityId: this.communityId,\r\n };\r\n }\r\n\r\n /**\r\n * This function returns the HTML in charge of build the hover card of a given marker\r\n * @returns hover card HTML\r\n */\r\n getCard() {\r\n if (this.priceReducedText) {\r\n return this.getCardElementWithPriceReduction();\r\n }\r\n\r\n return this.getCardElementDefault();\r\n }\r\n\r\n /**\r\n * @returns The complete HTML that represent the housing unit marker as an icon and a card with details.\r\n */\r\n getIcon() {\r\n const parentElement = document.createElement('div');\r\n const htmlPinElement = this.getHtmlPinElement();\r\n const cardElement = this.getCard();\r\n\r\n parentElement.appendChild(htmlPinElement);\r\n parentElement.appendChild(cardElement);\r\n parentElement.classList.add('nhs-c-advance-marker', 'nhs-c-tooltip-hide', 'nhs-mq-tooltip-show--large');\r\n\r\n return parentElement;\r\n }\r\n\r\n /**\r\n * getMarkerIcon: gets the html in charge of representing the marker icon given some important attribute of it,\r\n * like being a price reduction marker, call for price marker, among others.\r\n * @returns a html string representing the marker icon.\r\n */\r\n getMarkerIcon() {\r\n if (this.isCallForPrice) {\r\n return `\r\n
\r\n
${callForPriceHomeSvgElement.cloneNode(true).outerHTML}
\r\n
${callForPriceHomeActiveSvgElement.cloneNode(true).outerHTML}
\r\n
`;\r\n }\r\n\r\n if (this.priceReducedText) {\r\n return `
${priceReducedSvgElement.cloneNode(true).outerHTML}
`;\r\n }\r\n return '';\r\n }\r\n\r\n /**\r\n * getDescription: returns a description that will help screen readers\r\n * provide a better explanation about the marker itself.\r\n * @returns a description for the marker.\r\n */\r\n getDescription() {\r\n if (this.shortPrice) {\r\n return `Home from ${this.shortPrice}`;\r\n }\r\n\r\n return this.title;\r\n }\r\n\r\n /**\r\n * getMarkerStyles function is in charge of returning an array with the classes to use for the map marker.\r\n * @returns an array representing all the classes we should apply to the map marker in terms of its characteristics.\r\n */\r\n getMarkerStyles() {\r\n const { base, viewed } = getClassesToApply({\r\n isBasic: this.isBasic,\r\n isNoPrice: this.isCallForPrice,\r\n isSpotlight: this.isFeaturedListing,\r\n isViewed: this.isViewed,\r\n isPriceReduction: this.isPriceReduction,\r\n });\r\n\r\n const classesToApply = [...base, ...viewed].filter(Boolean);\r\n return classesToApply;\r\n }\r\n\r\n /**\r\n * setMarkerInformation: this callback takes the marker node and sets the data attributes needed to\r\n * identifying the marker and render it in the right map spot.\r\n * @param {HTMLDivElement} marker that will hold the information this callback sets.\r\n */\r\n setMarkerInformation(marker) {\r\n marker.dataset.id = this.id;\r\n marker.dataset.type = this.getType();\r\n marker.dataset.geographicKey = createMarkerHashedKey(this.latitude, this.longitude);\r\n marker.dataset.priceReducedTrackingLabel = this.priceReducedTrackingLabel;\r\n marker.dataset.isSpotlight = this.isFeaturedListing;\r\n marker.dataset.isNoPrice = this.isCallForPrice;\r\n marker.dataset.viewed = this.isViewed;\r\n marker.dataset.isPriceReduction = this.isPriceReduction;\r\n marker.dataset.qa = 'marker_container';\r\n\r\n if (this.isBasic) {\r\n marker.dataset.isBasic = true;\r\n } else {\r\n marker.dataset.isPaid = true;\r\n }\r\n }\r\n\r\n /**\r\n * Creates a HTML element representing a pin marker of spec unit.\r\n * @returns the HTML Element that can represent the marker in the map.\r\n */\r\n getHtmlPinElement() {\r\n const element = document.createElement('div');\r\n element.dataset.markerIcon = true;\r\n element.classList.add(...this.getMarkerStyles());\r\n this.setMarkerInformation(element);\r\n\r\n if (this.isBasic) {\r\n return element;\r\n }\r\n\r\n const arrow = markerArrowSvgElement.cloneNode(true);\r\n arrow.classList.add('nhs-c-marker__arrow--default');\r\n\r\n const hoverArrow = markerArrowHoverSvgElement.cloneNode(true);\r\n hoverArrow.classList.add('nhs-c-marker__arrow--hover');\r\n\r\n element.innerHTML = `\r\n
\r\n ${this.getMarkerIcon()}\r\n ${this.getMarkerTextNode()}\r\n ${arrow.outerHTML}\r\n ${hoverArrow.outerHTML}\r\n
\r\n `;\r\n\r\n return element;\r\n }\r\n}\r\n","import { ProductType, ResultType } from 'features/searchResultsFacets';\r\nimport HousingDevelopmentMarker from '../models/housingDevelopmentMarker';\r\nimport BuildablePlanMarker from '../models/buildablePlanMarker';\r\nimport PlanUnitMarker from '../models/planUnitMarker';\r\nimport SpecUnitMarker from '../models/specUnitMarker';\r\nimport MarkerType from '../enums/markerType';\r\n\r\n/**\r\n * It filters out plans that are in the buildablePlans array from the plans array.\r\n * @param plans - An array of plans.\r\n * @param buildablePlans - An array of Housing Developments that has more than one plan.\r\n */\r\nexport const filterPlansFromBuildablePlans = (plans, buildablePlans) =>\r\n plans.filter((plan) => !buildablePlans.some((x) => x.GeoId === plan.GeoId));\r\n\r\n/**\r\n * Get all housing developments that have more than one plan.\r\n * @param housingDevelopments - An array of housing developments.\r\n */\r\nexport const getAllBuildablePlans = (housingDevelopments, plans) => {\r\n const featuredPlans = plans.filter(plan => plan.IsFeaturedListing).map(plan => plan.GeoId);\r\n const buildablePlans = housingDevelopments.filter((x) => x.TotalPlans > 1);\r\n \r\n buildablePlans.filter(plan => featuredPlans.includes(plan.GeoId)).forEach(element => {\r\n element.IsFeaturedListing = true;\r\n });\r\n\r\n return buildablePlans;\r\n} ;\r\n\r\n/**\r\n * If the productType is 'communities', then create a new HousingDevelopmentMarker, otherwise create a\r\n * new HousingUnitMarker.\r\n * @param productType - 'communities' or 'homes'\r\n * @param allHousing - an array of objects\r\n * @returns An array of objects.\r\n */\r\nexport const getMarkers = (productType, allHousing) => {\r\n const isCommunitiesSearch = productType === ResultType.Communities.toString();\r\n const markers = [\r\n ...allHousing.specs.map((spec) => new SpecUnitMarker(spec)),\r\n ...allHousing.plans.map((plan) => new PlanUnitMarker(plan)),\r\n ...allHousing.buildablePlans.map((b) => new BuildablePlanMarker(b)),\r\n ];\r\n\r\n if (isCommunitiesSearch) {\r\n return allHousing.communities.map((housing) => new HousingDevelopmentMarker(housing));\r\n }\r\n\r\n return markers;\r\n};\r\n\r\n\r\nexport const updatePageNumberOfMarkers = (productType, allHousing, markers) => {\r\n const isCommunitiesSearch = productType === ProductType.Communities.toString();\r\n const communityMarkers = markers.filter((marker) => marker.type === MarkerType.HousingDevelopment.toString());\r\n if (!isCommunitiesSearch ||\r\n !allHousing?.communities ||\r\n communityMarkers.length !== markers.length ||\r\n allHousing.communities.length !== markers.length) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < markers.length; i+=1) {\r\n const marker = markers[i];\r\n const sourceMarker = allHousing.communities[i];\r\n if(sourceMarker.Id === marker.id){\r\n marker.pageNumber = sourceMarker.Page;\r\n }\r\n else{\r\n const newPage = allHousing.communities.find((housing) => housing.Id === marker.id)?.Page;\r\n marker.pageNumber = newPage ?? marker.pageNumber;\r\n } \r\n }\r\n};","import { createSlice } from '@reduxjs/toolkit';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport initialState from './initialState';\r\nimport {\r\n filterPlansFromBuildablePlans,\r\n getAllBuildablePlans, \r\n getMarkers,\r\n updatePageNumberOfMarkers} from '../services/processMarkers';\r\n\r\n/* Creating a slice of the state for stuff related to the map. */\r\nexport const mapStateSlice = createSlice({\r\n name: 'mapState',\r\n initialState,\r\n reducers: {\r\n enableSearchWithinMap: (state) => {\r\n state.isSearchWithinMap = true;\r\n state.isSearchWithinMapReady = false;\r\n },\r\n disableSearchWithinMap: (state) => {\r\n state.isSearchWithinMap = false;\r\n state.isSearchWithinMapReady = false;\r\n },\r\n fetchResults: (state, action) => {\r\n state.isFetchingResults = action.payload.isFetchingResults;\r\n state.selectedMarker = null;\r\n state.nearbyListingsCarousel = null;\r\n },\r\n fetchResultsError: (state) => {\r\n state.isFetchingResults = false;\r\n },\r\n fetchResultsFulfilled: (state, action) => {\r\n const distinctHousingDevelopments = action.payload?.communities.CommunityResults || [];\r\n const productType = action.payload.parameters.product.productType;\r\n\r\n const allHousing = {\r\n communities: distinctHousingDevelopments,\r\n buildablePlans: [],\r\n specs: [],\r\n plans: [],\r\n };\r\n\r\n if (productType === 'homes') {\r\n const results = action.payload?.interactiveSitePlanHomes || action.payload?.homes;\r\n\r\n const plans = results?.Plans || [];\r\n allHousing.buildablePlans = getAllBuildablePlans(distinctHousingDevelopments, plans);\r\n allHousing.plans = filterPlansFromBuildablePlans(plans, allHousing.buildablePlans);\r\n allHousing.specs = results?.Specs || [];\r\n\r\n state.allPlanIds = plans.map((plan) => plan.Id);\r\n }\r\n\r\n state.isFetchingResults = false;\r\n state.results = getMarkers(productType, allHousing);\r\n },\r\n fetchResultsPagesNumbers: (state, action) => {\r\n const distinctHousingDevelopments = action.payload?.communities.CommunityResults || [];\r\n const productType = action.payload.parameters.product.productType;\r\n const allHousing = {\r\n communities: distinctHousingDevelopments,\r\n buildablePlans: [],\r\n specs: [],\r\n plans: [],\r\n };\r\n\r\n updatePageNumberOfMarkers(productType, allHousing, state.results);\r\n },\r\n mapLibraryFetch: (state) => {\r\n state.mapLibraryStatus = LoadingStatus.Loading.toString();\r\n },\r\n mapLibraryLoaded: (state) => {\r\n state.mapLibraryStatus = LoadingStatus.Succeeded.toString();\r\n },\r\n mapLibraryErrored: (state) => {\r\n state.mapLibraryStatus = LoadingStatus.Failed.toString();\r\n },\r\n onSearchWithinMapReady: (state) => {\r\n state.isSearchWithinMapReady = true;\r\n },\r\n selectedMarker: (state, action) => {\r\n state.selectedMarker = action.payload;\r\n state.nearbyListingsCarouselStatus = LoadingStatus.Loading.toString();\r\n },\r\n hoveredMarker: (state, action) => {\r\n state.hoveredMarker = action.payload;\r\n },\r\n /*\r\n The 'Update coordinates' action is intended to be changed exclusively by the map itself.\r\n It is imperative to avoid manually modifying the 'geoCoordinates' property, as doing so would compromise\r\n the intended functionality of the property and potentially lead to unintended adverse effects.\r\n */\r\n updateCoordinates: (state, action) => {\r\n state.geoCoordinates = action.payload;\r\n },\r\n getNearbyListingsCarouselFulfilled: (state, action) => {\r\n state.nearbyListingsCarouselStatus = LoadingStatus.Succeeded.toString();\r\n state.nearbyListingsCarousel = action.payload;\r\n },\r\n getNearbyListingsCarouselFailed: (state) => {\r\n state.nearbyListingsCarouselStatus = LoadingStatus.Failed.toString();\r\n state.nearbyListingsCarousel = null;\r\n },\r\n setActiveNearbyListingsCarousel: (state, action) => {\r\n state.nearbyListingsCarouselStatus = LoadingStatus.Succeeded.toString();\r\n state.nearbyListingsCarousel = action.payload; \r\n },\r\n clearNearbyListingsCarousel: (state) => {\r\n state.nearbyListingsCarouselStatus = LoadingStatus.Idle.toString();\r\n state.nearbyListingsCarousel = null;\r\n state.selectedMarker = null;\r\n },\r\n updateMapZoomLevel: (state, action) => {\r\n state.zoomLevel = action.payload;\r\n },\r\n addSitePlan: (state, action) => {\r\n state.sitePlans.push(action.payload);\r\n },\r\n removeSitePlan: (state, action) => {\r\n state.sitePlans = state.sitePlans.filter(\r\n sitePlan =>\r\n sitePlan.communityId !== action.payload.communityId &&\r\n sitePlan.url !== action.payload.url\r\n );\r\n },\r\n updateInteractiveSitePlanLoadingStatus: (state, action) => {\r\n action.payload.sitePlanIds.forEach(sitePlanId => {\r\n const sitePlan = state.sitePlans.find(plan => plan.sitePlanId === sitePlanId);\r\n sitePlan.markersLoadingStatus = action.payload.loadingStatus; \r\n });\r\n },\r\n },\r\n});\r\n\r\nexport const interactiveSitePlanSlice = createSlice({\r\n name: 'interactiveSitePlanState',\r\n initialState: {\r\n loadedInteractiveSitePlans: [],\r\n interactiveSitePlans: [],\r\n },\r\n reducers: {\r\n trackLoadedSitePlans: (state, action) => {\r\n const existingIndex = state.loadedInteractiveSitePlans.findIndex(\r\n (item) =>\r\n item.communityId === action.payload.communityId\r\n );\r\n \r\n if (existingIndex !== -1) {\r\n state.loadedInteractiveSitePlans[existingIndex] = {\r\n ...state.loadedInteractiveSitePlans[existingIndex],\r\n ...action.payload,\r\n };\r\n } else {\r\n state.loadedInteractiveSitePlans.push(action.payload);\r\n }\r\n },\r\n untrackInteractiveSitePlans: (state) => {\r\n state.loadedInteractiveSitePlans = [];\r\n },\r\n setInteractiveSitePlan: (state, action) => {\r\n const existingIndex = state.interactiveSitePlans.findIndex(\r\n (item) =>\r\n item.communityId === action.payload.communityId &&\r\n item.sitePlanId === action.payload.sitePlanId\r\n );\r\n \r\n if (existingIndex !== -1) {\r\n state.interactiveSitePlans[existingIndex] = {\r\n ...state.interactiveSitePlans[existingIndex],\r\n ...action.payload,\r\n };\r\n } else {\r\n state.interactiveSitePlans.push(action.payload);\r\n }\r\n },\r\n removeInteractiveSitePlan: (state, action) => {\r\n state.interactiveSitePlans = state.interactiveSitePlans.filter(\r\n sitePlan => sitePlan.sitePlanId !== action.payload\r\n );\r\n },\r\n setLotInformation: (state, action) => {\r\n state.lotId = action.payload.lotId;\r\n state.communityId = action.payload.communityId;\r\n state.lotNumber = action.payload.lotNumber;\r\n state.availableSpec = action.payload.availableSpec;\r\n state.availablePlans = action.payload.availablePlans;\r\n state.interactiveSitePlanCardStatus = action.payload.interactiveSitePlanCardStatus;\r\n state.lotStatus = action.payload.lotStatus;\r\n state.sitePlanId = action.payload.sitePlanId;\r\n },\r\n removeLotInformation: (state) => {\r\n state.lotId = null;\r\n state.communityId = null;\r\n state.lotNumber = null;\r\n state.availableSpec = null;\r\n state.availablePlans = null;\r\n state.interactiveSitePlanCard = null;\r\n state.lotStatus = null;\r\n state.sitePlanId = null;\r\n state.interactiveSitePlanCardStatus = LoadingStatus.Idle.toString();\r\n },\r\n getInteractiveSitePlanCardFulfilled: (state, action) => {\r\n if (state.interactiveSitePlanCardStatus === LoadingStatus.Loading.toString()) {\r\n state.interactiveSitePlanCardStatus = LoadingStatus.Succeeded.toString();\r\n state.interactiveSitePlanCard = action.payload;\r\n }\r\n },\r\n getInteractiveSitePlanCardFailed: (state) => {\r\n state.interactiveSitePlanCardStatus = LoadingStatus.Failed.toString();\r\n state.interactiveSitePlanCard = null;\r\n },\r\n clearInteractiveSitePlanCard: (state) => {\r\n state.interactiveSitePlanCardStatus = LoadingStatus.Idle.toString();\r\n state.interactiveSitePlanCard = null;\r\n },\r\n }\r\n});","import MarkerType from \"../enums/markerType\";\r\n\r\nconst markerConfiguration = {\r\n viewedPlanMarkers: [],\r\n viewedSpecMarkers: [],\r\n viewedCommunitiesMarkers: [],\r\n}\r\n\r\n/**\r\n * Loads the Viewed Markers ids inside the marker configuration object, in order to\r\n * display the already visited elements.\r\n */\r\nconst loadViewedMarkers = () => {\r\n const markersFromSession = sessionStorage.markersViewed !== undefined\r\n ? JSON.parse(sessionStorage.markersViewed) : markerConfiguration;\r\n markerConfiguration.viewedPlanMarkers = markersFromSession.viewedPlanMarkers;\r\n markerConfiguration.viewedSpecMarkers = markersFromSession.viewedSpecMarkers;\r\n markerConfiguration.viewedCommunitiesMarkers = markersFromSession.viewedCommunitiesMarkers;\r\n}\r\n\r\n/**\r\n * Check if the Hosing Development listing is already visited.\r\n */\r\nexport function isHousingDevelopmentViewed(id){ \r\n return markerConfiguration.viewedCommunitiesMarkers.indexOf(id) >= 0;\r\n}\r\n\r\n/**\r\n * Check if the spec unit listing is already visited.\r\n */\r\nexport function isSpecViewed(id){ \r\n return markerConfiguration.viewedSpecMarkers.indexOf(id) >= 0;\r\n}\r\n\r\n/**\r\n * Check if the plan listing is already visited.\r\n */\r\nexport function isPlanViewed(id){ \r\n return markerConfiguration.viewedPlanMarkers.indexOf(id) >= 0;\r\n}\r\n\r\n/**\r\n * Saved the community id clicked in the session storage.\r\n */\r\nconst saveCommunityMarkerViewed = (id) => {\r\n if(!isHousingDevelopmentViewed(id)){\r\n markerConfiguration.viewedCommunitiesMarkers.push(id);\r\n }\r\n}\r\n\r\n/**\r\n * Saved the spec id clicked in the session storage.\r\n */\r\nconst saveSpecMarkerViewed = (id) => {\r\n if(!isSpecViewed(id)){\r\n markerConfiguration.viewedSpecMarkers.push(id);\r\n }\r\n}\r\n\r\n/**\r\n * Saved the plan id clicked in the session storage.\r\n */\r\nconst savePlanMarkerViewed = (id) => {\r\n if(!isPlanViewed(id)){\r\n markerConfiguration.viewedPlanMarkers.push(id);\r\n }\r\n}\r\n\r\nloadViewedMarkers();\r\n\r\n/**\r\n * Gets the Marker Element clicked and handles its info to store it in the right configuration array.\r\n */\r\nexport function saveViewedMarker(marker){ \r\n if(marker.type === MarkerType.HousingDevelopment.toString()){\r\n saveCommunityMarkerViewed(marker.id);\r\n }\r\n if(marker.type === MarkerType.BuildablePlan.toString()){\r\n saveCommunityMarkerViewed(marker.id);\r\n }\r\n if(marker.type === MarkerType.PlanUnit.toString()){\r\n savePlanMarkerViewed(marker.id);\r\n }\r\n if(marker.type === MarkerType.SpecUnit.toString()){\r\n saveSpecMarkerViewed(marker.id);\r\n }\r\n sessionStorage.setItem(\"markersViewed\", JSON.stringify(markerConfiguration));\r\n}\r\n\r\n\r\n","/**\r\n * This RegExp gets all the caracters that cannot be used directly to an regexp expression.\r\n * Gets the characters +, \\, [, ] and ?.\r\n * The first and last '/' starts and finish the regex expression.\r\n * The '[]' that encapsulates everything match any character that is inside of it.\r\n * '+' matches '+'\r\n * '\\\\' matches '\\'\r\n * '[' matches '['\r\n * '\\]' matches ']'\r\n * '?' matches '?'\r\n*/ \r\nconst invalidRegexCharacters = /[+\\\\[\\]?]/;\r\n\r\n/**\r\n * Regular expression to check if a value is a number.\r\n */\r\nexport const isNumber = /\\d/;\r\n\r\nexport default invalidRegexCharacters;","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\n\r\n/**\r\n * Represents a Basic Summary Card component.\r\n */\r\nexport default class BasicCommunitySummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'basic',\r\n callToAction: 'Learn More',\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const callToActionButton = element.querySelector('[data-summary-card-cta]');\r\n callToActionButton.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = element.querySelector('[data-summary-card-link]');\r\n link.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Sets the label for the BasicSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price-low=\"${this.summaryCard.PriceLow}\"\r\n data-price-high=\"${this.summaryCard.PriceHigh}\"\r\n data-community-name=\"${this.summaryCard.Name}\"\r\n data-marketing-status=\"${this.summaryCard.MarketingStatus.Name}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-contact-vendor-name=\"${this.summaryCard.BasicContactVendorName}\"\r\n data-click-target=\"SRP Basic Map Card\"\r\n data-is-basic=\"true\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n \r\n \r\n

${this.getPrice()}

\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n

\r\n ${this.summaryCard.City}, ${this.summaryCard.StateAbbreviation}\r\n

\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\n\r\n/**\r\n * Represents a Basic Summary Card component.\r\n */\r\nexport default class BasicPlanSummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'basic',\r\n callToAction: 'Learn More',\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const elements = this.getElement();\r\n\r\n const callToActionButton = elements.querySelector('[data-summary-card-cta]');\r\n callToActionButton.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = elements.querySelector('[data-summary-card-link]');\r\n link.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = elements.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Returns the squarefeet information for the summary card.\r\n * If the squarefeet is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSquarefeet() {\r\n if (this.summaryCard.SquareFeet) {\r\n return `

${this.summaryCard.SquareFeet}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the bedrooms and bathrooms information for the summary card.\r\n * If the bedrooms and bathrooms is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSpecifications() {\r\n if (this.summaryCard.Bedrooms && this.summaryCard.Bathrooms) {\r\n return `

${this.summaryCard.Bedrooms} | ${this.summaryCard.Bathrooms}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Sets the label for the BasicPlanSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price=\"${this.summaryCard.PriceLow}\"\r\n data-min-price=\"${this.summaryCard.PriceLow}\"\r\n data-community-id=\"${this.summaryCard.CommunityId}\"\r\n data-community-name=\"${this.summaryCard.CommunityName}\"\r\n data-community-status=\"${this.summaryCard.CommunityType}\"\r\n data-home-status=\"${this.summaryCard.StatusLabel}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-contact-vendor-name=\"${this.summaryCard.BasicContactVendorName}\"\r\n data-is-basic=\"true\"\r\n data-click-target=\"SRP Basic Map Card\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n \r\n \r\n

${this.getPrice()}

\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n ${this.getSquarefeet()}\r\n ${this.getSpecifications()}\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\n\r\n/**\r\n * Represents a Basic Summary Card component.\r\n */\r\nexport default class BasicSpecSummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'basic',\r\n callToAction: 'Learn More',\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const callToActionButton = element.querySelector('[data-summary-card-cta]');\r\n callToActionButton.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = element.querySelector('[data-summary-card-link]');\r\n link.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Returns the squarefeet information for the summary card.\r\n * If the squarefeet is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSquarefeet() {\r\n if (this.summaryCard.SquareFeet) {\r\n return `

${this.summaryCard.SquareFeet}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the bedrooms and bathrooms information for the summary card.\r\n * If the bedrooms and bathrooms is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSpecifications() {\r\n if (this.summaryCard.Bedrooms && this.summaryCard.Bathrooms) {\r\n return `

${this.summaryCard.Bedrooms} | ${this.summaryCard.Bathrooms}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Sets the label for the BasicSpecSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price=\"${this.summaryCard.PriceLow}\"\r\n data-min-price=\"${this.summaryCard.PriceLow}\"\r\n data-community-id=\"${this.summaryCard.CommunityId}\"\r\n data-community-name=\"${this.summaryCard.CommunityName}\"\r\n data-community-status=\"${this.summaryCard.CommunityType}\"\r\n data-home-status=\"${this.summaryCard.StatusLabel}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-contact-vendor-name=\"${this.summaryCard.BasicContactVendorName}\"\r\n data-is-basic=\"true\"\r\n data-click-target=\"SRP Basic Map Card\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n \r\n \r\n

${this.getPrice()}

\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n ${this.getSquarefeet()}\r\n ${this.getSpecifications()}\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","/**\r\n * @classdesc The `CommunityType` class serves as the source of truth for current community types and their codes.\r\n */\r\nexport default class CommunityType {\r\n /**\r\n * Gets the instance for the Normal community type.\r\n * @returns {CommunityType} The instance for the Normal community type.\r\n */\r\n static get Normal() {\r\n return this.getInstance('SBC');\r\n }\r\n\r\n /**\r\n * Gets the instance for the Custom community type.\r\n * @returns {CommunityType} The instance for the Custom community type.\r\n */\r\n static get Custom() {\r\n return this.getInstance('CST');\r\n }\r\n\r\n /**\r\n * Gets the instance for the BuildOnYourLot community type.\r\n * @returns {CommunityType} The instance for the BuildOnYourLot community type.\r\n */\r\n static get BuildOnYourLot() {\r\n return this.getInstance('BYL');\r\n }\r\n\r\n /**\r\n * Gets the instance for the Modular community type.\r\n * @returns {CommunityType} The instance for the Modular community type.\r\n */\r\n static get Modular() {\r\n return this.getInstance('MFR');\r\n }\r\n\r\n /**\r\n * Gets the instance for the Condo community type.\r\n * @returns {CommunityType} The instance for the Condo community type.\r\n */\r\n static get Condo() {\r\n return this.getInstance('CON');\r\n }\r\n\r\n /**\r\n * Gets the instance for the Adult community type.\r\n * @returns {CommunityType} The instance for the Adult community type.\r\n */\r\n static get Adult() {\r\n return this.getInstance('ADU');\r\n }\r\n\r\n /**\r\n * Gets the instance for the TownHome community type.\r\n * @returns {CommunityType} The instance for the TownHome community type.\r\n */\r\n static get TownHome() {\r\n return this.getInstance('THM');\r\n }\r\n\r\n /**\r\n * Gets the instance for the MasterPlanned community type.\r\n * @returns {CommunityType} The instance for the MasterPlanned community type.\r\n */\r\n static get MasterPlanned() {\r\n return this.getInstance('MPC');\r\n }\r\n\r\n /**\r\n * Gets the instance for the CustomLocation community type.\r\n * @returns {CommunityType} The instance for the CustomLocation community type.\r\n */\r\n static get CustomLocation() {\r\n return this.getInstance('CSL');\r\n }\r\n\r\n /**\r\n * Converts a key to the corresponding community type instance.\r\n * @param {string} key The key representing a community type.\r\n * @returns {CommunityType|null} The community type instance or null if not found.\r\n */\r\n static fromKey(key) {\r\n const communityTypeMap = {\r\n SBC: CommunityType.Normal,\r\n CST: CommunityType.Custom,\r\n BYL: CommunityType.BuildOnYourLot,\r\n MFR: CommunityType.Modular,\r\n CON: CommunityType.Condo,\r\n ADU: CommunityType.Adult,\r\n THM: CommunityType.TownHome,\r\n MPC: CommunityType.MasterPlanned,\r\n CSL: CommunityType.CustomLocation,\r\n };\r\n return communityTypeMap[key] || null;\r\n }\r\n\r\n /**\r\n * Gets or creates an instance of the `CommunityType` class based on the provided key.\r\n * @param {string} key The key representing a community type.\r\n * @returns {CommunityType} The community type instance.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new CommunityType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * Creates a new instance of the `CommunityType` class.\r\n * @param {string} name The name of the community type.\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Returns the name of the community type as a string.\r\n * @returns {string} The name of the community type.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(CommunityType, 'instances', { value: {} });\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport MarketingStatus from 'enums/marketingStatus';\r\nimport CommunityType from 'enums/communityType';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\nimport { priceReducedSvgElement } from '../../constants/svgIcons';\r\nimport { ratingStarSvgElement } from '../../constants/svgIcons.b1';\r\n\r\n/**\r\n * Represents a Paid Summary Card component.\r\n */\r\nexport default class PaidCommunitySummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.IsPriceReduction = this.summaryCard?.IsPriceReduction;\r\n this.IsFeaturedListing = this.summaryCard?.IsFeaturedListing;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const callToAction = this.getCallToAction();\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'paid',\r\n callToAction,\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Sets the label for the PaidSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const callToActionButton = element.querySelector('[data-summary-card-cta]');\r\n callToActionButton?.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = element.querySelector('[data-summary-card-link]');\r\n link?.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Get the title of the summary card.\r\n * @returns {string} The title of the summary card.\r\n */\r\n getTitle() {\r\n if (this.IsPriceReduction) {\r\n return `\r\n

\r\n
\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n
\r\n ${this.getPrice()}\r\n

\r\n `;\r\n }\r\n\r\n return `

${this.getPrice()}

`;\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Returns the builder information for the summary card.\r\n * If the builder rating is available, it includes the rating and name.\r\n * Otherwise, it returns the brand name.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getBuilder() {\r\n if (this.summaryCard.BuilderRating) {\r\n return `\r\n

\r\n \r\n ${ratingStarSvgElement.cloneNode(true).outerHTML}\r\n \r\n ${\r\n this.summaryCard.BuilderRating\r\n }\r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n return `\r\n

\r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n /**\r\n * Returns the call to action based on the summary card properties.\r\n * @returns {string} The call to action text.\r\n */\r\n getCallToAction() {\r\n const { CommunityProjectType, IsLimited } = this.summaryCard;\r\n\r\n if (IsLimited) {\r\n return '';\r\n }\r\n\r\n if (this.summaryCard.CommunityType.Key === MarketingStatus.ComingSoon.toString()) {\r\n return 'Get More Information';\r\n }\r\n\r\n if (\r\n !IsLimited &&\r\n CommunityProjectType.Key !== CommunityType.CustomLocation.toString() &&\r\n CommunityProjectType.Key !== CommunityType.Custom.toString()\r\n ) {\r\n return 'Download Brochure';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the lead generator opener based on the the summary card information.\r\n * @returns {string} The lead generator opener.\r\n */\r\n getLeadGeneratorOpener() {\r\n if (this.summaryCard.CommunityType.Key === MarketingStatus.ComingSoon.toString()) {\r\n return 'more-information-paid';\r\n }\r\n\r\n return 'get-brochure-paid';\r\n }\r\n\r\n /**\r\n * Returns the call to action button HTML for the summary card.\r\n * @returns {string} The HTML string representing the call to action button.\r\n */\r\n getCallToActionButton() {\r\n const calltoAction = this.getCallToAction();\r\n const opener = this.getLeadGeneratorOpener();\r\n\r\n return calltoAction\r\n ? `\r\n \r\n `\r\n : '';\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price-low=\"${this.summaryCard.PriceLow}\"\r\n data-price-high=\"${this.summaryCard.PriceHigh}\"\r\n data-community-name=\"${this.summaryCard.Name}\"\r\n data-marketing-status=\"${this.summaryCard.MarketingStatus.Name}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-is-basic=\"false\"\r\n data-click-target=\"SRP Map Card\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n ${this.getCallToActionButton()}\r\n \r\n ${this.getTitle()}\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n

\r\n ${this.summaryCard.City}, ${this.summaryCard.StateAbbreviation}\r\n

\r\n ${this.getBuilder()}\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport MarketingStatus from 'enums/marketingStatus';\r\nimport CommunityType from 'enums/communityType';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\nimport { priceReducedSvgElement } from '../../constants/svgIcons';\r\nimport { ratingStarSvgElement } from '../../constants/svgIcons.b1';\r\n\r\n/**\r\n * Represents a Paid Summary Card component.\r\n */\r\nexport default class PaidPlanSummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.IsPriceReduction = this.summaryCard?.PriceReduced;\r\n this.IsFeaturedListing = this.summaryCard?.IsFeaturedListing;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const callToAction = this.getCallToAction();\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'paid',\r\n callToAction,\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Sets the label for the PaidPlanSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const callToActionButton = element.querySelector('[data-summary-card-cta]');\r\n callToActionButton?.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = element.querySelector('[data-summary-card-link]');\r\n link?.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = element.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Get the title of the summary card.\r\n * @returns {string} The title of the summary card.\r\n */\r\n getTitle() {\r\n if (this.IsPriceReduction) {\r\n return `\r\n

\r\n
\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n
\r\n ${this.getPrice()}\r\n

\r\n `;\r\n }\r\n\r\n return `

${this.getPrice()}

`;\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Returns the builder information for the summary card.\r\n * If the builder rating is available, it includes the rating and name.\r\n * Otherwise, it returns the brand name.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getBuilder() {\r\n if (this.summaryCard.BuilderRating) {\r\n return `\r\n

\r\n \r\n ${ratingStarSvgElement.cloneNode(true).outerHTML}\r\n \r\n\r\n ${\r\n this.summaryCard.BuilderRating\r\n }\r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n return `\r\n

\r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n /**\r\n * Returns the squarefeet information for the summary card.\r\n * If the squarefeet is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSquarefeet() {\r\n if (this.summaryCard.SquareFeet) {\r\n return `

${this.summaryCard.SquareFeet}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the bedrooms and bathrooms information for the summary card.\r\n * If the bedrooms and bathrooms is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSpecifications() {\r\n if (this.summaryCard.Bedrooms && this.summaryCard.Bathrooms) {\r\n return `

${this.summaryCard.Bedrooms} | ${this.summaryCard.Bathrooms}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the call to action based on the summary card properties.\r\n * @returns {string} The call to action text.\r\n */\r\n getCallToAction() {\r\n const { CommunityProjectType, IsLimited, CommunityStatus } = this.summaryCard;\r\n\r\n if (IsLimited) {\r\n return '';\r\n }\r\n\r\n if (CommunityStatus.Key === MarketingStatus.ComingSoon.toString()) {\r\n return 'Get More Information';\r\n }\r\n\r\n if (\r\n !IsLimited &&\r\n CommunityProjectType.Key !== CommunityType.CustomLocation.toString() &&\r\n CommunityProjectType.Key !== CommunityType.Custom.toString()\r\n ) {\r\n return 'Download Brochure';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the lead generator opener based on the the summary card information.\r\n * @returns {string} The lead generator opener.\r\n */\r\n getLeadGeneratorOpener() {\r\n if (this.summaryCard.CommunityStatus.Key === MarketingStatus.ComingSoon.toString()) {\r\n return 'more-information-paid';\r\n }\r\n\r\n return 'get-brochure-paid';\r\n }\r\n\r\n /**\r\n * Returns the call to action button HTML for the summary card.\r\n * @returns {string} The HTML string representing the call to action button.\r\n */\r\n getCallToActionButton() {\r\n const calltoAction = this.getCallToAction();\r\n const opener = this.getLeadGeneratorOpener();\r\n\r\n return calltoAction\r\n ? `\r\n \r\n `\r\n : '';\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price=\"${this.summaryCard.PriceLow}\"\r\n data-min-price=\"${this.summaryCard.PriceLow}\"\r\n data-community-id=\"${this.summaryCard.CommunityId}\"\r\n data-community-name=\"${this.summaryCard.CommunityName}\"\r\n data-community-status=\"${this.summaryCard.CommunityType}\"\r\n data-home-status=\"${this.summaryCard.StatusLabel}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-is-basic=\"false\"\r\n data-click-target=\"SRP Map Card\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n ${this.getCallToActionButton()}\r\n \r\n ${this.getTitle()}\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n ${this.getSquarefeet()}\r\n ${this.getSpecifications()}\r\n ${this.getBuilder()}\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","import getRandomLifestyleImage from 'utils/getLifestyleImage';\r\nimport { isNumber } from 'constants/regexExpressions';\r\nimport MarketingStatus from 'enums/marketingStatus';\r\nimport CommunityType from 'enums/communityType';\r\nimport createPictureImageSources from 'utils/createPictureImageSources';\r\nimport { priceReducedSvgElement } from '../../constants/svgIcons';\r\nimport { ratingStarSvgElement } from '../../constants/svgIcons.b1';\r\n\r\n/**\r\n * Represents a Paid Summary Card component.\r\n */\r\nexport default class PaidSpecSummaryCard {\r\n /**\r\n * Sets the information for the summary card.\r\n *\r\n * @param {Object} summaryCard - The summary card object.\r\n */\r\n setInformation(summaryCard) {\r\n this.summaryCard = summaryCard;\r\n this.id = 'summaryCard' + this.summaryCard.Id;\r\n this.IsPriceReduction = this.summaryCard?.PriceReduced;\r\n this.IsFeaturedListing = this.summaryCard?.IsFeaturedListing;\r\n this.CommunityProjectType = this.summaryCard.CommunityProjectType;\r\n this.errorImage = getRandomLifestyleImage();\r\n // TODO: NewHomeSource Rebrand\r\n // Change sources on backend.\r\n const { sources, src } = createPictureImageSources({\r\n url: this.summaryCard.Thumbnail ?? this.errorImage,\r\n breakpoints: {\r\n '2x': {\r\n width: 286,\r\n height: 208,\r\n },\r\n '3x': {\r\n width: 350,\r\n height: 312,\r\n },\r\n },\r\n irsParameters: {\r\n mode: 'crop',\r\n progressive: true,\r\n },\r\n });\r\n this.sources = sources;\r\n this.src = src;\r\n }\r\n\r\n /**\r\n * Emits a custom event when the CTA (Call to Action) is clicked.\r\n */\r\n emitCtaClickEvent() {\r\n const callToAction = this.getCallToAction();\r\n const element = this.getElement();\r\n const target = element.dataset.clickTarget;\r\n\r\n const callToActionClickEvent = new CustomEvent('summaryCardCtaClick', {\r\n detail: {\r\n name: 'leadGenerator',\r\n type: this.summaryCard.Type,\r\n id: this.summaryCard.Id,\r\n url: this.summaryCard.Url,\r\n marker: this.summaryCard,\r\n variation: 'paid',\r\n callToAction,\r\n target,\r\n },\r\n });\r\n\r\n document.dispatchEvent(callToActionClickEvent);\r\n }\r\n\r\n /**\r\n * Emits a custom event when a link is clicked on the summary card.\r\n */\r\n emitLinkClickEvent() {\r\n const linkClickEvent = new CustomEvent('summaryCardLinkClick', {\r\n detail: {\r\n summaryCard: this.summaryCard,\r\n },\r\n });\r\n\r\n document.dispatchEvent(linkClickEvent);\r\n }\r\n\r\n /**\r\n * Sets the label for the PaidSpecSummaryCard.\r\n * @param {string} label - The label to set.\r\n */\r\n setLabel(label) {\r\n this.label = label;\r\n }\r\n\r\n /**\r\n * Handles the error event for the image element in the summary card.\r\n * If the image fails to load, it sets the error image as the source and removes all source elements from the parent\r\n * @param {Event} event - The error event object.\r\n */\r\n handleOnErrorImage(event) {\r\n const picture = event.target.parentElement;\r\n event.target.src = this.errorImage;\r\n\r\n picture?.querySelectorAll('source').forEach((source) => source.remove());\r\n event.target.onerror = null;\r\n }\r\n\r\n /**\r\n * Binds events to the summary card.\r\n */\r\n bindEvents() {\r\n const element = this.getElement();\r\n\r\n const callToActionButton = element.querySelector('[data-summary-card-cta]');\r\n callToActionButton?.addEventListener('click', this.emitCtaClickEvent.bind(this));\r\n\r\n const link = element.querySelector('[data-summary-card-link]');\r\n link?.addEventListener('click', this.emitLinkClickEvent.bind(this));\r\n\r\n const image = element?.querySelector('img');\r\n\r\n // remove all sources and set the lifestyle error image as the src for the image\r\n // if the image fails loading.\r\n image?.addEventListener('error', this.handleOnErrorImage.bind(this));\r\n }\r\n\r\n /**\r\n * Gets the HTML element with the specified ID.\r\n * @returns {HTMLElement} The HTML anchor element.\r\n */\r\n getElement() {\r\n return document.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Get the price of the summary card.\r\n * @returns {string} The price of the summary card.\r\n */\r\n getPrice() {\r\n const price = this.summaryCard.Price;\r\n const containsNumbers = isNumber.test(price);\r\n\r\n if (containsNumbers) {\r\n return `From ${price}`;\r\n }\r\n\r\n return price;\r\n }\r\n\r\n /**\r\n * Get the title of the summary card.\r\n * @returns {string} The title of the summary card.\r\n */\r\n getTitle() {\r\n if (this.IsPriceReduction) {\r\n return `\r\n

\r\n
\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n
\r\n ${this.getPrice()}\r\n

\r\n `;\r\n }\r\n\r\n return `

${this.getPrice()}

`;\r\n }\r\n\r\n /**\r\n * Retrieves the image element for the summary card.\r\n *\r\n * @returns {string} The HTML string representing the image element.\r\n */\r\n getImage() {\r\n return `\r\n \r\n ${this.sources\r\n .map((source) => ``)\r\n .join('')}\r\n \r\n \r\n `;\r\n }\r\n\r\n /**\r\n * Returns the squarefeet information for the summary card.\r\n * If the squarefeet is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSquarefeet() {\r\n if (this.summaryCard.SquareFeet) {\r\n return `

${this.summaryCard.SquareFeet}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the bedrooms and bathrooms information for the summary card.\r\n * If the bedrooms and bathrooms is available, it includes the value.\r\n * Otherwise, it returns empty.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getSpecifications() {\r\n if (this.summaryCard.Bedrooms && this.summaryCard.Bathrooms) {\r\n return `

${this.summaryCard.Bedrooms} | ${this.summaryCard.Bathrooms}

`;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the builder information for the summary card.\r\n * If the builder rating is available, it includes the rating and name.\r\n * Otherwise, it returns the brand name.\r\n *\r\n * @returns {string} The HTML markup for the builder information.\r\n */\r\n getBuilder() {\r\n if (this.summaryCard.BuilderRating) {\r\n return `\r\n

\r\n \r\n ${ratingStarSvgElement.cloneNode(true).outerHTML}\r\n \r\n\r\n \r\n ${this.summaryCard.BuilderRating}\r\n \r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n return `\r\n

\r\n ${this.summaryCard.BrandName}\r\n

`;\r\n }\r\n\r\n /**\r\n * Returns the call to action based on the summary card properties.\r\n * @returns {string} The call to action text.\r\n */\r\n getCallToAction() {\r\n const { CommunityProjectType, IsLimited, CommunityStatus } = this.summaryCard;\r\n\r\n if (IsLimited) {\r\n return '';\r\n }\r\n\r\n if (CommunityStatus.Key === MarketingStatus.ComingSoon.toString()) {\r\n return 'Get More Information';\r\n }\r\n\r\n if (\r\n !IsLimited &&\r\n CommunityProjectType.Key !== CommunityType.CustomLocation.toString() &&\r\n CommunityProjectType.Key !== CommunityType.Custom.toString()\r\n ) {\r\n return 'Download Brochure';\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the lead generator opener based on the the summary card information.\r\n * @returns {string} The lead generator opener.\r\n */\r\n getLeadGeneratorOpener() {\r\n if (this.summaryCard.CommunityStatus === MarketingStatus.ComingSoon.toString()) {\r\n return 'more-information-paid';\r\n }\r\n\r\n return 'get-brochure-paid';\r\n }\r\n\r\n /**\r\n * Returns the call to action button HTML for the summary card.\r\n * @returns {string} The HTML string representing the call to action button.\r\n */\r\n getCallToActionButton() {\r\n const calltoAction = this.getCallToAction();\r\n const opener = this.getLeadGeneratorOpener();\r\n\r\n return calltoAction\r\n ? `\r\n \r\n `\r\n : '';\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of the summary card.\r\n * @returns {string} The HTML string representing the summary card.\r\n */\r\n getHtml() {\r\n return `\r\n
0}\"\r\n data-price=\"${this.summaryCard.PriceLow}\"\r\n data-min-price=\"${this.summaryCard.PriceLow}\"\r\n data-community-id=\"${this.summaryCard.CommunityId}\"\r\n data-community-name=\"${this.summaryCard.CommunityName}\"\r\n data-community-status=\"${this.summaryCard.CommunityType}\"\r\n data-home-status=\"${this.summaryCard.StatusLabel}\"\r\n data-price-reduction-label=\"${this.summaryCard.PriceReductionLabel}\"\r\n data-has-limited-information=\"${this.summaryCard.IsLimited}\"\r\n data-is-basic=\"false\"\r\n data-click-target=\"SRP Map Card\"\r\n data-zip-code=\"${this.summaryCard.Zip}\"\r\n data-builder-id=\"${this.summaryCard.BuilderId}\"\r\n data-market-name=\"${this.summaryCard.MarketName}\"\r\n data-state-abbreviation=\"${this.summaryCard.StateAbbreviation}\"\r\n data-state-name=\"${this.summaryCard.StateName}\"\r\n >\r\n ${this.label.getHtml()}\r\n ${this.getImage()}\r\n ${this.getCallToActionButton()}\r\n \r\n ${this.getTitle()}\r\n

\r\n ${this.summaryCard.Name}\r\n

\r\n ${this.getSquarefeet()}\r\n ${this.getSpecifications()}\r\n ${this.getBuilder()}\r\n
\r\n
\r\n `;\r\n }\r\n}\r\n","import MarkerType from \"../enums/markerType\";\r\nimport BasicCommunitySummaryCard from '../components/summaryCard/basicCommunityCard';\r\nimport BasicPlanSummaryCard from '../components/summaryCard/basicPlanCard';\r\nimport BasicSpecSummaryCard from '../components/summaryCard/basicSpecCard';\r\nimport PaidCommunitySummaryCard from '../components/summaryCard/paidCommunityCard';\r\nimport PaidPlanSummaryCard from '../components/summaryCard/paidPlanCard';\r\nimport PaidSpecSummaryCard from '../components/summaryCard/paidSpecCard';\r\nimport CommunityLabel from '../components/summaryCard/communityLabel';\r\nimport HomeLabel from '../components/summaryCard/homeLabel';\r\n\r\n/**\r\n * Returns a summary card based on the provided data.\r\n * @param {Object} data - The data object containing information about the card.\r\n * @returns {Object} - The summary card object.\r\n */\r\nfunction getCardInstance(data) {\r\n switch (data.Type) {\r\n case MarkerType.HousingDevelopment.toString():\r\n return data.IsBasic ? new BasicCommunitySummaryCard() : new PaidCommunitySummaryCard();\r\n case MarkerType.PlanUnit.toString():\r\n return data.IsBasic ? new BasicPlanSummaryCard() : new PaidPlanSummaryCard();\r\n case MarkerType.SpecUnit.toString():\r\n return data.IsBasic ? new BasicSpecSummaryCard() : new PaidSpecSummaryCard();\r\n default:\r\n return new PaidCommunitySummaryCard();\r\n }\r\n}\r\n\r\n/**\r\n * Retrieves the label for a summary card.\r\n * @param {Object} summaryCard - The summary card object.\r\n * @returns {Object} - The label object.\r\n */\r\nfunction getLabel(summaryCard) {\r\n let label;\r\n\r\n if (summaryCard.Type === MarkerType.HousingDevelopment.toString()) {\r\n label = new CommunityLabel();\r\n label.setInformation(summaryCard);\r\n } else {\r\n label = new HomeLabel();\r\n label.setInformation(summaryCard);\r\n }\r\n\r\n return label;\r\n}\r\n\r\n/**\r\n * Retrieves a summary card based on the given data.\r\n * \r\n * @param {Object} data - The data used to generate the summary card.\r\n * @returns The generated summary card.\r\n */\r\nconst getCard = (data) => {\r\n const card = getCardInstance(data);\r\n const label = getLabel(data);\r\n card.setInformation(data);\r\n card.setLabel(label);\r\n\r\n return card;\r\n}\r\n\r\nexport default getCard;\r\n\r\n\r\n/**\r\n * Combines and sorts a list of listings (plans and specs) based on a provided order.\r\n * @param {Object[]} listings - An object containing arrays of plans and specs.\r\n * @param {string} order - A comma-separated string of IDs representing the desired order.\r\n * @returns {Object[]} - The combined and sorted array of listings.\r\n */\r\nexport const combineAndSortListings = (listings, sortOrder) => {\r\n // Merge plans and specs into a single array\r\n const combinedListings = [...listings.plans, ...listings.specs];\r\n\r\n // Create an array of IDs based on the sort order\r\n const sortedIds = sortOrder.split(',');\r\n // Iterate over the order list and get the corresponding item from combined listings\r\n const sortedListings = combinedListings.sort((a, b) => {\r\n const aIndex = sortedIds.indexOf(a.Id.toString());\r\n const bIndex = sortedIds.indexOf(b.Id.toString());\r\n return aIndex - bIndex;\r\n });\r\n\r\n return sortedListings;\r\n}\r\n","/**\r\n * getEncodedImage function will request an image provided as an argument, and return\r\n * the base 64 representation of that image.\r\n * @param {string} imageUrl representing the resource we want to transform to base 64.\r\n * @returns a base 64 string for an image resource.\r\n */\r\nconst getEncodedImage = (imageUrl) => new Promise((resolve) => {\r\n fetch(imageUrl)\r\n .then(response => {\r\n if (!response.ok) {\r\n return null;\r\n }\r\n \r\n return response.blob();\r\n })\r\n .then(blob => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => {\r\n resolve(reader.result);\r\n };\r\n reader.onerror = () => {\r\n resolve(null);\r\n };\r\n reader.readAsDataURL(blob);\r\n })\r\n .catch(() => {\r\n resolve(null);\r\n });\r\n});\r\n\r\nexport default getEncodedImage;","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { searchCommunitySitePlans } from 'constants/routes'\r\n\r\n/**\r\n * Retrieves community site plans associated to a given community id.\r\n * @param {Object} payload - The payload containing the list of community ids.\r\n * @returns {Observable} - An observable that emits the community site plans information.\r\n */\r\nfunction searchCommunitySitePlansInformation(payload) {\r\n return fromFetch(searchCommunitySitePlans, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n body: JSON.stringify(payload.communityIds),\r\n }).pipe(\r\n switchMap((response) => response.json())\r\n );\r\n}\r\n\r\nexport default searchCommunitySitePlansInformation;","import { interactiveSitePlanSvg } from 'constants/svg-assets';\r\nimport { priceReducedSvgElement } from '../constants/svgIcons';\r\n\r\nexport default class SitePlanTooltip {\r\n /**\r\n * setInformation function is in charge of fill the information needed to build the site plan tooltip.\r\n * @param {Object} information related to the community where the site plan belongs.\r\n * @param {Boolean} hasInteractiveSitePlan indicates if the site plan is interactive or not.\r\n */\r\n setInformation(information, hasInteractiveSitePlan) {\r\n this.hasInteractiveSitePlan = hasInteractiveSitePlan;\r\n this.sitePlanCenterLatitude = information.SitePlanCenterLatitude;\r\n this.sitePlanCenterLongitude = information.SitePlanCenterLongitude;\r\n this.communityId = information.Id;\r\n this.priceText = SitePlanTooltip.getPriceText(information.Price);\r\n this.title = information.Name;\r\n this.detailText = SitePlanTooltip.getDetailText(information.FormattedBedrooms, information.FormattedBathrooms);\r\n this.priceReducedText = SitePlanTooltip.getPriceReducedText(information.PriceReduced);\r\n }\r\n\r\n /**\r\n * getDetailText: retrieves information about bathrooms and bedrooms facts.\r\n * @param {string} formattedBedrooms of the community.\r\n * @param {string} formattedBathrooms of the community.\r\n * @returns a string indicating bathrooms and bedrooms of the community where the site plan belongs.\r\n */\r\n static getDetailText(formattedBedrooms, formattedBathrooms) {\r\n const detailText =\r\n (formattedBedrooms ? `${formattedBedrooms} Bed` : '') +\r\n (formattedBedrooms && formattedBathrooms ? ' / ' : '') +\r\n (formattedBathrooms ? `${formattedBathrooms} Ba` : '');\r\n\r\n return detailText;\r\n }\r\n\r\n /**\r\n * getPriceReducedText: returns a string indicating the price reduction text for the community.\r\n * @param {decimal} priceReduced is the price reduction.\r\n * @returns a string representing the price reduction community text.\r\n */\r\n static getPriceReducedText(priceReduced) {\r\n return priceReduced\r\n ? `Up to ${priceReduced}` \r\n : null;\r\n }\r\n\r\n /**\r\n * getPriceText functino will return the community price.\r\n * @param {decimal} price of the community.\r\n * @returns a string representing the community price.\r\n */\r\n static getPriceText(price) {\r\n return price ? `From ${price}+` : '';\r\n }\r\n\r\n /**\r\n * getInteractiveSitePlanSection: adds a button with the information needed to reach\r\n * the interactive site plan.\r\n */\r\n getInteractiveSitePlanSection() {\r\n if (!this.hasInteractiveSitePlan) {\r\n return '';\r\n }\r\n\r\n return `\r\n ${interactiveSitePlanSvg} Interactive Map\r\n `;\r\n }\r\n\r\n /**\r\n * getCardElement returns The HTML for the card element to be associated to\r\n * the community where the site plan belongs.\r\n */\r\n getCardElement() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.setAttribute('hidden', '');\r\n hoverCard.classList.add('nhs-c-tooltip--map', 'site-plan_tooltip');\r\n hoverCard.dataset.id = this.communityId;\r\n hoverCard.dataset.tooltip = true;\r\n\r\n hoverCard.innerHTML = `\r\n

${this.priceText}

\r\n

${this.title}

\r\n

${this.detailText}

\r\n ${this.getInteractiveSitePlanSection()}`;\r\n\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * getCardElementWithPriceReduction: returns the HTML for the card element to be associated to\r\n * the community site plan.\r\n */\r\n getCardElementWithPriceReduction() {\r\n const hoverCard = document.createElement('div');\r\n hoverCard.setAttribute('hidden', '');\r\n hoverCard.classList.add('nhs-c-tooltip--map', 'site-plan_tooltip');\r\n hoverCard.dataset.id = this.communityId;\r\n hoverCard.dataset.tooltip = true;\r\n\r\n hoverCard.innerHTML = `\r\n

${this.priceText}

\r\n

${this.title}

\r\n

\r\n ${priceReducedSvgElement.cloneNode(true).outerHTML}\r\n ${this.priceReducedText}\r\n

\r\n

${this.detailText}

\r\n ${this.getInteractiveSitePlanSection()}`;\r\n\r\n return hoverCard;\r\n }\r\n\r\n /**\r\n * getCard: returns the tooltip html.\r\n */\r\n getCard() {\r\n if (this.priceReducedText) {\r\n return this.getCardElementWithPriceReduction();\r\n }\r\n\r\n return this.getCardElement();\r\n }\r\n}\r\n","/**\r\n * This service is responsible for preparing the DOM elements required for rendering a Community Site Plan \r\n * in the Search Results map. It handles tasks such as creating containers for the Community Site Plan, \r\n * transforming its image into base64 format, and preparing tooltips for hover events on the Community Site Plan, \r\n * among other functionalities expected from this service.\r\n */\r\nimport {\r\n buffer,\r\n catchError,\r\n debounceTime,\r\n filter,\r\n firstValueFrom,\r\n fromEvent,\r\n of,\r\n switchMap,\r\n take,\r\n withLatestFrom\r\n} from 'rxjs';\r\nimport { store } from '@redux/store';\r\nimport getEncodedImage from 'utils/base64Transformations';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport { selectLayoutBreakpoint } from 'layout/redux/selectors';\r\nimport {\r\n isSitePlanInViewport,\r\n setZoomLevel,\r\n toggleDoubleClickZoom,\r\n updateMapCenter\r\n} from 'libraries/mapLibrary';\r\nimport fastdom from 'fastdom';\r\nimport searchSitePlansInformation$ from '../apis/searchCommunitySitePlans';\r\nimport {\r\n mapStateSlice,\r\n interactiveSitePlanSlice\r\n} from '../redux/slices';\r\nimport {\r\n mapMarkers,\r\n selectSitePlans,\r\n selectZoomLevel\r\n} from '../redux/selectors';\r\nimport LotPolygonType from '../enums/lotPolygonType';\r\nimport { mapClicked$, mapDragStart$ } from '../redux/observables';\r\nimport { zoomLevelLayersLookup, zoomLevelTriggers } from '../constants/sitePlansConstants';\r\nimport SitePlanLayer from '../enums/sitePlanLayer';\r\nimport SitePlanTooltip from '../models/sitePlanTooltip';\r\nimport getCommunitySummaryCardInformation from '../apis/getCommunitySummaryCard';\r\n\r\nconst actions = {\r\n ...mapStateSlice.actions,\r\n ...interactiveSitePlanSlice.actions,\r\n};\r\n\r\nconst map = document.getElementById('nhs_map');\r\n\r\n/**\r\n * getSitePlan: will retrieve a given community site plan from store.\r\n * @param {int} sitePlanId identifier of the site plan.\r\n * @param {int} communityId identifier of the community where site plan belongs.\r\n * @returns a community site plan.\r\n */\r\nexport const getSitePlan = ({ sitePlanId, communityId }) => {\r\n const sitePlans = selectSitePlans(store.getState());\r\n const sitePlanInformation = sitePlanId\r\n ? sitePlans.find((sitePlan) => sitePlan.sitePlanId === sitePlanId)\r\n : sitePlans.find((sitePlan) => sitePlan.communityId === communityId)\r\n\r\n const isInInteractiveState =\r\n selectZoomLevel(store.getState()) >= zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger;\r\n\r\n return {\r\n sitePlanInformation,\r\n isInInteractiveState,\r\n };\r\n}\r\n\r\n/**\r\n * Maps LayoutBreakpoints to a more event tracking friendly term.\r\n */\r\nconst sizeDeviceMap = new Map([\r\n [ LayoutBreakpoint.Small.toString(), 'Mobile'],\r\n [ LayoutBreakpoint.Medium.toString(), 'Tablet'],\r\n [ LayoutBreakpoint.Big.toString(), 'Desktop']\r\n ]);\r\n\r\n/**\r\n * getDeviceType returns an string for event tracking purposes\r\n * indicating the device where the event was triggered.\r\n * @returns a string from the sizeDeviceMap map structure.\r\n */\r\nexport const getDeviceType = () => {\r\n const state = store.getState();\r\n const layoutBreakpoint = selectLayoutBreakpoint(state);\r\n return sizeDeviceMap.get(layoutBreakpoint.text);\r\n}\r\n\r\n/**\r\n * getDetailUrl returns a string that is the url to the detail page of the community\r\n * @param {Object} marker with the information to build the detail page url.\r\n * @returns The string `/communitydetail/community-${this.communityId}` \r\n */\r\nconst getDetailUrl = (marker) => marker.builderId\r\n ? `/communitydetail/builder-${marker.builderId}/community-${marker.communityId}`\r\n : `/communitydetail/community-${marker.communityId}`\r\n\r\n/**\r\n * getActiveMarker function will find a marker in the store by ID and return it.\r\n * @param {int} mapId is the marker identifier.\r\n * @returns a marker object from store.\r\n */\r\nconst getActiveMarker = (mapId) => {\r\n const state = store.getState();\r\n const markers = mapMarkers(state);\r\n const marker = markers.find((element) => element.communityId === mapId);\r\n const communityMarker = Object.assign({}, marker);\r\n communityMarker.markerPosition = {\r\n lat: +marker.latitude,\r\n lng: +marker.longitude,\r\n };\r\n return communityMarker;\r\n}\r\n\r\n/**\r\n * setActiveMarker function will activate a marker in the map slice.\r\n * @param {Object} marker to be markerd as selected.\r\n */\r\nconst setActiveMarker = (marker) => {\r\n store.dispatch(actions.selectedMarker(marker));\r\n};\r\n\r\n/**\r\n * getInteractiveOverlay function adds an SVG with that outlines the community area. It is useful for mouse over\r\n * site plan interactions, as it allows us to determine if the mouse is hovering the right place of the SVG in\r\n * order to show the site plan tooltip to the user.\r\n * @param {Object} sitePlanConfiguration contains information like rotation degrees for the site plan,\r\n * its hight and width, the url to fetch with the actual image of the site plan. among others.\r\n */\r\nexport const getInteractiveOverlay = (sitePlanConfiguration) => {\r\n const rotationCenterX = sitePlanConfiguration.viewboxWidth / 2;\r\n const rotationCenterY = sitePlanConfiguration.viewboxHeight / 2;\r\n const svgContent =\r\n `\r\n \r\n ${sitePlanConfiguration.svgMask}\r\n \r\n `;\r\n\r\n const overlayElement = document.createElement(\"div\");\r\n overlayElement.classList.add('site-plan_overlay');\r\n overlayElement.id = sitePlanConfiguration.communityId;\r\n overlayElement.dataset.communityId = sitePlanConfiguration.communityId;\r\n overlayElement.dataset.sitePlanId = sitePlanConfiguration.sitePlanId;\r\n overlayElement.dataset.communityMapInteractive = true;\r\n overlayElement.dataset.url = sitePlanConfiguration.imageUrl;\r\n overlayElement.dataset.isInteractiveSitePlan = sitePlanConfiguration.isInteractiveSitePlan;\r\n overlayElement.innerHTML = svgContent;\r\n\r\n return overlayElement;\r\n};\r\n\r\n/**\r\n * \r\n * @param {Object} sitePlanConfiguration contains information like rotation degrees for the site plan,\r\n * its hight and width, the url to fetch with the actual image of the site plan. among others.\r\n * @param {string} base64image representing the map's url in a format usefull for rendering an img node in map.\r\n * @returns a string representing the SVG with the content of the site plan.\r\n */\r\nconst getSvgContent = (sitePlanConfiguration, base64image) =>\r\n `\r\n ${sitePlanConfiguration.svgMask}\r\n \r\n \r\n \r\n \r\n `\r\n\r\n/**\r\n * Determines whether a point within an SVG falls inside the community area of a site plan. \r\n * This function is essential for handling user interactions on interactive maps, ensuring \r\n * accurate detection even when transformations (such as rotations) are applied.\r\n * \r\n * @param {HTMLElement} siteplanSvg - The SVG element representing the site plan.\r\n * @param {HTMLElement} pathElement - The `` element outlining the community area within the SVG.\r\n * @param {Event} event - The mouseover event containing the X and Y coordinates of the cursor.\r\n * \r\n * ### Important Notes for iOS:\r\n * - The `getScreenCTM` method does **not** propagate transformations from parent elements \r\n * to their children, as documented in MDN:\r\n * https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement/getScreenCTM\r\n * - To address this, a `` (group) element is used to contain the overlay mask, ensuring \r\n * that rotations are properly interpreted.\r\n * - Previously, this limitation caused issues (e.g., NHS20-4527), where site plans with \r\n * rotations were non-interactive on iOS devices because this function incorrectly returned `false`.\r\n * \r\n * ### Rotation Handling:\r\n * - The **rotation must remain at the overlay SVG level**, as user interactions occur on this element.\r\n * - However, when determining whether the interaction is within the overlay mask, \r\n * **only the `` rotation should be considered**.\r\n * - The **SVG rotation is temporarily ignored** during this evaluation to ensure correct results.\r\n * \r\n * @returns {boolean} `true` if the mouse is hovering over the visible portion of the site plan, otherwise `false`.\r\n */\r\nconst isMouseOnSitePlan = (siteplanSvg, pathElement, event) => {\r\n const point = siteplanSvg.createSVGPoint();\r\n point.x = event.clientX;\r\n point.y = event.clientY;\r\n\r\n const parentGroup = pathElement.closest(\"g\");\r\n const transformMatrix = parentGroup.getScreenCTM().inverse();\r\n const transformedPoint = point.matrixTransform(transformMatrix);\r\n\r\n return pathElement.isPointInFill(transformedPoint);\r\n}\r\n\r\n/**\r\n * getLotPathFromCoordinates will return the lot that receivid a click or tap in an Interactive Site Plan\r\n * @param {event} event containing information like X and Y coordinates of the click event.\r\n * @param {Int} sitePlanId is the site plan identifier. \r\n * @returns \r\n */\r\nconst getLotPathFromCoordinates = (event, sitePlanId) => {\r\n const sitePlan = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n const svg = sitePlan?.querySelector(`svg`);\r\n const hitElements = document.elementsFromPoint(event.clientX, event.clientY);\r\n\r\n return hitElements.find((element) => {\r\n const idMatch = element.id?.match(/^g\\d+_l\\d+$/);\r\n return idMatch && svg?.contains(element);\r\n });\r\n};\r\n\r\n/**\r\n * getInteractiveMap function returns information related with the interactive svg associated with an event the\r\n * user is triggering, like clicking, mousemove, dbclick.\r\n * @param {Event} event - The mouse event containing the X and Y coordinates of the current mouse cursor position.\r\n * @returns an interaction object containing a flag indicating whether the interaction was in the outlined area of the\r\n * site plan, and the actual site plan that received the interaction.\r\n */\r\nconst getInteractiveMap = (event) => {\r\n const mapOverlays = document.querySelectorAll(`[data-community-map-interactive] svg`);\r\n const candidate = {\r\n isMouseMovingOnMap: false,\r\n interactiveMap: null\r\n }\r\n\r\n mapOverlays.forEach((mapOverlay) => {\r\n const originalTransform = mapOverlay.style.transform;\r\n mapOverlay.style.removeProperty(\"transform\");\r\n const paths = mapOverlay.querySelectorAll('path');\r\n \r\n paths.forEach((pathElement) => {\r\n if (isMouseOnSitePlan(mapOverlay, pathElement, event)) {\r\n candidate.isMouseMovingOnMap = true;\r\n candidate.interactiveMap = mapOverlay;\r\n candidate.communityId = +mapOverlay.parentElement.dataset.communityId;\r\n candidate.sitePlanId = +mapOverlay.parentElement.dataset.sitePlanId;\r\n candidate.isInteractive = mapOverlay.parentElement.dataset.isInteractiveSitePlan === \"true\";\r\n\r\n if (candidate.isInteractive) {\r\n candidate.interestedLotPath = getLotPathFromCoordinates(event, candidate.sitePlanId);\r\n }\r\n }\r\n });\r\n\r\n mapOverlay.style.transform = originalTransform;\r\n });\r\n\r\n return candidate;\r\n};\r\n\r\n/**\r\n * isUserInteractingWithSitePlan function will tell any caller control if the event\r\n * triggered was on a site plan outlined section.\r\n * @param {Event} event - The mouse event containing the X and Y coordinates of the current mouse cursor position.\r\n * @returns a flag indicating whether the event interaction was on a site plan.\r\n */\r\nexport const isUserInteractingWithSitePlan = (event) => {\r\n const { isMouseMovingOnMap } = getInteractiveMap(event);\r\n return isMouseMovingOnMap;\r\n}\r\n\r\n/**\r\n * hideSitePlansTooltips hides all of the site plan tooltips\r\n * and return them to their original position in case they were hovered causing\r\n * its coordinates to change after their original positioning.\r\n */\r\nexport const hideSitePlansTooltips = (sitePlanId) => {\r\n const tooltipsToHide = Array.from(document.querySelectorAll(`[data-site-plan-tooltip-id]`))\r\n .filter(tooltip => +tooltip.dataset.sitePlanTooltipId !== sitePlanId);\r\n\r\n tooltipsToHide.forEach(tooltip => {\r\n tooltip.setAttribute('hidden', '');\r\n tooltip.parentElement.classList.add(\"site-plan-tooltip_container\");\r\n tooltip.style.left = tooltip.dataset.left;\r\n tooltip.style.top = tooltip.dataset.top;\r\n });\r\n}\r\n\r\n/**\r\n * removeActiveSitePlans function will remove active class from site plans.\r\n */\r\nexport const removeActiveSitePlans = (id) => {\r\n const activeMaps = Array.from(document.querySelectorAll(`[data-community-map-wrapper-id]`))\r\n .filter(activeMap => +activeMap.dataset.communityMapWrapperId !== id);\r\n\r\n activeMaps.forEach(activeMap => {\r\n activeMap.classList.remove('site-plan_image-active');\r\n });\r\n}\r\n\r\n/**\r\n * onMouseLeaveSitePlan will remove any active tooltip or style\r\n * on site plans rendered.\r\n */\r\nconst onMouseLeaveSitePlan = (event) => {\r\n const { isMouseMovingOnMap } = getInteractiveMap(event);\r\n if (!isMouseMovingOnMap) {\r\n hideSitePlansTooltips();\r\n removeActiveSitePlans();\r\n }\r\n}\r\n\r\n/**\r\n * onMouseHoveringInteractiveSitePlan function is in charge of mouse moving on top of static site plans.\r\n * @param {Object} mouseMoveInformation contains the metadata needed to handle the mouse move event.\r\n */\r\nconst onMouseHoveringInteractiveSitePlan = (mouseMoveInformation) => {\r\n const {\r\n tooltip,\r\n isInInteractiveState,\r\n interestedLotPath,\r\n sitePlanInformation,\r\n communityId,\r\n } = mouseMoveInformation;\r\n\r\n if (!isInInteractiveState && tooltip) {\r\n tooltip.removeAttribute('hidden');\r\n const mapContainer = document.querySelector(`[data-community-map-wrapper-id=\"${communityId}\"]:not(.site-plan_image-active)`);\r\n mapContainer?.classList.add('site-plan_image-active');\r\n\r\n return;\r\n }\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('hoveredLot', {\r\n detail: {\r\n interestedLotPath,\r\n sitePlanId: sitePlanInformation.sitePlanId,\r\n polygonId: interestedLotPath?.id\r\n },\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * onMouseHoveringStaticSitePlan function is in charge of mouse moving on top of interactive site plans.\r\n * @param {Object} mouseMoveInformation contains the metadata needed to handle the mouse move event.\r\n */\r\nconst onMouseHoveringStaticSitePlan = (mouseMoveInformation) => {\r\n const {\r\n tooltip,\r\n event,\r\n communityId,\r\n } = mouseMoveInformation;\r\n\r\n if (tooltip) {\r\n tooltip.removeAttribute('hidden');\r\n }\r\n\r\n fastdom.measure(() => {\r\n const mapRect = map.getBoundingClientRect();\r\n const mouseX = event.clientX - mapRect.left;\r\n const mouseY = event.clientY - mapRect.top;\r\n const mapOffsetTop = map.closest('[data-search-results-content]')?.offsetTop;\r\n\r\n if (tooltip) {\r\n tooltip.style.left = `${mouseX}px`;\r\n tooltip.style.top = `${mouseY - mapOffsetTop}px`;\r\n tooltip.parentElement.classList.remove(\"site-plan-tooltip_container\");\r\n }\r\n });\r\n\r\n const mapContainer = document.querySelector(`[data-community-map-wrapper-id=\"${communityId}\"]:not(.site-plan_image-active)`);\r\n mapContainer?.classList.add('site-plan_image-active');\r\n}\r\n\r\n/**\r\n * onMouseMoveSitePlan function will find all of the needed information for toggling the site plan\r\n * tooltip.\r\n * @param {Event} event is the mousemove event dispatched by the user's mouse.\r\n */\r\nconst onMouseMoveSitePlan = (event) => {\r\n /**\r\n * If the user is clicking while mousing move, it means she/he is dragging the map around, not hovering it.\r\n * For these scenarios we are not displaying the tooptip as it is meant just for hovering.\r\n */\r\n if (event.buttons > 0) {\r\n return;\r\n }\r\n\r\n const { isMouseMovingOnMap, communityId, sitePlanId, name, interestedLotPath } = getInteractiveMap(event);\r\n const { isInInteractiveState, sitePlanInformation } = getSitePlan({ sitePlanId });\r\n\r\n const tooltip =\r\n document.querySelector(`[data-site-plan-tooltip-id=\"${sitePlanId}\"]`) ||\r\n document.querySelector(`[data-community-map-tooltip-id=\"${communityId}\"]`);\r\n\r\n const mouseMoveInformation = {\r\n tooltip,\r\n isInInteractiveState,\r\n sitePlanInformation,\r\n isMouseMovingOnMap,\r\n communityId,\r\n sitePlanId,\r\n event,\r\n interestedLotPath,\r\n };\r\n\r\n if (!isMouseMovingOnMap) {\r\n document.body.dispatchEvent(\r\n new CustomEvent('hoveredLot', {\r\n detail: { interestedLotPath: null, sitePlanId: null, polygonId: null },\r\n })\r\n );\r\n } else {\r\n const onMouseHoverFunction = sitePlanInformation?.isInteractiveSitePlan\r\n ? onMouseHoveringInteractiveSitePlan\r\n : onMouseHoveringStaticSitePlan;\r\n \r\n onMouseHoverFunction(mouseMoveInformation);\r\n }\r\n\r\n hideSitePlansTooltips(isMouseMovingOnMap ? sitePlanId : null);\r\n removeActiveSitePlans(isMouseMovingOnMap ? communityId : null);\r\n\r\n const communityMap = {\r\n id: communityId,\r\n name,\r\n }\r\n\r\n toggleDoubleClickZoom(isMouseMovingOnMap);\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapMouseOver', {\r\n detail: {\r\n communityMap,\r\n isMouseMovingOnMap,\r\n deviceType: getDeviceType(),\r\n },\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * openUrl function open a marker url.\r\n * @param {Object} marker from store with the information to open an url.\r\n */\r\nconst openUrl = (marker) => {\r\n window.open(getDetailUrl(marker), '_blank');\r\n};\r\n\r\n/**\r\n * isMarkerActive function checks if a given marker is set as selected marker in store.\r\n * @param {Object} marker to check if is active.\r\n * @returns a flag indicating whether a marker is active or not.\r\n */\r\nconst isMarkerActive = (marker) => {\r\n const mapState = store?.getState()?.mapState;\r\n return marker.communityId === mapState?.selectedMarker?.communityId;\r\n };\r\n\r\n/**\r\n * Handles a double click event on a map marker element.\r\n * @param {Event} event - The double click event object.\r\n */\r\nconst onDoubleClickSitePlan = (data) => {\r\n const [[event]] = data;\r\n const {\r\n isMouseMovingOnMap,\r\n communityId,\r\n isInteractive,\r\n } = getInteractiveMap(event);\r\n\r\n if (isInteractive) {\r\n return;\r\n }\r\n\r\n if (isMouseMovingOnMap) {\r\n const activeMarker = getActiveMarker(communityId);\r\n setActiveMarker(activeMarker);\r\n openUrl(activeMarker);\r\n\r\n const tooltip = document.querySelector(`[data-community-map-tooltip-id=\"${communityId}\"]`);\r\n tooltip.setAttribute('hidden', '');\r\n\r\n const communityMap = {\r\n id: activeMarker.communityId,\r\n name: activeMarker.title,\r\n url: getDetailUrl(activeMarker),\r\n }\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapDoubleCLicked', {\r\n detail: {\r\n communityMap,\r\n deviceType: getDeviceType(),\r\n },\r\n })\r\n );\r\n }\r\n}\r\n\r\n/**\r\n \r\n * onClickCommunityInteractiveMap: will handle the logic needed after\r\n * clicking on a community interactive map.\r\n * @param {Object} sitePlanInformation from the store.\r\n */\r\nconst onClickCommunityInteractiveMap = (sitePlan, event, latLng) => {\r\n const { sitePlanInformation, isInInteractiveState } = sitePlan;\r\n\r\n if (isInInteractiveState) {\r\n const lotPath = getLotPathFromCoordinates(event, sitePlanInformation.sitePlanId);\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('lotClicked', {\r\n detail: {\r\n lotPath,\r\n communityId: sitePlanInformation.communityId,\r\n },\r\n })\r\n );\r\n\r\n return;\r\n }\r\n\r\n updateMapCenter({ latitude: latLng.lat(), longitude: latLng.lng() });\r\n setZoomLevel(zoomLevelTriggers.zoomLevelEnterInteractiveStateTrigger);\r\n}\r\n\r\n/**\r\n * onClickCommunityStaticMap: will handle the logic needed after\r\n * clicking on a site plan.\r\n * @param {int} communityId identifier of the site plan.\r\n */\r\nconst onClickCommunityStaticMap = (communityId) => {\r\n const activeMarker = getActiveMarker(communityId);\r\n\r\n if (isMarkerActive(activeMarker)) {\r\n openUrl(activeMarker);\r\n\r\n const tooltip = document.querySelector(`[data-community-map-tooltip-id=\"${communityId}\"]`);\r\n tooltip.setAttribute('hidden', '');\r\n }\r\n\r\n setActiveMarker(activeMarker);\r\n\r\n const communityMap = {\r\n id: activeMarker.communityId,\r\n name: activeMarker.title,\r\n }\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapCLicked', {\r\n detail: {\r\n communityMap,\r\n deviceType: getDeviceType(),\r\n },\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * onClickSitePlan: will execute the callback associated with the community clicked.\r\n * @param {Event} event is the click event dispatched.\r\n */\r\nconst onClickSitePlan = (data) => {\r\n const [[event], { detail: { latLng } }] = data;\r\n\r\n const { isMouseMovingOnMap, communityId, sitePlanId } = getInteractiveMap(event);\r\n\r\n if (isMouseMovingOnMap) {\r\n const sitePlan = getSitePlan({ sitePlanId });\r\n\r\n if (sitePlan.sitePlanInformation.isInteractiveSitePlan) {\r\n onClickCommunityInteractiveMap(sitePlan, event, latLng);\r\n } else {\r\n onClickCommunityStaticMap(communityId);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * getSitePlanWrapper function will try to find a main wrapper for the N site plans of a community.\r\n * If it exists, the function will return it, otherwise it will create and append one to the map container before\r\n * returning it.\r\n * @param {int} communityId is the identifier of the wrapper container.\r\n * @returns a DOM element representing the main container of the N site plans for a given community id.\r\n */\r\nconst getSitePlanWrapper = ({ communityId, isInteractiveSitePlan }) => {\r\n const mapWrapper = document.querySelector(`[data-community-map-wrapper-id=\"${communityId}\"]`);\r\n if (mapWrapper) {\r\n return mapWrapper;\r\n }\r\n\r\n const newMapWrapper = document.createElement('div');\r\n newMapWrapper.classList.add('site-plan-wrapper_container');\r\n newMapWrapper.dataset.communityMapWrapperId = communityId;\r\n newMapWrapper.dataset.isInteractiveCommunity = isInteractiveSitePlan;\r\n newMapWrapper.classList.add(isInteractiveSitePlan ? \"interactive\" : \"static\");\r\n\r\n const polygonsContainer = document.createElement('div');\r\n polygonsContainer.dataset.polygonsContainerCommunityId = communityId;\r\n\r\n newMapWrapper.appendChild(polygonsContainer);\r\n map.appendChild(newMapWrapper);\r\n\r\n return newMapWrapper;\r\n}\r\n\r\n/**\r\n * appendSitePlanContainerToMainWrapper: will add the site plan container in sorted way inside\r\n * the main site plan wrapper. The sorting is important as overlapping could happen in the final\r\n * output and pieces of the site plan can become invisible due to other posicioned on top of them.\r\n */\r\nconst appendSitePlanContainerToMainWrapper = (sitePlanContainer, mainSitePlanWrapper, sitePlanConfiguration) => {\r\n const { rotationDegrees, sitePlanId, communityId } = sitePlanConfiguration;\r\n const polygonsSvgNode = sitePlanContainer.querySelector('#lot_polygons')?.closest('svg');\r\n const mainPolygonsContainer = document.querySelector(`[data-polygons-container-community-id=\"${communityId}\"]`);\r\n\r\n const polygonsContainer = document.createElement('div');\r\n polygonsContainer.className = 'site-plan-polygons_container';\r\n polygonsContainer.style.transform = `rotate(${rotationDegrees}deg)`;\r\n polygonsContainer.dataset.polygonContainerId = sitePlanId;\r\n\r\n polygonsContainer.appendChild(polygonsSvgNode);\r\n mainPolygonsContainer.appendChild(polygonsContainer);\r\n mainSitePlanWrapper.appendChild(sitePlanContainer);\r\n};\r\n\r\n/**\r\n * getCommunityStaticMapContainer function will create the HTML container for the site plan.\r\n * @param {Object} sitePlanConfiguration contains information like rotation degrees for the site plan,\r\n * its hight and width, the url to fetch with the actual image of the site plan. among others.\r\n * @returns the HTML container for the site plan.\r\n */\r\nexport const getCommunityStaticMapContainer = async (sitePlanConfiguration) => {\r\n const base64image = await getEncodedImage(sitePlanConfiguration.imageUrl);\r\n\r\n if (!base64image) {\r\n return null;\r\n }\r\n\r\n const sitePlanWrapper = getSitePlanWrapper(sitePlanConfiguration);\r\n\r\n const svgContent = getSvgContent(sitePlanConfiguration, base64image);\r\n const svgUrl = `data:image/svg+xml;charset=UTF-8;base64,${(window.btoa(window.unescape(encodeURIComponent(svgContent))))}`;\r\n\r\n const container = document.createElement('div');\r\n container.classList.add('site-plan_container');\r\n container.dataset.communityMapId = sitePlanConfiguration.communityId;\r\n container.dataset.sitePlanId = sitePlanConfiguration.sitePlanId;\r\n container.dataset.url = sitePlanConfiguration.imageUrl;\r\n \r\n const imgElement = document.createElement(\"img\");\r\n imgElement.classList.add('site-plan_image');\r\n imgElement.style.transform = `rotate(${sitePlanConfiguration.rotationDegrees}deg)`;\r\n imgElement.src = svgUrl;\r\n container.appendChild(imgElement);\r\n sitePlanWrapper.appendChild(container);\r\n\r\n return container;\r\n}\r\n\r\n/**\r\n * parseSVG function will take an SVG representing an interactive site plan and\r\n * prepare it to work in sync with elements like the mask overlay.\r\n * @param {string} svgContent represents the content of the SVG.\r\n * @param {Object} config represents the site plan configuration.\r\n * @returns an object containing the created SVG document and SVG element.\r\n */\r\nconst parseSVG = (svgContent, communityId) => {\r\n const parser = new DOMParser();\r\n const svgDocument = parser.parseFromString(svgContent, 'image/svg+xml');\r\n const svgElement = svgDocument.documentElement;\r\n\r\n const clipPathElement = svgElement.getElementById('mask');\r\n if (clipPathElement) {\r\n clipPathElement.id = communityId;\r\n }\r\n\r\n const graphicElement = svgElement.querySelector('#siteplan_graphic');\r\n graphicElement?.setAttribute('clip-path', `url(#${communityId})`);\r\n svgElement.classList.add('site-plan_image');\r\n\r\n return {\r\n svgElement,\r\n svgDocument,\r\n };\r\n};\r\n\r\n/**\r\n * createSVGGroup function will create SVG groups that will hold the interactive markers\r\n * representing lots for plans and specs within that community.\r\n * @param {HTMLElement} svgDocument representing the site plan to show.\r\n * @param {LotPolygonType} lotType is the lot type from LotPolygonType enum.\r\n * @returns the created group node.\r\n */\r\nconst createSVGGroup = (svgDocument, lotType) => {\r\n const group = svgDocument.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n group.setAttribute('id', lotType.toString());\r\n return group;\r\n};\r\n\r\n/**\r\n * createLotPolygonGroups function will distribute the lot polygons within the \r\n * 4 groups listed in LotPolygonType enum.\r\n * @param {HTMLElement} svgDocument representing the site plan to show.\r\n * @returns an object with the 4 groups created for the lot polygons.\r\n */\r\nconst createLotPolygonGroups = (svgDocument) => ({\r\n inactiveGroup: createSVGGroup(svgDocument, LotPolygonType.Inactive),\r\n activeGroup: createSVGGroup(svgDocument, LotPolygonType.Active),\r\n selectedGroup: createSVGGroup(svgDocument, LotPolygonType.Selected),\r\n hoveredGroup: createSVGGroup(svgDocument, LotPolygonType.Hovered),\r\n});\r\n\r\n/**\r\n * moveElementsToGroup function will take all of the elements in a given group node\r\n * and move them to the specified target group.\r\n * @param {HTMLElement} sourceGroup represents the source group.\r\n * @param {HTMLElement} targetGroup represents the target group.\r\n */\r\nconst moveElementsToGroup = (sourceGroup, targetGroup) => {\r\n while (sourceGroup.firstChild) {\r\n targetGroup.appendChild(sourceGroup.firstChild);\r\n }\r\n};\r\n\r\n/**\r\n * setAttributes function will take a HTML element and set the specified\r\n * attributes to it.\r\n * @param {HTMLElement} element to set the list of attributes.\r\n * @param {Array} attributes to set on the specified element.\r\n */\r\nconst setAttributes = (element, attributes) => {\r\n Object.entries(attributes).forEach(([key, value]) => {\r\n element?.setAttribute(key, value);\r\n });\r\n};\r\n\r\n/**\r\n * setGroupAttributes function will set a set of attributes to groups\r\n * of the SVG representing the Community Interactive Map.\r\n * @param {HTMLElement} inactiveGroup is the holding inactive markers \r\n * @param {HTMLElement} activeGroup is the holding active markers \r\n * @param {HTMLElement} selectedGroup is the holding selected markers \r\n * @param {HTMLElement} hoveredGroup is the holding hovered markers \r\n */\r\nconst setGroupAttributes = ({ inactiveGroup, activeGroup, selectedGroup, hoveredGroup }) => {\r\n const commonAttributes = {\r\n 'stroke-width': '.5',\r\n 'stroke-linecap': 'round',\r\n 'stroke-linejoin': 'round',\r\n };\r\n\r\n [activeGroup, selectedGroup, hoveredGroup, inactiveGroup].forEach((group) =>\r\n setAttributes(group, commonAttributes)\r\n );\r\n\r\n inactiveGroup.classList.add('non-interactive-state');\r\n};\r\n\r\n/**\r\n * appendGroups function will take an array of groups and append it to a specified parent group.\r\n * @param {HTMLElement} parentGroup is the destination for the specified group nodes.\r\n * @param {Array} groups is an array of groups to be append to a given parent element.\r\n */\r\nconst appendGroups = (parentGroup, groups) => {\r\n Object.values(groups).forEach((group) => parentGroup.appendChild(group));\r\n};\r\n\r\n/**\r\n * applyStreetStyles will apply styles to the Streets layer.\r\n */\r\nconst applyStreetStyles = (svgElement) => {\r\n const fill = '#FFFFFF';\r\n const paths = svgElement.querySelectorAll('path');\r\n paths.forEach((path) => path.setAttribute('fill', fill));\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * applyWalkwayStyles will apply styles to the Walkway layer.\r\n */\r\nconst applyWalkwayStyles = (svgElement) => {\r\n const fill = '#EBEBEB';\r\n const stroke = '#CDD6CA';\r\n const paths = svgElement.querySelectorAll('path');\r\n paths.forEach((path) => {\r\n path.setAttribute('fill', fill);\r\n path.setAttribute('stroke', stroke);\r\n });\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * applyGrassStyles will apply styles to the Grass layer.\r\n */\r\nconst applyGrassStyles = (svgElement) => {\r\n const fill = '#B8EAC3';\r\n const paths = svgElement.querySelectorAll('path');\r\n paths.forEach((path) => path.setAttribute('fill', fill));\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * applyGolfStyles will apply styles to the Golf layer.\r\n */\r\nconst applyGolfStyles = (svgElement) => {\r\n const paths = [...svgElement.querySelectorAll('path')];\r\n const [firstPath, ...otherPaths] = paths;\r\n \r\n if (firstPath) {\r\n firstPath.setAttribute('fill', '#90DFA2');\r\n }\r\n \r\n otherPaths.forEach((path) => {\r\n path.setAttribute('fill', '#B8EAC3');\r\n });\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * applyWaterStyles will apply styles to the Water layer.\r\n */\r\nconst applyWaterStyles = (svgElement) => {\r\n const fill = '#C8DBF9';\r\n const paths = svgElement.querySelectorAll('path');\r\n paths.forEach((path) => path.setAttribute('fill', fill));\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * applyGroundStyles will apply styles to the Ground layer.\r\n */\r\nconst applyGroundStyles = (svgElement) => {\r\n const fill = '#CCCCCC';\r\n const paths = svgElement.querySelectorAll('path');\r\n paths.forEach((path) => path.setAttribute('fill', fill));\r\n\r\n return svgElement;\r\n}\r\n\r\n/**\r\n * layerStylingCallbacks is a look up structure meant for applying styles to the\r\n * loaded layers of an Interactive Site Plan.\r\n */\r\nconst layerStylingCallbacks = {\r\n [SitePlanLayer.Street]: applyStreetStyles,\r\n [SitePlanLayer.Walkway]: applyWalkwayStyles,\r\n [SitePlanLayer.Grass]: applyGrassStyles,\r\n [SitePlanLayer.Golf]: applyGolfStyles,\r\n [SitePlanLayer.Water]: applyWaterStyles,\r\n [SitePlanLayer.Ground]: applyGroundStyles,\r\n};\r\n\r\n/**\r\n * getInteractiveSitePlanLayers: will lazy load layers of an interactive site plan\r\n * depending on the current zoom level applied in the search results map.\r\n * @param {int} zoomLevel of the search results map.\r\n * @param {Array} svgLayers collection of the layers shwon by the site plan\r\n * @param {HTMLElement} container of the site plan\r\n * @param {int} communityId of the map shown\r\n */\r\nexport const getInteractiveSitePlanLayers = async (zoomLevel, svgLayers, container, communityId) => {\r\n const loadedLayers = container.hasAttribute('data-loaded-layers')\r\n ? container.getAttribute('data-loaded-layers').split(',').filter(Boolean)\r\n : [];\r\n\r\n const layersToShow = Array.from(zoomLevelLayersLookup.entries())\r\n .filter(([key]) => key <= zoomLevel)\r\n .flatMap(([, layers]) => layers)\r\n .filter((layer) => !loadedLayers.includes(layer.name));\r\n\r\n const layersToFetch = svgLayers.filter(svg =>\r\n layersToShow.some(layer => layer.name === svg.SvgLayerType)\r\n );\r\n\r\n const fetchPromises = layersToFetch.map(layer =>\r\n fetch(layer.Url).then(response => (response.ok ? response.text() : null))\r\n );\r\n\r\n const svgContents = await Promise.all(fetchPromises);\r\n const interactiveLayers = [SitePlanLayer.LotPolygons.toString(), SitePlanLayer.Lots.toString()];\r\n\r\n svgContents.forEach((svgContent, index) => {\r\n const layer = layersToFetch[index];\r\n if (svgContent && layer) {\r\n const { svgElement, svgDocument } = parseSVG(svgContent, communityId);\r\n\r\n if (interactiveLayers.indexOf(layer.SvgLayerType) !== -1) {\r\n svgElement.style.zIndex = layer.Order;\r\n const lotPolygonsGroup = svgElement.querySelector('#lot_polygons');\r\n\r\n if (lotPolygonsGroup) {\r\n const groups = createLotPolygonGroups(svgDocument);\r\n moveElementsToGroup(lotPolygonsGroup, groups.inactiveGroup);\r\n setGroupAttributes(groups);\r\n appendGroups(lotPolygonsGroup, groups);\r\n }\r\n\r\n container.appendChild(svgElement);\r\n } else {\r\n const img = document.createElement('img');\r\n const styledSvg = layerStylingCallbacks[layer.SvgLayerType]?.(svgElement) || svgElement;\r\n img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(styledSvg.outerHTML)}`;\r\n img.style.zIndex = layer.Order;\r\n img.classList.add('site-plan_container');\r\n\r\n container.appendChild(img);\r\n }\r\n\r\n loadedLayers.push(layer.SvgLayerType);\r\n container.setAttribute('data-loaded-layers', loadedLayers.join(','));\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * getCommunityInteractiveMapContainer function will create the container for an Interactive site plan.\r\n * @param {Object} sitePlanConfiguration holding the metadata needed for the creation of a site plan.\r\n * @param {int} zoomLevel is the current map zoom level. Based on it, elements will be shown or hidden.\r\n * @returns the HTML container for the community interactive map.\r\n */\r\nexport const getCommunityInteractiveMapContainer = async (sitePlanConfiguration, zoomLevel) => {\r\n const container = document.createElement('div');\r\n container.classList.add('site-plan_container');\r\n container.dataset.communityMapId = sitePlanConfiguration.communityId;\r\n container.dataset.sitePlanId = sitePlanConfiguration.sitePlanId;\r\n container.dataset.url = sitePlanConfiguration.imageUrl;\r\n\r\n await getInteractiveSitePlanLayers(\r\n zoomLevel,\r\n sitePlanConfiguration.sitePlanLayers,\r\n container,\r\n sitePlanConfiguration.communityId\r\n );\r\n\r\n const sitePlanWrapper = getSitePlanWrapper(sitePlanConfiguration);\r\n appendSitePlanContainerToMainWrapper(container, sitePlanWrapper, sitePlanConfiguration);\r\n container.style.transform = `rotate(${sitePlanConfiguration.rotationDegrees}deg)`;\r\n\r\n return container;\r\n};\r\n\r\n/**\r\n * getSitePlanTooltip function will create the HTML container for the site plan's tooltip.\r\n * @returns a HTML node representing the site plan's tooltip.\r\n */\r\nexport const getSitePlanTooltip = async (mapConfiguration) => {\r\n const { sitePlanId, communityId, isInteractiveSitePlan } = mapConfiguration;\r\n const tooltip = document.querySelector(`[data-community-map-tooltip-id=\"${communityId}\"]`);\r\n\r\n if (tooltip && !isInteractiveSitePlan) {\r\n return tooltip.parentElement;\r\n }\r\n\r\n const tooltipInformation = await firstValueFrom(getCommunitySummaryCardInformation(communityId));\r\n\r\n const sitePlanTooltip = new SitePlanTooltip();\r\n sitePlanTooltip.setInformation(tooltipInformation, isInteractiveSitePlan);\r\n const tooltipNode = sitePlanTooltip.getCard();\r\n\r\n tooltipNode.dataset.communityMapTooltipId = communityId;\r\n tooltipNode.dataset.sitePlanTooltipId = sitePlanId;\r\n\r\n const sitePlanTooltipContainer = document.createElement('div');\r\n sitePlanTooltipContainer.dataset.tooltipContainer = true;\r\n sitePlanTooltipContainer.classList.add(\"site-plan-tooltip_container\");\r\n\r\n sitePlanTooltipContainer.appendChild(tooltipNode);\r\n map.appendChild(sitePlanTooltipContainer);\r\n\r\n return sitePlanTooltipContainer;\r\n};\r\n\r\n/**\r\n * removeSitePlan function is called whenever a site plan is destroyed. It deletes any added resource\r\n * to the DOM related to the removed site plan.\r\n */\r\nexport const removeSitePlan = (resource) => {\r\n resource.container.parentElement?.remove();\r\n resource.container.remove();\r\n resource.overlay.remove();\r\n resource.tooltip?.remove();\r\n resource.polygonsContainer?.remove();\r\n resource.onSingleClick$.unsubscribe();\r\n resource.onDoubleClick$.unsubscribe();\r\n resource.onMouseMove$.unsubscribe();\r\n resource.onMouseLeave$.unsubscribe();\r\n}\r\n\r\n/**\r\n * applySitePlanStylesOnDraw will position the HTML site plan elements in terms of the map coordinates and zoom. \r\n */\r\nconst applySitePlanStylesOnDraw = (southWestPoint, northEastPoint, sitePlanContainer, sitePlanId) => {\r\n const polygonContainer = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n\r\n [polygonContainer, sitePlanContainer].forEach((container) => {\r\n if (container) {\r\n container.style.left = `${southWestPoint.x}px`;\r\n container.style.top = `${northEastPoint.y}px`;\r\n container.style.width = `${northEastPoint.x - southWestPoint.x}px`;\r\n container.style.height = `${southWestPoint.y - northEastPoint.y}px`;\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * handleSitePlanVisibility will show or hide the site plan containers depending on its visibility\r\n * relative to the viewport.\r\n * @param {HTMLElement} sitePlanContainer is the site plan container.\r\n * @param {int} sitePlanId is the site plan identifier. \r\n */\r\nconst handleSitePlanVisibility = (sitePlanContainer, sitePlanId, isSitePlanVisible) => {\r\n const polygonContainer = document.querySelector(`[data-polygon-container-id=\"${sitePlanId}\"]`);\r\n\r\n [polygonContainer, sitePlanContainer].forEach((container) => {\r\n if (container) {\r\n container.style.display = isSitePlanVisible ? 'block' : 'none';\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * drawSitePlan function is called whenever a Community site plan is draw.\r\n * It positiones the Community site plan resources in the DOM at the desired coordinates in terms of pixels.\r\n */\r\nexport const drawSitePlan = (resource, southWestPoint, northEastPoint) => {\r\n const { overlay, container, tooltip, communityId, sitePlanId } = resource;\r\n\r\n const isSitePlanVisible = isSitePlanInViewport(sitePlanId);\r\n handleSitePlanVisibility(container, sitePlanId, isSitePlanVisible);\r\n\r\n if (!isSitePlanVisible) {\r\n return;\r\n }\r\n\r\n const overlaySvg = overlay.querySelector('svg');\r\n applySitePlanStylesOnDraw(southWestPoint, northEastPoint, container, sitePlanId);\r\n\r\n overlaySvg.style.left = `${southWestPoint.x}px`;\r\n overlaySvg.style.top = `${northEastPoint.y}px`;\r\n overlaySvg.style.width = `${northEastPoint.x - southWestPoint.x}px`;\r\n overlaySvg.style.height = `${southWestPoint.y - northEastPoint.y}px`;\r\n\r\n const centerX = southWestPoint.x + (northEastPoint.x - southWestPoint.x) / 2;\r\n const centerY = northEastPoint.y + (southWestPoint.y - northEastPoint.y) / 2;\r\n\r\n if (tooltip) {\r\n tooltip.firstChild.style.left = `${centerX}px`;\r\n tooltip.firstChild.style.top = `${centerY}px`;\r\n \r\n /**\r\n * The left and top properties are tracked separately because they may change when \r\n * the user hovers over the site plan. Once the hover ends, the tooltip \r\n * must return to its original position, ensuring it aligns correctly if the user \r\n * hovers over the associated card in the list view.\r\n */\r\n tooltip.firstChild.dataset.left = `${centerX}px`;\r\n tooltip.firstChild.dataset.top = `${centerY}px`;\r\n tooltip.firstChild.setAttribute('hidden', '');\r\n }\r\n\r\n document.body.dispatchEvent(\r\n new CustomEvent('communityMapDrawComplete', {\r\n detail: {\r\n communityId,\r\n sitePlanId,\r\n },\r\n })\r\n );\r\n }\r\n\r\n/**\r\n * The `searchSitePlans` function returns an observable responsible for retrieving \r\n * site plan information. It manages both successful responses and error interactions \r\n * with the server, ensuring a smooth flow for the calling control.\r\n * \r\n * @param {Array} communityIds - The list of community IDs to be fetched from the server.\r\n * @returns {Observable} An observable that handles the retrieval of site plans data.\r\n */\r\nexport const searchSitePlans$ = (markers) => {\r\n const payload = {\r\n communityIds: markers.map(marker => marker.communityId),\r\n };\r\n\r\n return searchSitePlansInformation$(payload).pipe(\r\n switchMap(sitePlans => of({ sitePlans, markers })),\r\n catchError(() => of([])),\r\n );\r\n}\r\n\r\n/**\r\n * Creates an observable that handles mouse click events on a site plan image.\r\n * @param {HTML} sitePlanImage The element that receives the clicks.\r\n * @param {number} expectedClickCount The expected number of clicks to consider (1 for single, >1 for double).\r\n * @param {function} handler The function to handle the resulting click events.\r\n * @returns Observable for handling clicks in the site plan.\r\n */\r\nconst createClickObservable = (sitePlanImage, expectedClickCount, handler) => {\r\n const mouseDown$ = fromEvent(sitePlanImage, 'mousedown');\r\n const mouseUp$ = fromEvent(sitePlanImage, 'mouseup');\r\n\r\n return mouseDown$.pipe(\r\n switchMap((startEvent) => {\r\n const startX = startEvent.clientX;\r\n const startY = startEvent.clientY;\r\n\r\n return mouseUp$.pipe(\r\n take(1),\r\n filter((endEvent) => {\r\n const endX = endEvent.clientX;\r\n const endY = endEvent.clientY;\r\n const movementThreshold = 5;\r\n\r\n return (\r\n Math.abs(endX - startX) < movementThreshold &&\r\n Math.abs(endY - startY) < movementThreshold\r\n );\r\n })\r\n );\r\n }),\r\n buffer(mouseDown$.pipe(debounceTime(250))),\r\n filter(clicks => clicks.length === expectedClickCount),\r\n withLatestFrom(mapClicked$)\r\n ).subscribe(handler);\r\n};\r\n\r\n/**\r\n * onDragStart will hide any shown tooltips for site plans.\r\n */\r\nconst onDragStart = () => {\r\n hideSitePlansTooltips();\r\n}\r\n\r\nmapDragStart$.subscribe(onDragStart);\r\n\r\n/**\r\n * onDoubleClick$ observable will handle double click events on a site plan.\r\n * @param {HTML} container that received the double click.\r\n * @returns observable for handling double clicks in site plan.\r\n */\r\nexport const onDoubleClick$ = (container) => createClickObservable(container, 2, onDoubleClickSitePlan);\r\n\r\n/**\r\n * onSingleClick$ observable will handle single click events on a site plan.\r\n * @param {HTML} container that received the single click.\r\n * @returns observable for handling single clicks in site plan.\r\n */\r\nexport const onSingleClick$ = (container) => createClickObservable(container, 1, onClickSitePlan);\r\n\r\n/**\r\n * onMouseMove$ observable will handle mouse move events on a site plan.\r\n * @param {HTML} container that received the mouse move.\r\n * @returns observable for handling mouse move in site plan.\r\n */\r\nexport const onMouseMove$ = (container) =>\r\n fromEvent(container, 'mousemove').subscribe(onMouseMoveSitePlan);\r\n\r\n/**\r\n * onMouseLeave$ observable will handle mouse leave events on a site plan.\r\n * @param {HTML} container that received the mouse leave.\r\n * @returns observable for handling mouse leave in site plan.\r\n */\r\nexport const onMouseLeave$ = (container) =>\r\n fromEvent(container, 'mouseleave').subscribe(onMouseLeaveSitePlan);","const cssClassesToApply = {\r\n paid: {\r\n base: 'nhs-c-marker',\r\n selected: 'nhs-c-marker--selected',\r\n viewed: 'nhs-c-marker--viewed',\r\n },\r\n spotlight: {\r\n base: 'nhs-c-marker--spotlight',\r\n selected: 'nhs-c-marker--spotlight-selected',\r\n viewed: 'nhs-c-marker--spotlight-viewed',\r\n },\r\n noPrice: {\r\n base: 'nhs-c-marker__no-price',\r\n selected: 'nhs-c-marker__no-price--selected',\r\n viewed: 'nhs-c-marker__no-price--viewed',\r\n },\r\n priceReduction: {\r\n base: 'nhs-c-marker--price-off',\r\n selected: '',\r\n viewed: '',\r\n },\r\n basic: {\r\n base: 'nhs-c-marker-basic',\r\n selected: 'nhs-c-marker-basic--selected',\r\n viewed: 'nhs-c-marker-basic--viewed',\r\n },\r\n};\r\n\r\nconst getStateClasses = (markerTypeClasses, isSelected, isViewed) => ({\r\n base: markerTypeClasses.base,\r\n selected: isSelected ? markerTypeClasses.selected : null,\r\n viewed: isViewed ? markerTypeClasses.viewed : null,\r\n});\r\n\r\nconst getClassesToApply = ({ isBasic, isNoPrice, isSpotlight, isPriceReduction, isSelected, isViewed }) => {\r\n const classesToReturn = {\r\n base: [],\r\n selected: [],\r\n viewed: [],\r\n };\r\n\r\n if (isBasic) {\r\n const { basic } = cssClassesToApply;\r\n const { base, selected, viewed } = getStateClasses(basic, isSelected, isViewed);\r\n classesToReturn.base.push(base);\r\n classesToReturn.selected.push(selected);\r\n classesToReturn.viewed.push(viewed);\r\n return classesToReturn;\r\n }\r\n\r\n if (isNoPrice) {\r\n const { noPrice } = cssClassesToApply;\r\n const { base, selected, viewed } = getStateClasses(noPrice, isSelected, isViewed);\r\n classesToReturn.base.push(base);\r\n classesToReturn.selected.push(selected);\r\n classesToReturn.viewed.push(viewed);\r\n }\r\n\r\n if (isSpotlight) {\r\n const { spotlight } = cssClassesToApply;\r\n const { base, selected, viewed } = getStateClasses(spotlight, isSelected, isViewed);\r\n classesToReturn.base.push(base);\r\n classesToReturn.selected.push(selected);\r\n classesToReturn.viewed.push(viewed);\r\n }\r\n\r\n if (isPriceReduction && !isNoPrice) {\r\n const { priceReduction } = cssClassesToApply;\r\n const { base } = getStateClasses(priceReduction, isSelected, isViewed);\r\n classesToReturn.base.push(base);\r\n }\r\n\r\n if (!isNoPrice) {\r\n const { paid } = cssClassesToApply;\r\n const { base, selected, viewed } = getStateClasses(paid, isSelected, isViewed);\r\n classesToReturn.base.push(base);\r\n classesToReturn.selected.push(selected);\r\n classesToReturn.viewed.push(viewed);\r\n }\r\n\r\n return classesToReturn;\r\n};\r\n\r\nexport default getClassesToApply;\r\n","import { store } from '@redux/store';\r\nimport { selectConfigurationSegmentApiKey } from 'layout/redux/selectors'\r\n\r\n/**\r\n * The getSegmentKey function returns the Segment API key from the Redux store.\r\n * key is taken from bhi config and expose through the store.\r\n * @return A string\r\n */\r\nconst getSegmentApiKey = () => {\r\n const state = store.getState();\r\n const segmentApiKey = selectConfigurationSegmentApiKey(state);\r\n\r\n return segmentApiKey;\r\n}\r\n\r\n/* `const analyticsInstance` is an object that stores the state of the analytics script. It has three\r\nproperties: `isAnalyticsScriptLoaded`, `isAnalyticsScriptLoading`, and `loadingAttemps`. */\r\nconst analyticsInstance = {\r\n isAnalyticsScriptLoaded: false,\r\n isAnalyticsScriptLoading: false,\r\n loadingAttemps: 0,\r\n};\r\n\r\n/**\r\n * The onAnalyticsError function is called when the analytics script fails to load.\r\n * \r\n *\r\n * @param reject Reject the promise\r\n *\r\n * @return A promise\r\n */\r\nconst onAnalyticsError = (reject) => {\r\n console.log('Unable to load analytics script.');\r\n analyticsInstance.isAnalyticsScriptLoaded = false;\r\n analyticsInstance.isAnalyticsScriptLoading = false;\r\n reject(new Error(`Unable to load analytics script.`));\r\n};\r\n \r\n/**\r\n * The onAnalyticsLoaded function is called when the analytics script has been loaded.\r\n * \r\n *\r\n * @param resolve Resolve the promise\r\n *\r\n * @return A promise\r\n */\r\nconst onAnalyticsLoaded = (resolve) => {\r\n analyticsInstance.isAnalyticsScriptLoaded = true;\r\n resolve();\r\n};\r\n\r\n\r\n/**\r\n * The isAnalyticsLoaded function checks if the analytics script has been loaded.\r\n * If it is, then it resolves the promise with a call to onAnalyticsLoaded. \r\n * Otherwise, if loadingAttemps is less than 10, then we increment loadingAttemps and try again in 100ms.\r\n * If loadingAttempts reaches 10 without resolving the promise, we reject it with a call to onAnalyticsError.\r\n *\r\n * @param resolve Call the onanalyticsloaded function\r\n * @param reject Reject the promise\r\n *\r\n * @return A promise\r\n */\r\nconst isAnalyticsLoaded = (resolve, reject) => { \r\n if (analyticsInstance.isAnalyticsScriptLoaded) {\r\n onAnalyticsLoaded(resolve);\r\n } else if (analyticsInstance.loadingAttemps < 10){\r\n analyticsInstance.loadingAttemps = + 1;\r\n setTimeout(isAnalyticsLoaded.bind(null, resolve, reject), 100);\r\n } else {\r\n onAnalyticsError(reject);\r\n }\r\n};\r\n\r\n\r\n/**\r\n * The waitForAnalytics function returns a Promise that resolves when the Segment Analytics library has loaded.\r\n * @return A promise\r\n */\r\nconst waitForAnalytics = () =>\r\nnew Promise((resolve, reject) => {\r\n setTimeout(isAnalyticsLoaded.bind(null, resolve, reject), 100);\r\n});\r\n\r\n\r\n/**\r\n * The appendAnalyticsScript function appends the analytics script to the DOM.\r\n * @param resolve Resolve the promise\r\n * @param reject Reject the promise\r\n *\r\n * @return A promise\r\n */\r\nconst appendAnalyticsScript = (resolve, reject) => {\r\n \r\n /** Segment script to laod analytics.js */\r\n var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error(\"Segment snippet included twice.\");else{analytics.invoked=!0;analytics.methods=[\"trackSubmit\",\"trackClick\",\"trackLink\",\"trackForm\",\"pageview\",\"identify\",\"reset\",\"group\",\"track\",\"ready\",\"alias\",\"debug\",\"page\",\"once\",\"off\",\"on\",\"addSourceMiddleware\",\"addIntegrationMiddleware\",\"setAnonymousId\",\"addDestinationMiddleware\"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e {};\r\nconst segmentAnalyticsErrored = () => {};\r\n\r\nconst onConfigurationLoaded$ = store$.pipe(\r\n map(selectLoading),\r\n filter((loadingStatus) => loadingStatus === LoadingStatus.Succeeded.toString()),\r\n distinctUntilChanged()\r\n);\r\n\r\n// Loads segment analytics library\r\n/* `loadAnalytics(segmentAnalyticsLoaded, segmentAnalyticsErrored);` is calling the `loadAnalytics`\r\nfunction from the `segmentAnalyticsLibrary` module and passing two callback functions\r\n`segmentAnalyticsLoaded` and `segmentAnalyticsErrored` as arguments. These callback functions will\r\nbe executed depending on whether the analytics library is successfully loaded or if there is an\r\nerror during the loading process. */\r\nonConfigurationLoaded$.subscribe(() => loadAnalytics(segmentAnalyticsLoaded, segmentAnalyticsErrored));\r\n\r\nexport { segmentTrack, segmentImpression, segmentIdentify, segmentPageView };\r\n","import { createAction } from '@reduxjs/toolkit';\r\n\r\n// Event Action of type Track\r\n/* `const segmentTrack = createAction('segment/track');` is creating an action creator function using\r\nthe `createAction` function from the `@reduxjs/toolkit` library. This action creator function will\r\nreturn an action object with a `type` property set to `'segment/track'` when it is called. This\r\naction can then be dispatched to the Redux store to trigger a state update or other side effects. */\r\nconst segmentTrack = createAction('segment/track');\r\n\r\n// Event Action of type Impression\r\n/* `const segmentImpression = createAction('segment/impression');` is creating an action creator\r\nfunction using the `createAction` function from the `@reduxjs/toolkit` library. This action creator\r\nfunction will return an action object with a `type` property set to `'segment/impression'` when it\r\nis called. This action can then be dispatched to the Redux store to trigger a state update or other\r\nside effects. */\r\nconst segmentImpression = createAction('segment/impression');\r\n\r\n/* `const segmentIdentify = createAction('segment/identify');` is creating an action creator function\r\nusing the `createAction` function from the `@reduxjs/toolkit` library. This action creator function\r\nwill return an action object with a `type` property set to `'segment/identify'` when it is called.\r\nThis action can then be dispatched to the Redux store to trigger a state update or other side\r\neffects. */\r\nconst segmentIdentify = createAction('segment/identify');\r\n\r\n/* `const segmentPageView = createAction('segment/pageview');` is creating an action creator function\r\nusing the `createAction` function from the `@reduxjs/toolkit` library. This action creator function\r\nwill return an action object with a `type` property set to `'segment/pageview'` when it is called.\r\nThis action can then be dispatched to the Redux store to trigger a state update or other side\r\neffects. */\r\nconst segmentPageView = createAction('segment/pageview');\r\n\r\nexport { segmentTrack, segmentImpression, segmentIdentify, segmentPageView };\r\n","export default class SegmentEventType {\r\n /**\r\n * This is a static method that returns an instance of the \"Track\" class.\r\n * @returns The `Track` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Track'` as an argument.\r\n */\r\n static get Track() {\r\n return this.getInstance('Track');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"Impression\" class.\r\n * @returns The `Impression` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Impression'` as an argument.\r\n */\r\n static get Impression() {\r\n return this.getInstance('Impression');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"Identify\" class.\r\n * @returns The `Identify` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Identify'` as an argument.\r\n */\r\n static get Identify() {\r\n return this.getInstance('Identify');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"PageView\" class.\r\n * @returns The `PageView` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'PageView'` as an argument.\r\n */\r\n static get PageView() {\r\n return this.getInstance('PageView');\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n Track: SegmentEventType.Track,\r\n Impression: SegmentEventType.Impression,\r\n Identify: SegmentEventType.Identify,\r\n PageView: SegmentEventType.PageView,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * Gets an instance of a SegmentEventType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the SegmentEventType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the SegmentEventType class that is being created.\r\n *\r\n * @returns an instance of `SegmentEventType` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new SegmentEventType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(SegmentEventType, 'instances', { value: {} });\r\n","import { IdleQueue } from 'idlize/IdleQueue';\r\n/* Class that represents the redux beacon target to track Segment events */\r\nclass Segment {\r\n constructor() {\r\n this.events = [];\r\n this.queue = new IdleQueue({ ensureTasksRun: true });\r\n\r\n this.target = (events) => {\r\n this.startTime = this.startTime || +new Date();\r\n this.events = [...this.events, ...events];\r\n this.queue.pushTask(this.trackEvent.bind(this));\r\n };\r\n\r\n this.hitTypeHandlers = {\r\n identify: (event) => window.analytics.identify(event.userId, event.traits, event.options),\r\n group: (event) => window.analytics.group(event.groupId, event.traits, event.options),\r\n pageview: (event) => window.analytics.page(event.page, event.name, event.properties, event.options),\r\n event: (event) => window.analytics.track(event.eventAction, event.properties, event.options),\r\n alias: (event) => window.analytics.alias(event.userId, event.previousId, event.options),\r\n reset: () => window.analytics.reset(),\r\n };\r\n }\r\n\r\n trackEvent() {\r\n const timeLapsed = +new Date() - this.startTime;\r\n const isTimeExpired = timeLapsed < 15000;\r\n\r\n /* If analytics is not defined and the time has not expired we shouldnt queue the event again */\r\n if (!window.analytics && isTimeExpired) {\r\n this.queue.pushTask(this.trackEvent.bind(this));\r\n return;\r\n }\r\n\r\n /* The event is not in queue anymore because the time has passed BUT the we need to continue to \r\n validate analytics */\r\n if (!window.analytics) {\r\n this.events = [];\r\n return;\r\n }\r\n\r\n while (this.events.length !== 0) {\r\n const event = this.events.shift();\r\n const handler = this.hitTypeHandlers[event.hitType];\r\n if (handler) {\r\n handler(event);\r\n }\r\n }\r\n\r\n this.startTime = +new Date();\r\n }\r\n\r\n getTarget() {\r\n return this.target;\r\n }\r\n}\r\n\r\nexport default Segment;\r\n","/**\r\n * Record actions your users perform\r\n * @param {string} eventAction - The name of the event you’re tracking.\r\n * @param {object} properties - Optional. A dictionary of properties for the event.\r\n * @param {object} options - Optional. A dictionary of options.\r\n */\r\nfunction trackEvent(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n hitType: 'event',\r\n eventAction: event.name,\r\n properties: event.properties,\r\n options: event.options,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Link your users and their actions, to a recognizable userId and traits.\r\n * @param {string} userId - The database ID for the user.\r\n * @param {object} traits - A dictionary of traits you know about the user, like email or name.\r\n * @param {object} options - A dictionary of options.\r\n */\r\nfunction identifyUser(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n hitType: 'identify',\r\n userId: event.userId,\r\n traits: event.traits,\r\n options: event.options,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Record page views on your website, along with optional extra information about the page viewed\r\n * by the user.\r\n * @param {string} page - The page type.\r\n * @param {object} name - The name of the page.\r\n * @param {object} properties - A dictionary of properties of the page\r\n * @param {object} options - A dictionary of options.\r\n */\r\nfunction trackPageView(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n hitType: 'pageview',\r\n page: event.category,\r\n name: event.name,\r\n properties: event.properties,\r\n options: event.options,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Record page views on your website, along with optional extra information about the page viewed\r\n * by the user.\r\n * @param {string} groupId - The Group ID to associate with the current user.\r\n * @param {object} traits - A dictionary of traits for the group.\r\n * @param {object} options - A dictionary of options.\r\n */\r\nfunction setGroup(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n hitType: 'group',\r\n groupId: event.groupId,\r\n traits: event.traits,\r\n options: event.options,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Combines two unassociated user identities.\r\n * @param {string} userId - The new user ID you want to associate with the user.\r\n * @param {object} previousId - The previous ID that the user was recognized by.\r\n * @param {object} options - A dictionary of options.\r\n */\r\nfunction setAlias(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n hitType: 'alias',\r\n userId: event.userId,\r\n previousId: event.previousId,\r\n options: event.options,\r\n };\r\n };\r\n}\r\n\r\n/* Calling reset resets the id, including anonymousId, and clears traits for the currently identified user and group. */\r\nfunction reset() {\r\n return () => ({\r\n hitType: 'reset',\r\n });\r\n}\r\n\r\nexport { trackEvent, identifyUser, trackPageView, setGroup, setAlias, reset };\r\n","/**\r\n* Class to work as a DTO to hold the information of a event dispatched to segment.\r\n*/\r\nclass SegmentEvent { \r\n constructor(name = '', customProperties = {}) {\r\n this.name = name;\r\n this.properties = customProperties;\r\n }\r\n }\r\n \r\n export default SegmentEvent;","/**\r\n* Class to work as a DTO to hold the information of a event dispatched to segment.\r\n*/\r\nclass SegmentIdentifyEvent { \r\n constructor(userId = '', traits = {}) {\r\n this.userId = userId;\r\n this.traits = traits;\r\n }\r\n }\r\n \r\n export default SegmentIdentifyEvent;","export default class DateExtensions {}\r\n/**\r\n * The formatDateFromStringTimestamp function takes an timestamp in a string format\r\n * as '1688009760000' and returns the date in a mm/dd/yyyy format\r\n * @param stringTimestamp string timestamp\r\n */\r\nObject.defineProperty(DateExtensions, \"formatDateFromStringTimestamp\", { value: dateString => {\r\n const date = new Date(dateString);\r\n const formattedDate = date.toLocaleDateString('en-US', {\r\n month: '2-digit',\r\n day: '2-digit',\r\n year: 'numeric'\r\n });\r\n return formattedDate;\r\n}});","/**\r\n * Class to work as a DTO to hold the information of a event dispatched to segment.\r\n * Read more at https://rangle.gitbook.io/redux-beacon/index/segment#identify\r\n */\r\nclass SegmentPageEvent {\r\n constructor(category, name, properties, options) {\r\n this.category = category;\r\n this.name = name;\r\n this.properties = properties;\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * The above function returns the category of a segment page event.\r\n * @returns The category of the segment page event.\r\n */\r\n getCategory() {\r\n return this.category;\r\n }\r\n\r\n /**\r\n * The above function is a getter method that returns the value of the \"name\" property.\r\n * @returns The name property of the segment page event.\r\n */\r\n getName() {\r\n return this.name;\r\n }\r\n\r\n /**\r\n * The function returns the properties of a segment page event.\r\n * @returns The properties of the segment page event.\r\n */\r\n getProperties() {\r\n return this.properties;\r\n }\r\n\r\n /**\r\n * The function returns the options property.\r\n * @returns The options property is being returned.\r\n */\r\n getOptions() {\r\n return this.options;\r\n }\r\n}\r\n\r\nexport default SegmentPageEvent;\r\n","import { store } from '@redux/store';\r\nimport { trackEvent, identifyUser, trackPageView } from 'middlewares/segment';\r\nimport SegmentEvent from 'dataTransferObjects/segmentEvent';\r\nimport SegmentIdentifyEvent from 'dataTransferObjects/segmentIdentifyEvent';\r\nimport SegmentEventType from 'enums/segmentEventType';\r\nimport {\r\n hasAvailableNow,\r\n hasReadyToBuild,\r\n hasInventoryStatusCombination,\r\n MoveInDate,\r\n} from 'features/searchResultsFacets';\r\nimport getTrackingCommonProperties from 'features/trackingProperties';\r\nimport merge from 'deepmerge';\r\nimport cleanObjectsEmptyProperties from 'utils/cleanObject';\r\nimport DateExtensions from 'utils/dateExtensions';\r\nimport { FavoriteType } from 'features/userProfile';\r\nimport SegmentPageEvent from 'dataTransferObjects/segmentPageEvent';\r\nimport LocationType from '../features/searchResultsFacets/enums/locationType';\r\nimport { getTrackerClientId } from './googleAnalytics';\r\n\r\n/**\r\n * The getCommonProperties function returns an object containing the common properties\r\n * that are used in all Segment events.\r\n * @return An object\r\n */\r\nconst getCommonProperties = () => {\r\n const state = store.getState();\r\n const commonProperties = getTrackingCommonProperties(state);\r\n return commonProperties;\r\n};\r\n\r\n/**\r\n * The function filters the segment common properties, and take only the ones needed for Track events.\r\n * ex. track don't need user information. user information is available in common properties.\r\n * @returns object containing the common properties for a Track event.\r\n */\r\nconst getTrackCommonProperties = () => {\r\n const commonProperties = getCommonProperties();\r\n const marketNameProperty = (commonProperties.marketName && commonProperties.stateAbbreviation)\r\n ? `${commonProperties.marketName}, ${commonProperties.stateAbbreviation}`\r\n : undefined;\r\n\r\n const trackCommonProperties = {\r\n market_id: commonProperties.marketId?.toString(),\r\n market_name: marketNameProperty,\r\n city: commonProperties.city,\r\n state: commonProperties.stateAbbreviation,\r\n zip: commonProperties.zip,\r\n brand_id: commonProperties.brandId,\r\n brand_name: commonProperties.brandName,\r\n page_type: commonProperties.pageType,\r\n code_version: commonProperties.buildCodeVersion,\r\n test_version: commonProperties.testVersion,\r\n response_version: commonProperties.responseVersion,\r\n partner_id: commonProperties.partnerId,\r\n partner_name: commonProperties.partnerName,\r\n brand_partner_name_partner_name: commonProperties.brandPartnerName,\r\n };\r\n\r\n const cleanedTrackCommonProperties = cleanObjectsEmptyProperties(trackCommonProperties);\r\n return cleanedTrackCommonProperties;\r\n};\r\n\r\n/**\r\n * The createTrackEvent function is a helper function that creates an event object\r\n * for the Segment analytics library. The event object contains information about\r\n * the type of event, and any properties associated with it. This function returns\r\n * a redux-beacon middleware compatible action creator that can be dispatched to\r\n * trigger an analytics call to Segment's servers.\r\n * @param eventName Identify the event name\r\n * @param properties Pass in any additional properties that you want to be sent with the event\r\n *\r\n * @return A function that returns a segmentevent\r\n */\r\nconst createTrackEvent = ({ eventName, customProperties }) => {\r\n const commonProperties = getTrackCommonProperties();\r\n const properties = merge(commonProperties, customProperties);\r\n\r\n return trackEvent(() => new SegmentEvent(eventName, properties));\r\n};\r\n\r\n/** method formats user favorites.\r\n * @returns An object with the list of Communities, Homes and Builders that are already saved.\r\n */\r\nconst getUserSavedElements = (favorites) => {\r\n const communities = [];\r\n const homes = [];\r\n const builders = [];\r\n\r\n favorites.forEach((obj) => {\r\n const savedDate = DateExtensions.formatDateFromStringTimestamp(obj.dateChanged);\r\n const favoriteType = FavoriteType.fromKey(obj.type);\r\n // For the Community Saved Items\r\n if (favoriteType === FavoriteType.Community) {\r\n communities.push({\r\n communityId: obj.listingId,\r\n dateSaved: savedDate,\r\n });\r\n\r\n // For the Spec and Plan Saved Items\r\n } else if (favoriteType === FavoriteType.Spec || favoriteType === FavoriteType.Plan) {\r\n homes.push({\r\n homeId: obj.listingId,\r\n dateSaved: savedDate,\r\n });\r\n\r\n // For the Builder Saved Items\r\n } else if (favoriteType === FavoriteType.Builder) {\r\n builders.push({\r\n builderId: obj.builderInfo?.builderId,\r\n dateSaved: savedDate,\r\n });\r\n }\r\n });\r\n\r\n return {\r\n communities,\r\n homes,\r\n builders,\r\n };\r\n};\r\n\r\n/**\r\n * Checks the type and array length\r\n * @param array - the array to be checked.\r\n * @returns the array send on the parameters or null value if it's length is 0.\r\n */\r\n\r\nconst checkEmptyArray = (array) => {\r\n if (Array.isArray(array) && array.length) {\r\n return array;\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * The function filters the segment identify common properties, and take only the ones needed for Identify events.\r\n * ex. track don't need user information. user information is available in common properties.\r\n * @returns object containing the common properties for a Track event.\r\n */\r\nconst getIdentifyProperties = () => {\r\n const state = store.getState();\r\n const commonProperties = getCommonProperties(state);\r\n const [firstName, lastName] = commonProperties.name.split(' ');\r\n const savedElements = getUserSavedElements(commonProperties.favorites);\r\n const userId = commonProperties.userId.replace(/[{}]/g, '');\r\n\r\n const identifyCommonProperties = {\r\n user_id: userId,\r\n email: commonProperties.email || null,\r\n first_name: firstName || null,\r\n last_name: lastName || null,\r\n zip: commonProperties.userZip || null,\r\n phone: commonProperties.phone || null,\r\n outside_us: commonProperties.livesOutside,\r\n saved_communities: checkEmptyArray(savedElements.communities),\r\n saved_homes: checkEmptyArray(savedElements.homes),\r\n saved_builders: checkEmptyArray(savedElements.builders),\r\n g_client_id: getTrackerClientId(),\r\n };\r\n\r\n // By biz rule, if the neustarSegment equals to 000, we don't have to send the values with _n prefix on the event.\r\n if (commonProperties.neustarSegment !== '000') {\r\n identifyCommonProperties.n_segment = commonProperties.neustarSegment;\r\n identifyCommonProperties.n_zip = commonProperties.neustarZip || null;\r\n identifyCommonProperties.n_year = commonProperties.neustarAge || null;\r\n identifyCommonProperties.n_gender = commonProperties.neustarGender || null;\r\n }\r\n\r\n const cleanedIdentifyCommonProperties = cleanObjectsEmptyProperties(identifyCommonProperties);\r\n return cleanedIdentifyCommonProperties;\r\n};\r\n\r\nconst createIdentifyEvent = ({ eventName }) => {\r\n const traits = getIdentifyProperties();\r\n traits.last_event = eventName;\r\n const userId = traits.user_id;\r\n\r\n return identifyUser(() => new SegmentIdentifyEvent(userId, traits));\r\n};\r\n\r\n/**\r\n * getMoveInDate: Sets the Move-In value depending on the selection on the dropdown\r\n * @param moveInInformation The move-in information that can be either the date range or home status\r\n * @returns The value with the move-in home status or range.\r\n */\r\nfunction getMoveInDate(moveInInformation) {\r\n const { moveInDateRange, homeStatus } = moveInInformation;\r\n /* return value for each QMI status */\r\n const moveNow = 'QMI_Now';\r\n const buildablePlans = 'R';\r\n const quickMoveIn = 'QMI';\r\n const oneToTwoMonths = 'QMI_1_2Months';\r\n const threeToSixMonths = 'QMI_3_6Months';\r\n\r\n /* All Quick Move-In */\r\n if (hasInventoryStatusCombination(homeStatus)) {\r\n return quickMoveIn;\r\n }\r\n\r\n /* Move now */\r\n if (hasAvailableNow(homeStatus)) {\r\n return moveNow;\r\n }\r\n\r\n /* Buildable Plans */\r\n if (hasReadyToBuild(homeStatus)) {\r\n return buildablePlans;\r\n }\r\n\r\n /* 1-2 months */\r\n if (moveInDateRange === MoveInDate.OneToTwoMonths.toString()) {\r\n return oneToTwoMonths;\r\n }\r\n\r\n /* 3-6 months */\r\n if (moveInDateRange === MoveInDate.ThreeToSixMonths.toString()) {\r\n return threeToSixMonths;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * getSearchLocation: Gets the search location information based on what's on the search box\r\n * @param locationInformation All the location information: market, state, zip\r\n * @returns The value with search location information.\r\n */\r\nfunction getSearchLocation(locationInformation) {\r\n const { locationType, marketName, city, marketState, zip, syntheticGeographicName, county } = locationInformation;\r\n const searchType = LocationType.fromKey(locationType);\r\n\r\n /* Search label depending on the different search types */\r\n const searchLocationLabelDictionary = {\r\n market: `${marketName} ${marketState}, Area`,\r\n city: `${city}, ${marketState}`,\r\n zip,\r\n syntheticGeo: `${syntheticGeographicName}, ${marketState}`,\r\n county: `${county} County, ${marketState}`,\r\n };\r\n\r\n if (locationType === searchType.name) {\r\n return searchLocationLabelDictionary[locationType];\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * getMasterBedLocationLabel: Gets the primary bedroom location: Up - Down.\r\n * @param bedroom The primary bedroom location: 1 / 2\r\n * @returns The master bed location that as requested should be: Up as 2 and Down as 1.\r\n */\r\nfunction getMasterBedLocationLabel(bedroom) {\r\n switch (bedroom) {\r\n /* 1 value corresponds as second floor, but returns 2 since that was de value requested on ticket NHS20-2248 */\r\n case 1:\r\n return 2;\r\n /* 2 value corresponds as first floor, but returns 1 since that was de value requested on ticket NHS20-2248 */\r\n case 2:\r\n return 1;\r\n default:\r\n return undefined;\r\n }\r\n}\r\n\r\n/** This function handles the mapping of the object values in order to rename them\r\n * as requested with underscore.\r\n * This function will receive as parameters all the filters facets applied and as well\r\n * the price if is min or max.\r\n */\r\nfunction formatFiltersApplied(facets, price, schools, moveIn, search) {\r\n return {\r\n bathrooms: facets.bathrooms,\r\n bedrooms: facets.bedrooms,\r\n price_high: price?.maximumPrice,\r\n price_low: price?.minimumPrice,\r\n single_family: facets.singleFamily,\r\n model_homes: facets.modelHomes,\r\n luxury_homes: facets.luxury,\r\n condo_townhome: facets.condosAndTownHomes,\r\n living_areas: facets.livingAreas,\r\n master_bed_location: getMasterBedLocationLabel(facets.primaryBedroom),\r\n garages: facets.garages,\r\n stories: facets.stories,\r\n gated: facets.gatedCommunity,\r\n pool: facets.pool,\r\n golf_course: facets.golfCourse,\r\n green: facets.green,\r\n nature_areas: facets.natureAreas,\r\n parks: facets.parks,\r\n sports: facets.sportsFacilities,\r\n views: facets.views,\r\n waterfront: facets.waterfront,\r\n hot_deals: facets.hotDeals,\r\n price_reduction: facets.priceReduction,\r\n listings_hoa_info: facets.hasHomeOwnersAssociationFee,\r\n age_restricted: facets.adult,\r\n rv_garage: facets.rvGarage,\r\n school_district_ids: schools?.join(', '),\r\n brand_id: facets.builderBrand,\r\n move_in_date: getMoveInDate(moveIn),\r\n mfr: facets.manufactured,\r\n custom: facets.customHomes,\r\n search_location: getSearchLocation(search),\r\n coming_soon: facets.comingsoon,\r\n grand_opening: facets.grandOpening,\r\n active: facets.active,\r\n closeout: facets.closeOut,\r\n };\r\n}\r\n\r\n/**\r\n * facetsEntriesValues: Gets the active values from facets and converts them into an object\r\n * filters when an object is active or not.\r\n * @param facet The facet we are trying to filter and convert\r\n * @returns The active facet values as an object.\r\n */\r\n\r\nfunction facetsEntriesValues(facet) {\r\n const activeFacet = Object.entries(facet).filter(([, facetValue]) => Boolean(facetValue));\r\n\r\n const facetValues = Object.fromEntries(activeFacet);\r\n\r\n return facetValues;\r\n}\r\n\r\n/**\r\n * getImpressionBaseProperties: Gets all the only impression-shared properties to be used\r\n * on the impression events. It relates exactly to the common properties that are shown\r\n * on the impression events but not considering the track common properties.\r\n * @returns The properties that are shared for the impression events.\r\n */\r\n\r\nconst getImpressionBaseProperties = () => {\r\n const { facets, listingCount, pageNumber, price, schools, moveInDate, searchLocation } = getCommonProperties();\r\n\r\n const filtersValues = facetsEntriesValues(facets);\r\n\r\n const priceValues = facetsEntriesValues(price);\r\n\r\n const impressionCommonProperties = {\r\n filters_applied: formatFiltersApplied(filtersValues, priceValues, schools, moveInDate, searchLocation),\r\n result_count: listingCount,\r\n current_page_number: pageNumber,\r\n };\r\n return impressionCommonProperties;\r\n};\r\n\r\n/**\r\n * getImpressionProperties: Gets all the shared properties that should be used on\r\n * every impression event. It includes the track common properties.\r\n * @returns The impression properties that every impression event should use.\r\n */\r\nconst getImpressionProperties = () => {\r\n const trackCommonProperties = getTrackCommonProperties();\r\n const impressionCommonProperties = getImpressionBaseProperties();\r\n const properties = merge(trackCommonProperties, impressionCommonProperties);\r\n return properties;\r\n};\r\n/**\r\n * createImpressionEvent: Triggers the impression events with all the required properties.\r\n * @param eventName Identify the event name\r\n * @param properties Pass in any additional properties that you want to be sent with the event\r\n * @return A function that returns a segmentevent\r\n */\r\nconst createImpressionEvent = ({ eventName, customProperties }) => {\r\n const impressionProperties = getImpressionProperties();\r\n const properties = merge(impressionProperties, customProperties);\r\n return trackEvent(() => new SegmentEvent(eventName, properties));\r\n};\r\n\r\nconst createPageEvent = ({ category, name, customProperties = {}, options }) => {\r\n const commonProperties = getTrackCommonProperties();\r\n const properties = merge(commonProperties, customProperties);\r\n return trackPageView(() => new SegmentPageEvent(category, name, properties, options));\r\n};\r\n\r\n/**\r\n * The getSegmentEvent function returns a SegmentEvent object.\r\n * @param eventType Determine which type of event to create\r\n * @param eventName Identify the event name\r\n * @param customProperties Pass in custom properties to the event\r\n *\r\n * @return An SegmentEvent object\r\n */\r\nconst getSegmentEvent = (eventType, event) => {\r\n switch (eventType) {\r\n case SegmentEventType.Track:\r\n return createTrackEvent(event);\r\n case SegmentEventType.Identify:\r\n return createIdentifyEvent(event);\r\n case SegmentEventType.Impression:\r\n return createImpressionEvent(event);\r\n case SegmentEventType.PageView:\r\n return createPageEvent(event);\r\n\r\n default:\r\n // Default case\r\n return null;\r\n }\r\n};\r\n\r\nexport default getSegmentEvent;\r\n","import { createMiddleware } from 'redux-beacon';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport SegmentEventType from 'enums/segmentEventType';\r\nimport { Segment } from 'middlewares/segment';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport getSegmentEvent from 'services/segmentEventBuilder';\r\nimport { segmentIdentify, segmentImpression, segmentPageView, segmentTrack } from './actions';\r\n\r\n/**\r\n * The eventsMap function is a mapping of Redux actions to Segment events.\r\n * It returns an array of Segment events, which are objects with the following shape:\r\n * {\r\n * eventType: string, // The name of the event (e.g., 'track')\r\n * fieldsObj: object, // An object containing all properties for this event type (e.g., {eventName})\r\n * }\r\n *\r\n * @param action Determine which event to return\r\n *\r\n * @return An array of events\r\n */\r\nconst eventsMap = (action) => {\r\n switch (action.type) {\r\n case segmentTrack.type: {\r\n const payload = action.payload;\r\n const event = debounceEvent(\r\n 1000,\r\n getSegmentEvent(SegmentEventType.Track, {\r\n eventName: payload.eventName,\r\n customProperties: payload.customProperties,\r\n })\r\n );\r\n return event;\r\n }\r\n case segmentIdentify.type: {\r\n const payload = action.payload;\r\n const event = debounceEvent(1000, getSegmentEvent(SegmentEventType.Identify, { eventName: payload.eventName }));\r\n return event;\r\n }\r\n\r\n case segmentImpression.type: {\r\n const payload = action.payload;\r\n const event = debounceEvent(\r\n 1000,\r\n getSegmentEvent(SegmentEventType.Impression, {\r\n eventName: payload.eventName,\r\n customProperties: payload.customProperties,\r\n })\r\n );\r\n return event;\r\n }\r\n\r\n case segmentPageView.type: {\r\n const payload = action.payload;\r\n const event = debounceEvent(\r\n 1000,\r\n getSegmentEvent(SegmentEventType.PageView, {\r\n category: payload.category,\r\n name: payload.name,\r\n customProperties: payload.customProperties,\r\n options: payload.options,\r\n })\r\n );\r\n return event;\r\n }\r\n\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\n/* `const segment = Segment();` is creating an instance of the `@redux-beacon/segment` library, which\r\nis used to send events to the Segment analytics platform. This instance is then passed as an\r\nargument to the `createMiddleware` function to create a middleware that listens for Redux actions\r\nand sends corresponding Segment events using the `segment` instance. */\r\nconst segment = new Segment();\r\n\r\n/* `const middleware = createMiddleware(eventsMap, segment);` is creating a middleware using\r\n`redux-beacon` library. The `createMiddleware` function takes two arguments: `eventsMap` and\r\n`segment`. `eventsMap` is a function that maps Redux actions to Segment events, and `segment` is an\r\ninstance of the `@redux-beacon/segment` library. The middleware created by `createMiddleware` will\r\nlisten for Redux actions and send corresponding Segment events using the `segment` instance. */\r\nconst middleware = createMiddleware(eventsMap, segment.getTarget());\r\n\r\n// registers the middleware in redux\r\n/* `addMiddleware(middleware)` is registering the middleware created by `createMiddleware` in the Redux\r\nstore. This allows the middleware to listen for Redux actions and send corresponding Segment events\r\nusing the `segment` instance. */\r\naddMiddleware(middleware);\r\n","import { createSlice } from '@reduxjs/toolkit';\r\n\r\n/* Creating a slice of the state for stuff related to the map. */\r\nconst speedcurveStateSlice = createSlice({\r\n name: 'speedcurveState',\r\n initialState: {\r\n isInProgress: false,\r\n },\r\n reducers: {\r\n start: (state) => {\r\n state.isInProgress = true;\r\n },\r\n end: (state) => {\r\n state.isInProgress = false;\r\n },\r\n },\r\n});\r\n\r\nexport default speedcurveStateSlice;\r\n","import { store } from '@redux/store';\r\nimport {\r\n speedCurveTrackConversion,\r\n speedCurveMarkStart,\r\n speedCurveMarkEnd,\r\n speedcurveTimingMetric,\r\n} from './redux/actions';\r\nimport selectIsInProgress from './redux/selectors';\r\nimport speedcurveStateSlice from './redux/slices';\r\n\r\nconst { actions, reducer } = speedcurveStateSlice;\r\n\r\nstore.injectReducer('speedcurveState', reducer);\r\n\r\nrequire('./redux/beaconMiddleware');\r\n\r\nexport {\r\n speedCurveTrackConversion,\r\n speedCurveMarkStart,\r\n speedCurveMarkEnd,\r\n speedcurveTimingMetric,\r\n selectIsInProgress,\r\n actions as speedcurveStateActions,\r\n};\r\n","import { createAction } from '@reduxjs/toolkit';\r\n\r\n/* This function is being called with the argument `'speedcurve/trackConversion'`, which is a string\r\nrepresenting the name of the action. The `createAction` function is used to create an action\r\ncreator, which is a function that returns an action object with a specific type. In this case, the\r\naction object will have a type of `'speedcurve/trackConversion'`. \r\n\r\nExamples:\r\n\r\nstore.dispatch(speedCurveTrackConversion([{ name: 'lead_sent', value: 1 }]))\r\n*/\r\nconst speedCurveTrackConversion = createAction('speedcurve/trackConversion');\r\n\r\n/* This function is being called with the argument `'speedcurve/markStart'`, which is a string\r\nrepresenting the name of the action. The `createAction` function is used to create an action\r\ncreator, which is a function that returns an action object with a specific type. In this case, the\r\naction object will have a type of `'speedcurve/markStart'`. \r\n\r\nExamples:\r\n\r\nstore.dispatch(speedCurveMarkStart([{ name: 'map_script_start' }]))\r\n*/\r\nconst speedCurveMarkStart = createAction('speedcurve/markStart');\r\n\r\n/* This function is being called with the argument `'speedcurve/markEnd'`, which is a string\r\nrepresenting the name of the action. The `createAction` function is used to create an action\r\ncreator, which is a function that returns an action object with a specific type. In this case, the\r\naction object will have a type of `'speedcurve/markEnd'`. \r\n\r\nExamples:\r\n\r\nstore.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: 'map_downloaded',\r\n markNameStart: 'map_script_start',\r\n markNameEnd: 'map_script_end',\r\n },\r\n ])\r\n );\r\n*/\r\nconst speedCurveMarkEnd = createAction('speedcurve/markEnd');\r\n\r\n/* This function is being called with the argument `'speedcurve/timingMetric'`, which is a string\r\nrepresenting the name of the action. The `createAction` function is used to create an action\r\ncreator, which is a function that returns an action object with a specific type. In this case, the\r\naction object will have a type of `'speedcurve/timingMetric'`. \r\n\r\nExamples:\r\n\r\nstore.dispatch(speedcurveTimingMetric([{ name: 'srp', value: 500 }]))\r\n*/\r\nconst speedcurveTimingMetric = createAction('speedcurve/timingMetric');\r\n\r\nexport { speedCurveTrackConversion, speedCurveMarkStart, speedCurveMarkEnd, speedcurveTimingMetric };\r\n","/* Class that represents the redux beacon target to track RUM events */\r\nclass SpeedcurveRum {\r\n constructor() {\r\n this.target = (events) => {\r\n if (!window.LUX) {\r\n return;\r\n }\r\n\r\n events.forEach((event) => {\r\n switch (event.type) {\r\n case 'conversionEvent':\r\n case 'timingMetric':\r\n window.LUX.addData(event.name, event.value);\r\n break;\r\n\r\n case 'markStart':\r\n window.LUX.mark(event.name);\r\n break;\r\n\r\n case 'markEnd':\r\n window.LUX.mark(event.markNameEnd);\r\n window.LUX.measure(event.measureName, event.markNameStart, event.markNameEnd);\r\n break;\r\n default:\r\n break;\r\n }\r\n });\r\n };\r\n }\r\n\r\n getTarget() {\r\n return this.target;\r\n }\r\n}\r\n\r\nexport default SpeedcurveRum;\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched the speedcurve conversion event.\r\n */\r\nclass SpeedcurveConversion {\r\n constructor(name, value) {\r\n this.name = name;\r\n this.value = value;\r\n }\r\n\r\n /**\r\n * The function returns the value of the name property.\r\n * @returns The value of the variable `name`.\r\n */\r\n getName() {\r\n return this.name;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"value\" property.\r\n * @returns The `value` property is being returned.\r\n */\r\n getValue() {\r\n return this.value;\r\n }\r\n}\r\n\r\nexport default SpeedcurveConversion;\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched the speedcurve mark end event.\r\n * This class help us to measure the time when a resource start @SpeedcuveMarkStart and when it ends.\r\n */\r\nclass SpeedcurveMarkEnd {\r\n constructor(measureName, markNameStart, markNameEnd) {\r\n this.measureName = measureName;\r\n this.markNameStart = markNameStart;\r\n this.markNameEnd = markNameEnd;\r\n }\r\n\r\n /**\r\n * The function returns the value of the measureName property.\r\n * @returns The value of the variable `measureName`.\r\n */\r\n getMeasureName() {\r\n return this.measureName;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"markNameStart\" property.\r\n * @returns The `markNameStart` property is being returned.\r\n */\r\n getMarkNameStart() {\r\n return this.markNameStart;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"markNameEnd\" property.\r\n * @returns The `markNameEnd` property is being returned.\r\n */\r\n getMarkNameEnd() {\r\n return this.markNameEnd;\r\n }\r\n}\r\n\r\nexport default SpeedcurveMarkEnd;\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched the speedcurve mark start event.\r\n */\r\nclass SpeedcurveMarkStart {\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * The function returns the value of the name property.\r\n * @returns The value of the variable `name`.\r\n */\r\n getName() {\r\n return this.name;\r\n }\r\n}\r\n\r\nexport default SpeedcurveMarkStart;\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched the speedcurve timing metric.\r\n */\r\nclass SpeedcurveTimingMetric {\r\n constructor(name, value) {\r\n this.name = name;\r\n this.value = value;\r\n }\r\n\r\n /**\r\n * The function returns the value of the name property.\r\n * @returns The value of the variable `name`.\r\n */\r\n getName() {\r\n return this.name;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"value\" property.\r\n * @returns The `value` property is being returned.\r\n */\r\n getValue() {\r\n return this.value;\r\n }\r\n}\r\n\r\nexport default SpeedcurveTimingMetric;\r\n","export default class SpeedcurveEventType {\r\n /**\r\n * This is a static method that returns an instance of the \"Conversion\" class.\r\n * @returns The `Conversion` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'Conversion'` as an argument.\r\n */\r\n static get Conversion() {\r\n return this.getInstance('Conversion');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"MarkStart\" class.\r\n * @returns The `MarkStart` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'MarkStart'` as an argument.\r\n */\r\n static get MarkStart() {\r\n return this.getInstance('MarkStart');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"MarkEnd\" class.\r\n * @returns The `MarkEnd` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'MarkEnd'` as an argument.\r\n */\r\n static get MarkEnd() {\r\n return this.getInstance('MarkEnd');\r\n }\r\n\r\n /**\r\n * This is a static method that returns an instance of the \"TimingMetric\" class.\r\n * @returns The `TimingMetric` instance is being returned. It is obtained by calling the `getInstance`\r\n * method of the current class (`this`) and passing in the string `'TimingMetric'` as an argument.\r\n */\r\n static get TimingMetric() {\r\n return this.getInstance('TimingMetric');\r\n }\r\n\r\n /**\r\n * The function returns a value from a map based on the input name.\r\n *\r\n * @param name - The name of the key in the `statusMap` object that we want to retrieve the value for.\r\n *\r\n * @returns the value of the `statusMap` object that corresponds to the `name` parameter passed to the function.\r\n * If `name` matches one of the keys in `statusMap`, the corresponding value is returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n Conversion: SpeedcurveEventType.Conversion,\r\n MarkStart: SpeedcurveEventType.MarkStart,\r\n MarkEnd: SpeedcurveEventType.MarkEnd,\r\n TimingMetric: SpeedcurveEventType.TimingMetric,\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n /**\r\n * Gets an instance of a SpeedcurveEventType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the SpeedcurveEventType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the SpeedcurveEventType class that is being created.\r\n *\r\n * @returns an instance of `SpeedcurveEventType` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new SpeedcurveEventType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(SpeedcurveEventType, 'instances', { value: {} });\r\n","import SpeedcurveConversion from 'dataTransferObjects/speedcurveConversion';\r\nimport SpeedcurveMarkEnd from 'dataTransferObjects/speedcurveMarkEnd';\r\nimport SpeedcurveMarkStart from 'dataTransferObjects/speedcurveMarkStart';\r\nimport SpeedcurveTimingMetric from 'dataTransferObjects/speedcurveTimingMetric';\r\nimport SpeedcurveEventType from 'enums/speedcurveEvent';\r\nimport { markEnd, markStart, timingMetric, trackConversion } from 'middlewares/speedcurveRum';\r\n\r\n/**\r\n * creates a track conversion using the provided name and value.\r\n */\r\nconst createTrackConversion = ({ name, value }) => trackConversion(() => new SpeedcurveConversion(name, value));\r\n\r\n/**\r\n * creates a Speedcurve mark at the start of a track with the given name.\r\n */\r\nconst createTrackMarkStart = ({ name }) => markStart(() => new SpeedcurveMarkStart(name));\r\n\r\n/**\r\n * creates a Speedcurve mark end based on the provided measure name, start mark name, and end mark name.\r\n */\r\nconst createTrackMarkEnd = ({ measureName, markNameStart, markNameEnd }) =>\r\n markEnd(() => new SpeedcurveMarkEnd(measureName, markNameStart, markNameEnd));\r\n\r\n/**\r\n * creates a new Speedcurve timing metric with a specified name and value.\r\n */\r\nconst createTrackTiming = ({ name, value }) => timingMetric(() => new SpeedcurveTimingMetric(name, value));\r\n\r\n/**\r\n * The getSpeedcurveEvent function returns a GoogleAdsEvent object.\r\n *\r\n */\r\nconst getSpeedcurveEvent = (eventType, events) => {\r\n if (eventType === SpeedcurveEventType.Conversion) {\r\n return events.map((event) => createTrackConversion(event));\r\n }\r\n\r\n if (eventType === SpeedcurveEventType.MarkStart) {\r\n return events.map((event) => createTrackMarkStart(event));\r\n }\r\n\r\n if (eventType === SpeedcurveEventType.MarkEnd) {\r\n return events.map((event) => createTrackMarkEnd(event));\r\n }\r\n\r\n if (eventType === SpeedcurveEventType.TimingMetric) {\r\n return events.map((event) => createTrackTiming(event));\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport default getSpeedcurveEvent;\r\n","/**\r\n * The function \"trackConversion\" returns a function that creates a conversion event object with the\r\n * given name and value.\r\n * @param name - The name parameter is a string that represents the name of the conversion event. It\r\n * could be something like \"purchase\", \"signup\", or \"add_to_cart\".\r\n * @param value - The \"value\" parameter is the value associated with the conversion event. It could be\r\n * a numeric value representing the amount of the conversion, or any other relevant information related\r\n * to the conversion.\r\n * @returns A function is being returned.\r\n */\r\nfunction trackConversion(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n type: 'conversionEvent',\r\n name: event.name,\r\n value: event.value,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * The markStart function returns a function that creates an object with a type of 'markStart' and a\r\n * given name.\r\n * This function is very useful to mark the initial point when a task begin and the measure.\r\n * @param name - The `name` parameter is a string that represents the name of the action being\r\n * dispatched.\r\n * @returns A function is being returned.\r\n */\r\nfunction markStart(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n type: 'markStart',\r\n name: event.name,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * The function `markEnd` returns a function that creates an object with properties `type`,\r\n * `measureName`, `markNameStart`, and `markNameEnd`.\r\n * This function is very useful to mark the end point when a task finish and the measure.\r\n * @param measureName - The name of the measure that the mark belongs to.\r\n * @param markNameStart - The parameter `markNameStart` is the name of the starting mark, it is created by markStart.\r\n * If the markstart is not created it will throw an error.\r\n * @param markNameEnd - The `markNameEnd` parameter is the name of the ending mark. It is used to\r\n * identify the end of a specific section or measurement in the code.\r\n * @returns an arrow function that returns an object with the properties `type`, `measureName`,\r\n * `markNameStart`, and `markNameEnd`.\r\n */\r\nfunction markEnd(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n type: 'markEnd',\r\n measureName: event.measureName,\r\n markNameStart: event.markNameStart,\r\n markNameEnd: event.markNameEnd,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * The timingMetric function returns a function that creates an object with a type, name, and value\r\n * property.\r\n * @param name - The name parameter is a string that represents the name of the timing metric. It is\r\n * used to identify the specific metric being measured.\r\n * @param value - The value parameter is the value of the timing metric that you want to track. It\r\n * could be a number representing the time in milliseconds, seconds, or any other unit of time.\r\n * @returns an arrow function that returns an object with properties `type`, `name`, and `value`.\r\n */\r\nfunction timingMetric(eventDefinition) {\r\n return (action, previousState, nextState) => {\r\n const event = eventDefinition(action, previousState, nextState);\r\n return {\r\n type: 'timingMetric',\r\n name: event.name,\r\n value: event.value,\r\n };\r\n };\r\n}\r\n\r\nexport { trackConversion, markStart, markEnd, timingMetric };\r\n","import { createMiddleware } from 'redux-beacon';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport { SpeedcurveRum } from 'middlewares/speedcurveRum';\r\nimport getSpeedcurveEvent from 'services/speedcurveBuilder';\r\nimport SpeedcurveEventType from 'enums/speedcurveEvent';\r\nimport { speedCurveMarkEnd, speedCurveMarkStart, speedCurveTrackConversion, speedcurveTimingMetric } from './actions';\r\n\r\n/**\r\n * The function `eventsMap` returns an event based on the action type and payload.\r\n * @param action - The `action` parameter is an object that represents an action being dispatched in a\r\n * Redux application. It typically has a `type` property that describes the type of action being\r\n * performed, and a `payload` property that contains any additional data associated with the action.\r\n * @returns The function `eventsMap` returns an event to be tracked.\r\n */\r\nconst eventsMap = (action) => {\r\n const payload = action.payload;\r\n\r\n switch (action.type) {\r\n case speedCurveTrackConversion.type:\r\n return getSpeedcurveEvent(SpeedcurveEventType.Conversion, payload);\r\n\r\n case speedCurveMarkStart.type:\r\n return getSpeedcurveEvent(SpeedcurveEventType.MarkStart, payload);\r\n\r\n case speedCurveMarkEnd.type:\r\n return getSpeedcurveEvent(SpeedcurveEventType.MarkEnd, payload);\r\n\r\n case speedcurveTimingMetric.type:\r\n return getSpeedcurveEvent(SpeedcurveEventType.TimingMetric, payload);\r\n\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\nconst speedcurveRum = new SpeedcurveRum();\r\nconst middleware = createMiddleware(eventsMap, speedcurveRum.getTarget());\r\naddMiddleware(middleware);\r\n","const selectIsInProgress = (state) => state?.speedcurveState?.isInProgress;\r\n\r\nexport default selectIsInProgress;\r\n","const totalDeliveryEvents = {\r\n \"MPC_Result\": {\r\n param: 'buildercommunitylist',\r\n getAttributes: (dataset) => `${dataset.builderId} ${dataset.communityId},` \r\n },\r\n \"COMR\": {\r\n param: 'buildercommunitylist',\r\n getAttributes: (dataset) => `${dataset.builderId} ${dataset.communityId},` \r\n },\r\n \"HOMEHR\": {\r\n param: 'homeList',\r\n getAttributes: (dataset) => {\r\n if (dataset.specId) {\r\n return `${dataset.specId} s,`;\r\n }\r\n\r\n return `${dataset.planId} p,`;\r\n } \r\n }\r\n};\r\n\r\nconst getEvent = (eventLabel, datasets) => {\r\n const event = {};\r\n if (datasets.length !== 0) {\r\n const config = totalDeliveryEvents[eventLabel];\r\n event[config.param] = '';\r\n datasets.forEach(dataset => { \r\n event[config.param] += config.getAttributes(dataset);\r\n });\r\n event[config.param] = event[config.param].slice(0,-1);\r\n // Not best approach, it should be consistent on every card, but as a hotfix urgency I will\r\n // manage it on my next pull request.\r\n event.market = datasets[0].market || datasets[0].marketId;\r\n }\r\n\r\n return event;\r\n};\r\n\r\nexport default getEvent;","import { createSlice } from '@reduxjs/toolkit';\r\nimport getEvent from '../services/processEvents';\r\n\r\n/* Creating a slice of the state for stuff related to the events. */\r\nconst totalDeliveryValueSlice = createSlice({\r\n name: 'totalDeliveryValue',\r\n initialState: {\r\n type: null\r\n },\r\n reducers: {\r\n fireTdvEvent: (state, action) => {\r\n state.type = 'tdv';\r\n const datasets = action.payload.datasets;\r\n const eventLabel = action.payload.event;\r\n state.parameters = getEvent(eventLabel, datasets);\r\n state.event = action.payload.event;\r\n },\r\n trackingEvent: (state, action) => {\r\n state.parameters = action.payload.parameters;\r\n state.isFetchingEvent = true;\r\n },\r\n trackingEventError: (state) => {\r\n state.parameters = null;\r\n state.isFetchingEvent = false;\r\n },\r\n trackingEventFulfilled: (state) => {\r\n state.parameters = null;\r\n state.event = null;\r\n state.type = null;\r\n state.isFetchingEvent = false;\r\n }\r\n },\r\n});\r\n\r\nexport default totalDeliveryValueSlice;\r\n","import { store } from \"@redux/store\";\r\nimport eventTrackingSlice from \"../redux/slices\";\r\n\r\nconst actions = eventTrackingSlice.actions;\r\n\r\nconst dispatchEvent = (event) => {\r\n event.eventType = \"tdvEvent\";\r\n document.body.dispatchEvent(new CustomEvent(\"trackOnDemandEvent\", {\r\n detail: { data: event }\r\n }));\r\n store.dispatch(actions.trackingEventFulfilled());\r\n};\r\n\r\nexport default dispatchEvent;","import { fromFetch } from 'rxjs/fetch';\r\nimport {\r\n totalDeliveryValueCommunityLogger,\r\n totalDeliveryValuePlanLogger,\r\n totalDeliveryValueSpecLogger,\r\n} from 'constants/routes';\r\n\r\nexport const postCommunityLogger$ = (payload) => {\r\n const requestObject = {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ...payload,\r\n }),\r\n selector: (response) => response.text(),\r\n };\r\n\r\n return fromFetch(totalDeliveryValueCommunityLogger, requestObject);\r\n};\r\n\r\nexport const postPlanLogger$ = (payload) => {\r\n const requestObject = {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ...payload,\r\n }),\r\n selector: (response) => response.text(),\r\n };\r\n\r\n return fromFetch(totalDeliveryValuePlanLogger, requestObject);\r\n};\r\n\r\nexport const postSpecLogger$ = (payload) => {\r\n const requestObject = {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ...payload,\r\n }),\r\n selector: (response) => response.text(),\r\n };\r\n\r\n return fromFetch(totalDeliveryValueSpecLogger, requestObject);\r\n};\r\n","import { catchError, filter, of, switchMap } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport eventTrackingSlice from './slices';\r\nimport { postCommunityLogger$, postPlanLogger$, postSpecLogger$ } from '../apis/postEvents';\r\n\r\nconst actions = eventTrackingSlice.actions;\r\n\r\nexport const getPlanLoggerEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.trackingEvent.type),\r\n filter((action) => action?.payload?.parameters?.type === 'plan'),\r\n switchMap((action) =>\r\n postPlanLogger$(action.payload.parameters).pipe(\r\n switchMap(() => of(actions.trackingEventFulfilled())),\r\n catchError((err) => of(actions.trackingEventError(err)))\r\n )\r\n )\r\n );\r\n\r\nexport const getSpecLoggerEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.trackingEvent.type),\r\n filter((action) => action?.payload?.parameters?.type === 'spec'),\r\n switchMap((action) =>\r\n postSpecLogger$(action.payload.parameters).pipe(\r\n switchMap(() => of(actions.trackingEventFulfilled())),\r\n catchError((err) => of(actions.trackingEventError(err)))\r\n )\r\n )\r\n );\r\n\r\n export const getCommunityLoggerEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.trackingEvent.type),\r\n filter((action) => action?.payload?.parameters?.type === 'community' ||\r\n action?.payload?.parameters?.type === 'buildeablePlan'),\r\n switchMap((action) =>\r\n postCommunityLogger$(action.payload.parameters).pipe(\r\n switchMap(() => of(actions.trackingEventFulfilled())),\r\n catchError((err) => of(actions.trackingEventError(err)))\r\n )\r\n )\r\n );","import { epic$, store$ } from \"@redux/store\";\r\nimport { map, filter, distinctUntilChanged } from \"rxjs\";\r\nimport dispatchEvent from \"./components/trackOnDemand\";\r\nimport totalDeliveryValueSlice from \"./redux/slices\";\r\nimport { getCommunityLoggerEpic, getPlanLoggerEpic, getSpecLoggerEpic } from \"./redux/epics\";\r\n\r\nconst eventTrackingSelector = (state) => state?.totalDeliveryValue;\r\nconst isTdvEvent = (eventTracking) => eventTracking?.type === 'tdv';\r\nconst { actions: totalDeliveryValueActions, reducer: totalDeliveryValueReducers} = totalDeliveryValueSlice;\r\n\r\n\r\nconst firedTdvEvents = (eventTracking) => {\r\n const event = {\r\n label: eventTracking.event,\r\n ...eventTracking.parameters\r\n }\r\n dispatchEvent(event);\r\n};\r\n\r\nstore$.pipe(\r\n map(eventTrackingSelector),\r\n filter(isTdvEvent),\r\n distinctUntilChanged()\r\n ).subscribe(firedTdvEvents);\r\n\r\nexport {\r\n totalDeliveryValueActions,\r\n totalDeliveryValueReducers\r\n};\r\n\r\nepic$.next(getPlanLoggerEpic);\r\nepic$.next(getSpecLoggerEpic);\r\nepic$.next(getCommunityLoggerEpic);","/** Constant partner information\r\n * The `Object.freeze()` method is used to make the object immutable, meaning that\r\n * its properties cannot be modified or deleted.\r\n */\r\nconst NewHomeSourcePartner = Object.freeze({\r\n partnerId: 1,\r\n partnerName: 'NewHomeSource',\r\n brandPartnerName: 'NewHomeSource',\r\n});\r\n\r\nexport default NewHomeSourcePartner;\r\n","/**\r\n * Gets when the word \"Mobile\" exists inside of the string to match.\r\n * \"\\b\" matches a word boundary position. With double \"\\b\", we make sure it is a whole word and\r\n * not a substring from other word.\r\n * \"Mobile\" matches this same word on the string.\r\n * Regex used for the changes on {@link https://builderhomesite.atlassian.net/browse/NHS20-2125} to be able to\r\n * identify the mobile devices by its user agent.\r\n */\r\nconst isMobileUserAgent = /\\bMobile\\b/\r\n\r\n/**\r\n * Determines if the current device user agent is mobile.\r\n * The current way to determine it is to check the User Agent string, and verify\r\n * if it contains the word \"Mobile\" on there.\r\n * By business, we manage the tablet and desktop devices as desktop.\r\n * @returns A bool value indicating whether the device user agent is mobile.\r\n */\r\nconst matchesMobileUserAgent = () => isMobileUserAgent.test(navigator.userAgent);\r\n\r\nexport default matchesMobileUserAgent;","import { createSelector } from '@reduxjs/toolkit';\r\nimport { selectSearchResultFacetsTrackingCommonProperties } from 'features/searchResultsFacets';\r\nimport { selectSearchMapTrackingCommonProperties } from 'features/searchResultsMap';\r\nimport { selectUserLocation, selectUserProfileTrackingCommonProperties } from 'features/userProfile';\r\nimport { selectUtmTrackingCommonProperties } from 'features/utm';\r\n\r\n/** This code is defining a selector which its main purpuse is to combine in a single object\r\n * a set of properties from different features.\r\n * The selector takes two other selector as arguments.\r\n * these selctores provide a set of properties from different features\r\n * this selector is inteded to be consumed by different events builders such as segment ot g4.\r\n */\r\nexport const selectTrackingCommonProperties = createSelector(\r\n selectSearchResultFacetsTrackingCommonProperties,\r\n selectUserProfileTrackingCommonProperties,\r\n selectUserLocation,\r\n selectUtmTrackingCommonProperties,\r\n selectSearchMapTrackingCommonProperties,\r\n (facets, userProfile, userLocation, utm, map) => ({\r\n marketId: facets.location?.marketId,\r\n marketName: facets.location?.marketName,\r\n city: facets.location?.city,\r\n stateAbbreviation: facets.location?.marketState,\r\n stateName: facets.location?.marketStateName,\r\n zip: facets.location?.zip,\r\n brandId: facets.brandId,\r\n brandName: facets.brandName,\r\n userId: userProfile.userId,\r\n name: userProfile.name,\r\n email: userProfile.email,\r\n phone: userProfile.phone,\r\n userZip: userProfile.zip,\r\n livesOutside: userProfile.livesOutside,\r\n favorites: userProfile.favorites,\r\n neustarSegment: userProfile.neustarSegment,\r\n neustarZip: userProfile.neustarZip,\r\n neustarAge: userProfile.neustarAge,\r\n neustarGender: userProfile.neustarGender,\r\n facets: facets.facetsList,\r\n price: facets?.price,\r\n schools: facets.schools,\r\n listingCount: facets.listingCount,\r\n pageNumber: facets.pageNumber,\r\n moveInDate: facets.moveInDate,\r\n searchLocation: facets.location,\r\n userLocationCity: userLocation.userLocationCity,\r\n userLocationCountry: userLocation.userLocationCountry,\r\n userLocationMarketId: userLocation.userLocationMarketId,\r\n userLocationState: userLocation.userLocationState,\r\n userLocationZipCode: userLocation.userLocationZipCode,\r\n isLoggedIn: userProfile.isLoggedIn,\r\n referCode: utm.refer,\r\n isSearchWithinMap: map.isSearchWithinMap,\r\n })\r\n);\r\n\r\nexport default selectTrackingCommonProperties;\r\n","import merge from 'deepmerge';\r\nimport NewHomeSourcePartner from 'constants/partner';\r\nimport matchesMobileUserAgent from 'modules/deviceCapabilities';\r\nimport { selectUrlSubdirectory } from 'features/routing';\r\nimport PageType from 'enums/pageType';\r\nimport { selectTrackingCommonProperties } from './redux/selectors';\r\n\r\nconst businnessInformationElement = document.querySelector(\"[data-component='business-information-data']\");\r\nconst businnessInformation = JSON.parse(businnessInformationElement.innerHTML);\r\n\r\nconst getResponseVersion = (isMobileDevice) => (isMobileDevice ? 'M' : 'D');\r\n\r\n/**\r\n * The getCommonPropertiesFromOtherSources function returns an object containing the properties obtained from:\r\n * sources such as html, or consts.\r\n * @return An object with the properties not stored in redux.\r\n */\r\nconst getCommonPropertiesFromOtherSources = (store) => {\r\n const urlSubdirectory = selectUrlSubdirectory(store);\r\n const pageType = PageType.fromKey(urlSubdirectory).toString();\r\n const isMobileUserAgent = matchesMobileUserAgent();\r\n const properties = {\r\n pageType,\r\n buildCodeVersion: businnessInformation.buildCodeVersion,\r\n responseVersion: getResponseVersion(isMobileUserAgent),\r\n testVersion: NewHomeSourcePartner.testVersion,\r\n partnerId: NewHomeSourcePartner.partnerId,\r\n partnerName: NewHomeSourcePartner.partnerName,\r\n brandPartnerName: NewHomeSourcePartner.brandPartnerName,\r\n };\r\n\r\n return properties;\r\n};\r\n\r\n/**\r\n * The function returns common tracking properties that are stored in the redux store.\r\n * @param store - The `store` parameter is likely an object representing a store or a state management\r\n * @returns an object containing the properties stored in a redux store.\r\n */\r\nconst getCommonPropertiesFromStore = (store) => {\r\n const trackingCommonPropertiesFromStore = selectTrackingCommonProperties(store);\r\n\r\n return trackingCommonPropertiesFromStore;\r\n};\r\n\r\n/**\r\n * The getTrackingCommonProperties function returns tracking common properties from the Redux store.\r\n * this uses a selector which takes from other features selectors a set of properties and combines them.\r\n * The idea is that this selctor can be used for different tracking consumets such as segment, g4.\r\n * by a respective object builder which will filter that properties as needed.\r\n * @param store Access the redux store\r\n *\r\n * @return An object of properties.\r\n */\r\nconst getTrackingCommonProperties = (store) => {\r\n const trackingCommonPropertiesFromStore = getCommonPropertiesFromStore(store);\r\n const trackingCommonPropertiesFromOtherSources = getCommonPropertiesFromOtherSources(store);\r\n const trackingCommonProperties = merge(trackingCommonPropertiesFromStore, trackingCommonPropertiesFromOtherSources);\r\n\r\n return trackingCommonProperties;\r\n};\r\n\r\nexport default getTrackingCommonProperties;\r\n","import FavoriteType from \"../enums/favoriteType\";\r\n\r\n/**\r\n * getListingInformationForPaidSpec: Gets all the listing information that will be used to add a new Pending Save value.\r\n * @param {Object} dataset All the information related to the Paid Spec Card.\r\n * @returns An object with the required listing information for Paid Spec Listings for the new Pending Save value.\r\n */\r\nfunction getListingInformationForPaidSpec(dataset) {\r\n const {\r\n specId, marketId, marketName, builderId, brandName, communityName, communityId, imageUrl,\r\n price, city, stateAbbreviation, zip, homeStatus, isBasic\r\n } = dataset;\r\n\r\n return {\r\n marketId,\r\n marketName,\r\n builderId,\r\n brandName,\r\n communityId,\r\n communityName,\r\n imageUrl,\r\n isBasic,\r\n homeStatus,\r\n price,\r\n id: specId,\r\n city,\r\n stateAbbreviation,\r\n zip,\r\n };\r\n}\r\n\r\n/**\r\n * getListingInformationForPaidCommunity: Gets all the listing information that will be used to add a\r\n * new Pending Save value.\r\n * @param {Object} dataset All the information related to the Paid Community Card.\r\n * @returns An object with the required listing information for Paid Community Listings for the new Pending Save value.\r\n */\r\nfunction getListingInformationForPaidCommunity(dataset) {\r\n const {\r\n id, marketId, marketName, builderId, brandName, communityName, marketingStatusLabel, isBasic, imageUrl,\r\n priceHigh, priceLow, city, stateAbbreviation, zip\r\n } = dataset;\r\n\r\n return {\r\n id,\r\n marketId,\r\n marketName,\r\n builderId,\r\n brandName,\r\n name: communityName,\r\n marketingStatusLabel,\r\n isBasic,\r\n imageUrl,\r\n priceHigh,\r\n priceLow,\r\n city,\r\n stateAbbreviation,\r\n zip\r\n };\r\n}\r\n\r\n/**\r\n * getListingInformationForPaidPlan: Gets all the listing information that will be used to add a new Pending Save value.\r\n * @param {Object} dataset All the information related to the Paid Plan Card.\r\n * @returns An object with the required listing information for Paid Plan Listings for the new Pending Save value.\r\n */\r\nfunction getListingInformationForPaidPlan(dataset) {\r\n const {\r\n planId, marketId, marketName, builderId, brandName, communityName, communityId, imageUrl,\r\n price, city, stateAbbreviation, zip, homeStatus, isBasic\r\n } = dataset;\r\n\r\n return {\r\n marketId,\r\n marketName,\r\n builderId,\r\n brandName,\r\n communityId,\r\n communityName,\r\n imageUrl,\r\n isBasic,\r\n homeStatus,\r\n price,\r\n id: planId,\r\n city,\r\n stateAbbreviation,\r\n zip,\r\n };\r\n}\r\n\r\nconst listingInformationGetter = new Map();\r\n\r\nlistingInformationGetter.set(FavoriteType.Community, getListingInformationForPaidCommunity);\r\nlistingInformationGetter.set(FavoriteType.Spec, getListingInformationForPaidSpec);\r\nlistingInformationGetter.set(FavoriteType.Plan, getListingInformationForPaidPlan);\r\n\r\nexport default function getListingInformationFromDataset(dataset) {\r\n const listingType = FavoriteType.fromKey(dataset.type);\r\n const getListingInformation = listingInformationGetter.get(listingType);\r\n\r\n if (!getListingInformation) {\r\n return {}\r\n }\r\n\r\n return getListingInformation(dataset);\r\n}","import { map, filter, take, distinctUntilChanged } from 'rxjs';\r\nimport { store$, store } from '@redux/store';\r\nimport { userProfileSlice } from '../redux/slices';\r\nimport {\r\n selectFavorites,\r\n selectIsLoggedIn,\r\n selectIsProfileFavoritesLoaded,\r\n selectUserIdAndPendingSaves\r\n} from '../redux/selectors';\r\nimport FavoriteType from '../enums/favoriteType';\r\nimport onOpenModal from './modal';\r\nimport getListingInformationFromDataset from '../services/getListingInformationForPendingSave';\r\n\r\nconst actions = userProfileSlice.actions;\r\n\r\n// Get the favorite information from the card\r\nfunction getCardInformation(card) {\r\n const { type } = card.dataset;\r\n const url = new URL(card.querySelector('a').href).pathname;\r\n const listingInformation = getListingInformationFromDataset(card.dataset)\r\n\r\n return {\r\n listingInformation,\r\n type: FavoriteType.fromKey(type).type,\r\n url,\r\n };\r\n }\r\n\r\n// Check if a favorite is already saved\r\nfunction isFavoriteSaved(id, favorites) {\r\n return favorites.some(favorite => favorite.listingId === Number(id));\r\n}\r\n\r\n// Dispatch the save/delete action\r\nfunction dispatchSaveOrDeleteAction(payload, isSaved) {\r\n const action = isSaved ? actions.deleteFavorite(payload) : actions.saveFavorite(payload);\r\n store.dispatch(action);\r\n}\r\n\r\n/**\r\n * handles whether to save or delete a favorite from the user's profile on user's click.\r\n * @param {HTMLElement} icon the icon clicked by the user.\r\n */\r\nfunction toggleFavorite(icon){\r\n const card = icon.closest('[data-card]');\r\n const { userId, favorites } = store.getState().userProfile;\r\n const cardInfo = getCardInformation(card);\r\n const isSaved = isFavoriteSaved(cardInfo.listingInformation.id, favorites);\r\n const payload = { ...cardInfo, userId };\r\n\r\n dispatchSaveOrDeleteAction(payload, isSaved);\r\n}\r\n\r\n/**\r\n * updates the favorites icon on each card to show if the listing is already saved as a favorite.\r\n * @param {Array[Object]} favorites list of favorites from the user's profile.\r\n */\r\nfunction updateSavedFavorites(favorites) {\r\n const favoritesIds = favorites?.map(favorite => favorite.listingId) ?? [];\r\n\r\n const cards = document.querySelectorAll('[data-card]') ?? [];\r\n\r\n cards.forEach(card => {\r\n const { id } = card.dataset;\r\n const isSaved = favoritesIds.includes(Number(id));\r\n const favorite = card.querySelector('.icon__save');\r\n\r\n if(favorite){\r\n favorite.classList?.toggle('icon__saved', isSaved);\r\n if (isSaved) {\r\n favorite.setAttribute('data-qa', 'favorite_saved');\r\n }\r\n }\r\n })\r\n}\r\n\r\n// Save pending favorites on initial load to handle logged-out users \r\n// that have favorites saved in the cookie from before they logged-in.\r\nfunction savePendingFavorites(data) {\r\n const { userId, pendingSaves } = data;\r\n \r\n if(pendingSaves){\r\n pendingSaves.forEach(pendingSave => {\r\n\r\n // update the favorite with the new user id.\r\n store.dispatch(actions.saveFavorite({ ...pendingSave, userId }));\r\n });\r\n }\r\n}\r\n\r\n\r\n/*\r\nSubscribe to the store$ observable to listen for changes. When the user is logged in and the favorites profile\r\nis loaded, map the favorites and compare with the lasted version. If the favorites change, update the\r\nfavorite UI.\r\n*/\r\nstore$.pipe(\r\n filter(selectIsLoggedIn),\r\n filter(selectIsProfileFavoritesLoaded),\r\n map(selectFavorites),\r\n distinctUntilChanged((previous, current) => JSON.stringify(previous) === JSON.stringify(current))\r\n).subscribe(updateSavedFavorites);\r\n\r\n/*\r\nSubscribe to the store$ observable to listen for changes. When the user is logged in and the favorites profile\r\nis loaded, map the pending favorites and the user id, because this scenarios handles and save the pending favcorites\r\nwhen the user is not logged in. Take only the first value emmited in the observable.\r\n*/\r\nstore$.pipe(\r\n filter(selectIsLoggedIn),\r\n filter(selectIsProfileFavoritesLoaded),\r\n map(selectUserIdAndPendingSaves),\r\n take(1)\r\n).subscribe(savePendingFavorites);\r\n\r\n/**\r\n * Using event delegation to handle clicks on the favorites icon.\r\n */\r\ndocument.body.addEventListener('click', (event) => {\r\n const icon = event.target.closest('.icon__save');\r\n const state = store.getState();\r\n const isLogin = state?.userProfile?.isLogin;\r\n\r\n // if the click was inside the icon, save or delete the favorite.\r\n if (icon) {\r\n toggleFavorite(icon)\r\n\r\n if (!isLogin) {\r\n onOpenModal(event);\r\n }\r\n }\r\n});\r\n\r\nexport default updateSavedFavorites;","/**\r\n * This module encapsulates Google One Tap functionality.\r\n * Use this module as a facade so interactions with Google One Tap library are simplified for any subject interest\r\n * in accessing Google One Tap capabilities.\r\n * Google One Tap is a user authentication and sign-in solution provided by Google.\r\n * It allows users to sign in to websites and apps using their Google account with a single tap,\r\n * providing a streamlined and secure authentication experience. With Google One Tap, users can\r\n * easily access websites without the need to remember and enter complex passwords.\r\n */\r\n\r\nconst googleOneTapInstance = {\r\n isGoogleOneTapLoaded: false,\r\n isGoogleOneTapLoading: false,\r\n clientId: null,\r\n onAuthenticated: null,\r\n};\r\n\r\n// Interval to sample waiting for the load event; this number is arbitrary.\r\nconst googleOneTapLoadSampleRate = 100;\r\n\r\n/**\r\n * If the Google One Tap API fails to load, set the loading and loaded flags to false and reject the promise.\r\n * @param reject - A function that rejects the promise.\r\n */\r\nconst onGoogleOneTapError = (reject) => {\r\n googleOneTapInstance.isGoogleOneTapLoading = false;\r\n googleOneTapInstance.isGoogleOneTapLoaded = false;\r\n reject(new Error(`Unable to load Google One Tap API.`));\r\n};\r\n\r\n/**\r\n * When the Google One Tap API is loaded, set the isGoogleOneTapLoaded property of the googleOneTapInstance object to\r\n * true and resolve the promise.\r\n * @param resolve - A function that is called when the promise is resolved.\r\n */\r\nconst onGoogleOneTapLoaded = (resolve) => {\r\n window.google.accounts.id.initialize({\r\n client_id: googleOneTapInstance.clientId,\r\n callback: googleOneTapInstance.onAuthenticated,\r\n cancel_on_tap_outside: false,\r\n // Due to Intelligent Tracking Prevention (ITP), the normal One Tap UX doesn't work on\r\n // Chrome on iOS, Safari, or Firefox. A different UX is provided instead on these browsers.\r\n itp_support: true,\r\n use_fedcm_for_prompt: true,\r\n });\r\n googleOneTapInstance.isGoogleOneTapLoaded = true;\r\n resolve();\r\n};\r\n\r\n/**\r\n * Create a script element, set its source to the Google One Tap source,\r\n * set its onerror property to a function that rejects the promise,\r\n * set its onload property to a function that resolves the promise.\r\n * @param resolve - The function to call when the script has loaded.\r\n * @param reject - A function that is called when the promise is rejected.\r\n */\r\nconst appendGoogleOneTapScript = (resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://accounts.google.com/gsi/client';\r\n script.async = true;\r\n script.defer = true;\r\n script.onerror = onGoogleOneTapError.bind(this, reject);\r\n script.onload = onGoogleOneTapLoaded.bind(this, resolve);\r\n document.head.appendChild(script);\r\n};\r\n\r\n/**\r\n * If the Google One Tap is loaded, resolve the promise.\r\n * If not, wait the amount of time from googleOneTapLoadSampleRate and try again.\r\n * @param resolve - The resolve function of the promise.\r\n */\r\nconst isGoogleOneTapLoaded = (resolve) => {\r\n if (googleOneTapInstance.isGoogleOneTapLoaded) {\r\n resolve();\r\n } else {\r\n setTimeout(isGoogleOneTapLoaded.bind(null, resolve), googleOneTapLoadSampleRate);\r\n }\r\n};\r\n\r\n/**\r\n * Wait the amount of time from googleOneTapLoadSampleRate for Google One Tap to load, and then resolve the promise.\r\n * @returns A promise that will resolve when the Google One Tap API is loaded.\r\n */\r\nconst waitForGoogleOneTap = () =>\r\n new Promise((resolve) => {\r\n setTimeout(isGoogleOneTapLoaded.bind(null, resolve), googleOneTapLoadSampleRate);\r\n });\r\n\r\n/**\r\n * loadGoogleOneTap: if the Google One Tap instance is not loading, then load it.\r\n * If it is loading, wait for it to load.\r\n * If it is loaded, resolve the promise\r\n * @param googleOneTapLoaded - A function that is called when the Google One Tap instance has loaded.\r\n * @param googleOneTapErrored - A function that will be called if the Google One Tap script fails to load.\r\n * @returns A promise.\r\n */\r\nexport function loadGoogleOneTap({ onLibraryLoaded, onLibraryErrored, onAuthenticated, clientId }) {\r\n googleOneTapInstance.clientId = clientId;\r\n googleOneTapInstance.onAuthenticated = onAuthenticated;\r\n\r\n if (!googleOneTapInstance.isGoogleOneTapLoading) {\r\n // Set the Google One Tap instance as loading to prevent multiple requests.\r\n googleOneTapInstance.isGoogleOneTapLoading = true;\r\n return new Promise(appendGoogleOneTapScript).then(onLibraryLoaded).catch(onLibraryErrored);\r\n }\r\n\r\n if (googleOneTapInstance.isGoogleOneTapLoaded) {\r\n // If the Google One Tap instance is already loaded resolve the promise.\r\n return Promise.resolve().then(onLibraryLoaded).catch(onLibraryErrored);\r\n }\r\n\r\n // Otherwise wait to review if the Google One Tap instance has loaded.\r\n return waitForGoogleOneTap().then(onLibraryLoaded).catch(onLibraryErrored);\r\n}\r\n\r\n/**\r\n * showGoogleOneTapModal: this function will prompt the google one tap login modal to the user.\r\n */\r\nexport function showGoogleOneTapModal() {\r\n window.google.accounts.id.prompt();\r\n}\r\n\r\n/**\r\n * Hides the Google One Tap modal.\r\n */\r\nexport function hideGoogleOneTapModal() {\r\n window.google?.accounts?.id?.cancel();\r\n}\r\n","import { catchError, switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { googleOneTapLogin } from 'constants/routes'\r\n\r\n/**\r\n * loginUserWithGoogleOneTap: this function returns a fromFetch observable. This observable is in charge of\r\n * posting user authentication information from Google One Tap to NewHomeSource so the page can sucessfully\r\n * authenticate an user coming from Google One Tap authentication widget.\r\n * @param {*} parameters a set of information retrieved from Google One Tap containing information used to\r\n * authenticate an user in NewHomeSource.\r\n * @returns \r\n */\r\nconst loginUserWithGoogleOneTap = (parameters) => fromFetch(googleOneTapLogin, {\r\n method: 'POST',\r\n body: JSON.stringify(parameters),\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n }).pipe(\r\n switchMap((response) => response.json()),\r\n catchError(() => {}),\r\n );\r\n\r\nexport default loginUserWithGoogleOneTap;","/**\r\n * parseJsonWebToken: This function is designed to parse a JSON Web Token (JWT) by extracting and decoding its payload.\r\n * JWTs consist of three parts: a header, a payload, and a signature, each separated by a period ('.').\r\n * This function focuses on the payload, which is base64-encoded.\r\n * The function decodes the base64-encoded payload and returns the corresponding JSON object.\r\n * @param {string} token the JWT from which the payload needs to be extracted and decoded.\r\n * @returns a json object containing the payload information retrieved from the JWT.\r\n */\r\nconst parseJsonWebToken = (token) => {\r\n const base64Url = token.split('.')[1];\r\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\r\n const jsonPayload = decodeURIComponent(window.atob(base64)\r\n .split('')\r\n .map((character) => '%' + ('00' + character.charCodeAt(0).toString(16)).slice(-2))\r\n .join(''));\r\n\r\n return JSON.parse(jsonPayload);\r\n}\r\n\r\nexport default parseJsonWebToken;","/**\r\n * This component works together with the information streamed from the store to accomplish functionality\r\n * related with the authentication in NewHomeSource using Google One Tap as the provider.\r\n * Interactions with Google One Tap are encapsulated in the googleOneTapLibrary.js facade, use this\r\n * component as the link between the interaction of the user in the page and that facade.\r\n */\r\n\r\nimport { store$, store } from '@redux/store';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { combineLatest, distinctUntilChanged, filter, fromEvent, map, take } from 'rxjs';\r\nimport { hideGoogleOneTapModal, loadGoogleOneTap, showGoogleOneTapModal } from 'libraries/googleOneTapLibrary';\r\nimport { selectConfigurationGoogleOneTapClientId, selectModal } from 'layout/redux/selectors';\r\nimport { selectIsLoggedIn, selectGoogleOneTapLibraryLoadingStatus } from '../redux/selectors';\r\nimport { authenticationSlice } from '../redux/slices';\r\nimport loginUserWithGoogleOneTap from '../apis/loginWithGoogleOneTap';\r\nimport parseJsonWebToken from '../services/parseJsonWebToken';\r\n\r\nconst authActions = authenticationSlice.actions;\r\n\r\nconst onLibraryLoaded = () => store.dispatch(authActions.googleOneTapLibraryLoadingStatus(LoadingStatus.Succeeded));\r\nconst onLibraryErrored = () => store.dispatch(authActions.googleOneTapLibraryLoadingStatus(LoadingStatus.Failed));\r\n\r\nconst onPageLoaded$ = fromEvent(window, 'load');\r\n\r\n/**\r\n * onAuthenticated: callback executed when Google One Tap successfully authenticated an user.\r\n * @param {object} googleResponse containing the information needed to authenticate the user in NewHomeSource.\r\n */\r\nconst onAuthenticated = async (googleResponse) => {\r\n const idToken = parseJsonWebToken(googleResponse.credential);\r\n const parameters = {\r\n payload: {\r\n locale: idToken.locale,\r\n picture: idToken.picture,\r\n email: idToken.email,\r\n name: idToken.name,\r\n givenName: idToken.given_name,\r\n familyName: idToken.family_name,\r\n subject: idToken.sub,\r\n audience: idToken.aud,\r\n emailVerified: idToken.email_verified,\r\n notBeforeTimeSeconds: idToken.nbf,\r\n hostedDomain: idToken.hd,\r\n issuer: idToken.iss,\r\n issuedAtTimeSeconds: idToken.iat,\r\n expirationTimeSeconds: idToken.exp,\r\n jwtId: idToken.jti,\r\n },\r\n keepMeLogged: true,\r\n };\r\n\r\n loginUserWithGoogleOneTap(parameters).subscribe((data) => {\r\n if (data?.Success) {\r\n window.location.reload();\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Subscribe to the store$ observable to listen for changes.\r\n * If the user is not logged in and the Google One Tap library is not loaded, we proceed\r\n * and load the library so we gain access to Google One Tap capabilities.\r\n * This obserbable streams just one time since every time a user logges in/out a full\r\n * page reload happens, so there is no need to keep listening to the store$ while the user\r\n * navigates in NewHomeSource.\r\n */\r\nconst googleOneTapConfiguration$ = store$.pipe(\r\n filter((state) => selectIsLoggedIn(state) === false),\r\n filter((state) => selectGoogleOneTapLibraryLoadingStatus(state) !== LoadingStatus.Succeeded.name),\r\n map((state) => ({\r\n onLibraryLoaded,\r\n onLibraryErrored,\r\n onAuthenticated,\r\n clientId: selectConfigurationGoogleOneTapClientId(state),\r\n })),\r\n distinctUntilChanged(),\r\n filter((googleOneTapInformation) => !!googleOneTapInformation.clientId),\r\n take(1)\r\n);\r\n\r\ncombineLatest([googleOneTapConfiguration$, onPageLoaded$])\r\n .pipe(map(([googleOneTapConfiguration]) => googleOneTapConfiguration))\r\n .subscribe(loadGoogleOneTap);\r\n\r\n/**\r\n * Subscribe to the store$ observable to listen for changes.\r\n * If the user is not logged in and Google One Tap library is loaded, then we prompt the modal\r\n * inviting the user to log in using Google One Tap.\r\n * This obserbable streams just one time since every time a user logges in/out a full\r\n * page reload happens, so there is no need to keep listening to the store$ while the user\r\n * navigates in NewHomeSource.\r\n */\r\nstore$\r\n .pipe(\r\n filter((state) => selectIsLoggedIn(state) === false),\r\n filter((state) => selectGoogleOneTapLibraryLoadingStatus(state) === LoadingStatus.Succeeded.name),\r\n take(1)\r\n )\r\n .subscribe(showGoogleOneTapModal);\r\n\r\n/**\r\n * Subscribe to the store$ observable to hide the Google One Tap modal\r\n * when a modal is opened.\r\n */\r\nstore$\r\n .pipe(\r\n filter((state) => Boolean(selectModal(state))),\r\n take(1)\r\n )\r\n .subscribe(hideGoogleOneTapModal);\r\n","/**\r\n * @public\r\n * getValidationCallback: get the validator callback to each fields in Sign Up modal.\r\n * @param {Object} signUpField with the information of the field \r\n * \r\n * @returns {Function} that will be execute when form need to be validate.\r\n */\r\nfunction getValidationCallback(signUpField) {\r\n switch(signUpField.name) {\r\n case 'FirstName':\r\n case 'LastName': {\r\n const regex = new RegExp(signUpField.validator.pattern);\r\n const hint = signUpField.validator.hint;\r\n return (name) => ({\r\n valid: regex.test(name) && name.length >= 2,\r\n hint\r\n });\r\n }\r\n case 'PostalCode': {\r\n const hint = signUpField.validator.hint;\r\n return (name) => ({\r\n valid: name.length === 0 || name.length === 5,\r\n hint\r\n });\r\n }\r\n default:\r\n return () => (true);\r\n }\r\n}\r\n\r\nexport default getValidationCallback;","import getValidationCallback from \"./signUpValidator\";\r\n\r\nconst configElement = document.querySelector('[data-auth0-parameter]');\r\nconst keepMeLoggedSection = document.querySelector('[data-keep-me-logged-section]');\r\nconst legalContentSection = document.querySelector('[data-legal-section]');\r\nconst configObject = JSON.parse(configElement.innerText);\r\nconfigObject.keepMeLoggedSection = keepMeLoggedSection;\r\nconfigObject.legalContentSection = legalContentSection;\r\nconfigObject.options.additionalSignUpFields.forEach((signUpField) => {\r\n const callback = getValidationCallback(signUpField);\r\n signUpField.validator = callback;\r\n});\r\n\r\n/**\r\n * @public\r\n * getBaseConfig: get the configuration object to show authentication modal.\r\n *\r\n * @returns { Object } with the configuration of authentication.\r\n */\r\nfunction getBaseConfig() {\r\n return Object.assign({}, configObject);\r\n}\r\n\r\nexport default getBaseConfig;\r\n","import { store$, store } from '@redux/store';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { createAuthInstance, showModal } from 'libraries/authLibrary';\r\nimport { isAuthLibraryLoaded, isAuthModalOpen } from '../constants/auth0Constants';\r\nimport { modalSlice, authenticationSlice } from '../redux/slices';\r\nimport getBaseConfig from './auth0BaseConfiguration';\r\n\r\nconst { actions: modalActions, reducer: modalReducers } = modalSlice;\r\nconst { reducer: authenticationReducers } = authenticationSlice\r\n\r\nconst configuration = getBaseConfig();\r\nconst onCloseModal = () => store.dispatch(modalActions.onClose());\r\nconst initAuthentication = () => createAuthInstance(configuration, onCloseModal);\r\nconst openModal = () => showModal();\r\nconst userIdSelector = (state) => state?.userProfile?.userId;\r\nconst invalidValuesFilter = (value) => !!value;\r\n\r\nconst storeUserId = (userId) => { \r\n localStorage.setItem('UserId', userId)\r\n };\r\n\r\n // We have to execute initAuthentication when the modal is not opened.\r\n // So it means we need to track isAuthModalOpen.\r\n // Where if it was already on true, we should not continue the flow.\r\n // If it was on false, so we should check if the new isAuthModalOpen value is true or false to determine\r\n // whether to continue the flow.\r\nstore$.pipe(\r\n filter(isAuthLibraryLoaded),\r\n map(isAuthModalOpen),\r\n distinctUntilChanged(),\r\n filter(Boolean))\r\n .subscribe(initAuthentication);\r\n\r\nstore$.pipe(\r\n filter(isAuthModalOpen),\r\n distinctUntilChanged())\r\n .subscribe(openModal);\r\n\r\nstore$.pipe(\r\n map(userIdSelector),\r\n distinctUntilChanged(),\r\n filter(invalidValuesFilter)\r\n ).subscribe(storeUserId);\r\n\r\nstore.injectReducer('modal', modalReducers);\r\nstore.injectReducer('authentication', authenticationReducers);","import { store, store$ } from \"@redux/store\";\r\nimport { loadAuth0 } from \"libraries/authLibrary\";\r\nimport { filter, fromEvent, take } from \"rxjs\";\r\nimport { authenticationSlice, modalSlice } from '../redux/slices';\r\nimport { isAuthLibraryNotLoaded } from '../constants/auth0Constants';\r\n\r\nconst { actions: authenticationActions } = authenticationSlice;\r\nconst { actions: modalActions } = modalSlice;\r\n\r\n// Dispatch the redux slices.\r\nconst onAuthLibraryLoaded = () => store.dispatch(authenticationActions.authLibraryLoaded());\r\nconst onAuthLibraryErrored = (value) => store.dispatch(authenticationActions.authLibraryErrored(value));\r\nconst openModal = () => store.dispatch(modalActions.onOpen());\r\n\r\n// check if user is logged in\r\nconst isUserNotLogin = (state) => state?.userProfile?.isLogin === false;\r\n\r\n// check if the target for the event is a sign-in component.\r\nconst isSignInElement = (event) => event?.target?.closest('[data-component=\"sign-in\"]');\r\n\r\n/**\r\n * @private\r\n * onOpenModal: open the authentication modal.\r\n *\r\n */\r\nfunction onOpenModal(event) {\r\n event.preventDefault();\r\n loadAuth0(onAuthLibraryLoaded, onAuthLibraryErrored).then(openModal);\r\n}\r\n\r\n/**\r\n * @private\r\n * attachSignUpClick: method to attach when user is not loging and need to open auth0 modal.\r\n * \r\n */\r\nconst attachSignUpClick = () => {\r\n // user event delegation listen to click on a sign-in component\r\n fromEvent(document.body, 'click').pipe(\r\n filter(isSignInElement),\r\n filter(Boolean)\r\n ).subscribe(onOpenModal);\r\n}\r\n\r\nstore$.pipe(\r\n filter(isUserNotLogin),\r\n filter(isAuthLibraryNotLoaded),\r\n take(1))\r\n .subscribe(attachSignUpClick);\r\n\r\nexport default onOpenModal;","import { fromEvent, map } from 'rxjs';\r\nimport { store } from '@redux/store';\r\nimport { userProfileSlice } from '../redux/slices';\r\n\r\nconst actions = userProfileSlice.actions;\r\n\r\nconst updateNeustarInformation = (response) => store.dispatch(actions.updateNeustarInformation(response));\r\n\r\nfromEvent(document.body, 'neustarLoaded')\r\n .pipe(map((event) => event.detail))\r\n .subscribe(updateNeustarInformation);\r\n","/**\r\n * Module to manage cookies in the site.\r\n * \r\n * The main difference of this cookieManager between legacies files in GlobalResources14 is that\r\n * those older modules should only be used on pages that use vanillaJS and requireJS for module loading.\r\n */\r\nconst partnerIdElement = document.querySelector('[data-cookie-partner]');\r\n\r\nfunction getCookieName(name, isPartnerCookie) {\r\n if (isPartnerCookie && partnerIdElement) {\r\n return `${name}_${partnerIdElement.value}`\r\n }\r\n return name;\r\n}\r\n\r\n/**\r\n * @public\r\n * readCookie: searches for a cookie and returns its value.\r\n *\r\n * @param {string} name of the cookie to be retrieved.\r\n * @param {boolean} isPartnerCookie true if the cookie name should include the partner ID information,\r\n * otherwise false.\r\n */\r\nfunction readCookie(name, isPartnerCookie) {\r\n let cookieName = getCookieName(name, isPartnerCookie);\r\n cookieName += '=';\r\n\r\n const items = document.cookie.split(';') || [];\r\n const nameLength = cookieName.length;\r\n const cookieFound = items.find((item) => {\r\n if (item.trim().indexOf(cookieName) === 0) {\r\n return item;\r\n }\r\n return null;\r\n });\r\n\r\n if (!cookieFound) {\r\n return null;\r\n }\r\n\r\n return cookieFound.trim().substring(nameLength);\r\n}\r\n\r\n/**\r\n * @public\r\n * createCookieByMins: creates a new cookie for the domain, expering in minutes.\r\n *\r\n * @param {string} name of the cookie.\r\n * @param {any} value that will be stored in the cookie.\r\n * @param {number} minutes of expiration time for the cookie.\r\n * @param {boolean} isPartnerCookie true if the cookie name should include the partner ID information,\r\n * otherwise false.\r\n */\r\nfunction createCookieByMins(name, value, mins, isPartnerCookie) {\r\n let expires = '';\r\n const cookieName = getCookieName(name, isPartnerCookie);\r\n\r\n if (mins) {\r\n const date = new Date();\r\n date.setTime(date.getTime() + (mins * 60 * 1000));\r\n expires = '; expires=' + date.toGMTString();\r\n }\r\n\r\n document.cookie = `${cookieName}=${value}${expires}; path=/; secure`;\r\n}\r\n\r\nexport {\r\n readCookie,\r\n createCookieByMins\r\n};\r\n","import { debounce, fromEvent, interval } from 'rxjs';\r\nimport { readCookie, createCookieByMins } from 'modules/cookieManager';\r\n\r\n/**\r\n * @public\r\n * initUserInteractions: init the interactions between user and login cookie,\r\n * to notice when the interaction with the site is lost.\r\n * In a certain time, check the value of @see sessionAliveElement, if that number of minuts already happen and\r\n * the user don't interact the user need to be log out, for this reason we need to check the cookie IsUserLoggedIn\r\n */\r\nconst documentClicks$ = fromEvent(document, 'click')\r\n.pipe(\r\n debounce(() => interval(3000))\r\n);\r\nconst sessionAliveElement = document.querySelector('[data-session-alive-minutes]');\r\nconst sessionAliveMin = (sessionAliveElement && sessionAliveElement.value) || 10; \r\n\r\nconst updateSession = {\r\n next: () => {\r\n const isUserLoggedIn = readCookie('IsUserLoggedIn', true);\r\n if (isUserLoggedIn === 'True') {\r\n createCookieByMins('IsUserLoggedIn', 'True', sessionAliveMin, true);\r\n }\r\n }\r\n};\r\n\r\ndocumentClicks$.subscribe(updateSession);","const { store$ } = require(\"@redux/store\");\r\nconst { map, distinctUntilChanged, filter } = require(\"rxjs\");\r\n\r\n/**\r\n * TODO: Rebrand Code Improvement\r\n * This code helps to prevent affect not B1 version.\r\n * Remove the links on the backend.\r\n */\r\nconst componentLinksToInclude = ['sign-in', 'account', 'sign-out']\r\n\r\nconst subMenuAccountList = document.querySelector('[data-sub-menu-account-list]');\r\nconst subMenuAccountContainer = document.querySelector('[data-sub-menu-account-container]');\r\nconst linkSelector = (state) => state?.userProfile?.links;\r\nconst invalidValuesFilter = (value) => !!value && value.length > 0;\r\nconst drawMenu = (links) => {\r\n const linksToPaint = links.filter((link) => componentLinksToInclude.includes(link.component));\r\n linksToPaint.forEach(link => {\r\n const li = document.createElement('li');\r\n li.dataset.component = link?.component;\r\n const anchor = document.createElement('a');\r\n anchor.href = link?.url;\r\n anchor.innerText = link.text;\r\n anchor.classList.add('nhs-c-standard-link--medium-regular');\r\n if (link.ShouldOpenNewTab) {\r\n anchor.target = '_blank';\r\n anchor.rel = 'noopener noreferrer';\r\n }\r\n anchor.dataset.qa = link?.component;\r\n li.appendChild(anchor);\r\n subMenuAccountList.appendChild(li);\r\n if (link?.component === 'account') {\r\n const signInToggle = document.querySelector('[data-sign-in-toggle]');\r\n \r\n signInToggle.classList.remove('nhs-mq-icon__unauthed-user--24-large');\r\n signInToggle.classList.add('nhs-mq-icon__authed-user--24-large');\r\n }\r\n });\r\n subMenuAccountContainer.removeAttribute('hidden')\r\n };\r\n\r\nstore$.pipe(\r\n map(linkSelector),\r\n distinctUntilChanged(),\r\n filter(invalidValuesFilter)\r\n).subscribe(drawMenu);","/**\r\n * @public\r\n * isAuthLibraryLoaded: verify if the authetication library is loaded\r\n * @param {Object} state of the Redux store. \r\n *\r\n * @returns true when the library is already loaded otherwise false.\r\n */\r\nexport const isAuthLibraryLoaded = (state) => !!state?.authentication?.isAuthLibraryLoaded;\r\n\r\n/**\r\n * @public\r\n * isAuthLibraryNotLoaded: verify if the authetication library is not loaded\r\n * @param {Object} state of the Redux store. \r\n *\r\n * @returns true when the library is not already loaded otherwise false.\r\n */\r\nexport const isAuthLibraryNotLoaded = (state) => state?.authentication?.isAuthLibraryLoaded === false;\r\n\r\n/**\r\n * @public\r\n * isAuthModalOpen: verify if the authetication modal is currently open in the user screen.\r\n * @param {Object} state of the Redux store. \r\n *\r\n * @returns true when modal is opening otherwise false.\r\n */\r\nexport const isAuthModalOpen = (state) => !!state?.modal?.isAuthModalOpen;","export const pendingSavesSessionStorageKey = 'pendingFavorites';\r\nexport const favoritesSessionStorageKey = 'favorites';\r\n","/**\r\n * FavoriteType enum\r\n * Contains the different types of favorites that can be saved.\r\n */\r\nexport default class FavoriteType {\r\n static get Plan() {\r\n return this.getInstance('HomePlan');\r\n }\r\n\r\n static get Spec() {\r\n return this.getInstance('HomeSpec');\r\n }\r\n\r\n static get Community() {\r\n return this.getInstance('Community');\r\n }\r\n\r\n static get Builder() {\r\n return this.getInstance('Builder');\r\n }\r\n\r\n static fromKey(key) {\r\n const typeMap = {\r\n plan: FavoriteType.Plan,\r\n spec: FavoriteType.Spec,\r\n community: FavoriteType.Community,\r\n builder: FavoriteType.Builder,\r\n };\r\n return typeMap[key.toLowerCase()];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new FavoriteType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(type) {\r\n this.type = type;\r\n }\r\n\r\n toString() {\r\n return `${this.type}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(FavoriteType, 'instances', { value: {} });\r\n","import FavoriteType from './enums/favoriteType';\r\nimport { \r\n deleteFavoriteEpic, \r\n fetchUserFavoritesEpic, \r\n fetchUserProfileEpic, \r\n saveFavoriteEpic } from './redux/epics';\r\nimport {\r\n selectEmail,\r\n selectFavorites,\r\n selectIsLoggedIn,\r\n selectIsProfileFavoritesLoaded,\r\n selectPendingSaves,\r\n selectUserProfileTrackingCommonProperties,\r\n selectUserLocation,\r\n selectNeustarSegment,\r\n selectNeustarStatus,\r\n selectNeustarInformation,\r\n} from './redux/selectors';\r\nimport { userProfileSlice } from './redux/slices';\r\n\r\nrequire('./components/userMenu');\r\nrequire('./components/sessionAliveInteraction');\r\nrequire('./components/mainAuthentication');\r\nrequire('./components/modal');\r\nrequire('./components/favorites');\r\nrequire('./redux/listeners');\r\nrequire('./components/neustarListener');\r\nrequire('./components/googleOneTapAuthentication');\r\n\r\nconst { actions: userProfileActions, reducer: userProfileReducers } = userProfileSlice;\r\n\r\nexport {\r\n selectPendingSaves,\r\n selectFavorites,\r\n selectIsProfileFavoritesLoaded,\r\n fetchUserProfileEpic,\r\n fetchUserFavoritesEpic,\r\n saveFavoriteEpic,\r\n deleteFavoriteEpic,\r\n userProfileActions,\r\n userProfileReducers,\r\n selectUserProfileTrackingCommonProperties,\r\n FavoriteType,\r\n selectIsLoggedIn,\r\n selectEmail,\r\n selectUserLocation,\r\n selectNeustarSegment,\r\n selectNeustarInformation,\r\n selectNeustarStatus,\r\n};\r\n","import { createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport { store } from '@redux/store';\r\nimport onListViewPaint from 'pages/searchResults/redux/actions';\r\nimport { userProfileSlice } from './slices';\r\nimport { favoritesSessionStorageKey, pendingSavesSessionStorageKey } from '../constants/sessionStorageConstants';\r\nimport { selectFavorites, selectIsLoggedIn } from './selectors';\r\nimport updateSavedFavorites from '../components/favorites';\r\n\r\nconst actions = userProfileSlice.actions;\r\nconst listenerMiddleware = createListenerMiddleware();\r\n\r\n// update the favorites data on session storage.\r\n// this is done when a save / delete is successful.\r\nlistenerMiddleware.startListening({\r\n matcher: isAnyOf(actions.deleteFavoriteFullfilled, actions.saveFavoriteFulfilled),\r\n effect: async () => {\r\n const state = store.getState();\r\n const { favorites } = state.userProfile;\r\n sessionStorage.setItem(favoritesSessionStorageKey, JSON.stringify(favorites));\r\n },\r\n});\r\n\r\n// update the pending saves data on session storage.\r\n// this is done when a save / delete hasn't been completed yet.\r\nlistenerMiddleware.startListening({\r\n matcher: isAnyOf(actions.saveFavorite, actions.deleteFavorite, actions.saveFavoriteFulfilled),\r\n effect: async () => {\r\n const state = store.getState();\r\n const { pendingSaves } = state.userProfile;\r\n\r\n sessionStorage.setItem(pendingSavesSessionStorageKey, JSON.stringify(pendingSaves));\r\n },\r\n});\r\n\r\n/* When the list view is paint, update the favorites if the user is login. */\r\nlistenerMiddleware.startListening({\r\n matcher: isAnyOf(onListViewPaint),\r\n effect: async () => {\r\n const state = store.getState();\r\n const isLoggedIn = selectIsLoggedIn(state);\r\n if (isLoggedIn) {\r\n const favorites = selectFavorites(state);\r\n updateSavedFavorites(favorites);\r\n }\r\n },\r\n});\r\n\r\naddMiddleware(listenerMiddleware.middleware);\r\n","import { createSelector } from '@reduxjs/toolkit';\r\n\r\nexport const selectIsLoggedIn = (state) => state?.userProfile?.isLogin;\r\nexport const selectFavorites = (state) => state?.userProfile?.favorites;\r\nexport const selectPendingSaves = (state) => state?.userProfile?.pendingSaves;\r\nexport const selectIsProfileFavoritesLoaded = (state) => state?.userProfile?.isProfileFavoritesLoaded;\r\nexport const selectUserId = (state) => state?.userProfile?.userId;\r\nexport const selectEmail = (state) => state?.userProfile?.email;\r\nexport const selectName = (state) => state?.userProfile?.name;\r\nexport const selectPhone = (state) => state?.userProfile?.phone;\r\nexport const selectZip = (state) => state?.userProfile?.zip;\r\nexport const selectlivesOutside = (state) => state?.userProfile?.livesOutside;\r\n\r\nexport const selectNeustarStatus = (state) => state?.userProfile?.neustarStatus;\r\nexport const selectNeustarSegment = (state) => state?.userProfile?.neustarInformation?.s;\r\nexport const selectNeustarZip = (state) => state?.userProfile?.neustarInformation?.z;\r\nexport const selectNeustarAge = (state) => state?.userProfile?.neustarInformation?.a;\r\nexport const selectNeustarGender = (state) => state?.userProfile?.neustarInformation?.g;\r\nexport const selectNeustarInformation = (state) => state?.userProfile?.neustarInformation;\r\n\r\nexport const selectUserLocationCity = (state) => state?.userProfile?.userLocation?.userCity;\r\nexport const selectUserLocationCountry = (state) => state?.userProfile?.userLocation?.userCountry;\r\nexport const selectUserLocationMarketId = (state) => state?.userProfile?.userLocation?.userMarketId;\r\nexport const selectUserLocationState = (state) => state?.userProfile?.userLocation?.userState;\r\nexport const selectUserLocationZipCode = (state) => state?.userProfile?.userLocation?.userZipCode;\r\n\r\n/**\r\n * @public\r\n * selectGoogleOneTapLibraryLoadingStatus: returns the loading status of the Google One Tap Library.\r\n * @param {Object} state of the Redux store.\r\n *\r\n * @returns the loading status of the Google One Tap Library.\r\n */\r\nexport const selectGoogleOneTapLibraryLoadingStatus = (state) =>\r\n state?.authentication?.googleOneTapLibraryLoadingStatus;\r\n\r\n/** this selector is intended to expose useful properties when the user use the save to favorites feature\r\n * but it is not logged in.\r\n */\r\nexport const selectUserIdAndPendingSaves = createSelector(selectUserId, selectPendingSaves, (userId, pendingSaves) => ({\r\n userId,\r\n pendingSaves,\r\n}));\r\n\r\n/* It is using the `createSelector` function from the `@reduxjs/toolkit`\r\nlibrary to create a memoized selector. It takes in multiple input selectors\r\n(`selectUserLocationCity`, `selectUserLocationCountry`, `selectUserLocationMarketId`,\r\n`selectUserLocationState`, `selectUserLocationZipCode`) and a result function. */\r\nexport const selectUserLocation = createSelector(\r\n selectUserLocationCity,\r\n selectUserLocationCountry,\r\n selectUserLocationMarketId,\r\n selectUserLocationState,\r\n selectUserLocationZipCode,\r\n (userLocationCity, userLocationCountry, userLocationMarketId, userLocationState, userLocationZipCode) => ({\r\n userLocationCity,\r\n userLocationCountry,\r\n userLocationMarketId,\r\n userLocationState,\r\n userLocationZipCode,\r\n })\r\n);\r\n\r\n/** this selector is intended to expose all the properties that should be included as common tracking properties.\r\n * the idea behind this is tha here should be placed the selectors/props that are usually used in tracking events.\r\n * then the consumers will filter and take the props they need, this will just serve the information.\r\n */\r\nexport const selectUserProfileTrackingCommonProperties = createSelector(\r\n selectUserId,\r\n selectEmail,\r\n selectName,\r\n selectPhone,\r\n selectZip,\r\n selectlivesOutside,\r\n selectFavorites,\r\n selectNeustarSegment,\r\n selectNeustarZip,\r\n selectNeustarAge,\r\n selectNeustarGender,\r\n selectIsLoggedIn,\r\n (\r\n userId,\r\n email,\r\n name,\r\n phone,\r\n zip,\r\n livesOutside,\r\n favorites,\r\n neustarSegment,\r\n neustarZip,\r\n neustarAge,\r\n neustarGender,\r\n isLoggedIn\r\n ) => ({\r\n userId,\r\n email,\r\n name,\r\n phone,\r\n zip,\r\n livesOutside,\r\n favorites,\r\n neustarSegment,\r\n neustarZip,\r\n neustarAge,\r\n neustarGender,\r\n isLoggedIn,\r\n })\r\n);\r\n","import LoadingStatus from \"enums/loadingStatus\";\r\nimport { favoritesSessionStorageKey, pendingSavesSessionStorageKey } from \"../constants/sessionStorageConstants\";\r\n\r\n// Read \"pendingSaves\" session storage on initial load\r\nconst pendingSavesData= sessionStorage.getItem(pendingSavesSessionStorageKey, false);\r\n// Assign value to a list\r\nconst pendingSaves = pendingSavesData ? JSON.parse(pendingSavesData) : [];\r\n\r\n// Read \"favorites\" information on initial load\r\nconst favoritesData = sessionStorage.getItem(favoritesSessionStorageKey, false);\r\nconst favorites = favoritesData ? JSON.parse(favoritesData) : [];\r\n\r\nexport default {\r\n name: '',\r\n email: '',\r\n phone: '',\r\n zip: '',\r\n livesOutside: false,\r\n pendingSaves,\r\n favorites,\r\n hasUserOptedIntoRecommendationEmail: true,\r\n realtorQuestion : '',\r\n neustarStatus: LoadingStatus.Idle.toString()\r\n}","import { createSlice } from '@reduxjs/toolkit';\r\nimport { camelCaseObjectKeys } from 'utils/camelCase';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport userProfileInitialState from './initialState';\r\n\r\nconst userProfileSlice = createSlice({\r\n name: 'userProfile',\r\n initialState: userProfileInitialState,\r\n reducers: {\r\n apply: (state, action) => \r\n // return the new state with camel case object keys and isLoading set to false\r\n {\r\n\r\n const profile = camelCaseObjectKeys(action.payload);\r\n\r\n state.email = profile.email;\r\n state.id = profile.id;\r\n state.imageProfile = profile.imageProfile;\r\n state.isLogin = profile.isLogin;\r\n state.links = profile.links;\r\n state.livesOutside = profile.livesOutside;\r\n state.name = profile.name?.trim().replace(/\\s+/g, ' ');\r\n state.phone = profile.phone;\r\n state.preferredContactMethod = profile.preferredContactMethod;\r\n state.hasUserOptedIntoRecommendationEmail = profile.hasUserOptedIntoRecommendationEmail;\r\n state.realtorQuestion = profile.realtorQuestion;\r\n state.userId = profile.userId;\r\n state.userLocation = profile.userLocation;\r\n state.zip = profile.zip;\r\n state.isLoading = false;\r\n },\r\n applyFavorites: (state, action) => {\r\n const payload = camelCaseObjectKeys(action.payload);\r\n state.favorites = payload?.favorites;\r\n state.isProfileFavoritesLoaded = true;\r\n },\r\n update: (state, action) => {\r\n const userInfo = {...state, ...action.payload};\r\n state.name = userInfo.name?.trim().replace(/\\s+/g, ' ');\r\n state.email = userInfo.email;\r\n state.phone = userInfo.phone;\r\n state.zip = userInfo.zip;\r\n state.livesOutside = userInfo.livesOutside;\r\n state.preferredContactMethod = userInfo.preferredContactMethod || state.preferredContactMethod;\r\n state.hasUserOptedIntoRecommendationEmail = userInfo.hasUserOptedIntoRecommendationEmail ??\r\n state.hasUserOptedIntoRecommendationEmail;\r\n state.realtorQuestion = userInfo.realtorQuestion || state.realtorQuestion;\r\n },\r\n fetch: (state) => {\r\n state.isLoading = true;\r\n },\r\n handleError: (state) => {\r\n state.isLoading = false;\r\n },\r\n saveFavorite: (state, action) => {\r\n // check if the action.payload.id is already in the pendingSaves array, if not, add it.\r\n const pendingSaveExists = state.pendingSaves.some((favorite) => \r\n Number(favorite.listingInformation.id) === Number(action.payload.listingInformation.id)\r\n );\r\n\r\n if (!pendingSaveExists) {\r\n\r\n // add the favorite to the pending array, in case the API call fails or the user is logged out\r\n // and we need to retry the API call once the user logs in.\r\n state.pendingSaves.push(action.payload);\r\n }\r\n\r\n },\r\n deleteFavorite: () => {},\r\n deleteFavoriteFullfilled: (state, action) => {\r\n const payload = action.payload;\r\n state.favorites = state.favorites.filter((favorite) => favorite.listingId !== payload.listingId);\r\n },\r\n saveFavoriteFulfilled: (state, action) => {\r\n const newFavorite = action.payload.data.favorite;\r\n\r\n // remove the favorite from the pending array\r\n state.pendingSaves = state.pendingSaves.filter(\r\n (favorite) => Number(favorite.listingInformation.id) !== Number(newFavorite.listingId)\r\n );\r\n \r\n const favoriteExists = state.favorites.find((favorite) => favorite.listingId === newFavorite.listingId);\r\n \r\n if (!favoriteExists) {\r\n // add the favorite to the favorites array\r\n state.favorites = [...state.favorites, newFavorite];\r\n }\r\n },\r\n updateNeustarInformation: (state, action) => {\r\n const neustarInformation = action.payload;\r\n state.neustarInformation = neustarInformation;\r\n state.neustarStatus = LoadingStatus.Succeeded.toString()\r\n },\r\n}});\r\n\r\nconst authenticationSlice = createSlice({\r\n name: 'authentication',\r\n initialState: {\r\n isAuthLibraryLoaded: false,\r\n isAuthModalOpen: false,\r\n googleOneTapLibraryLoadingStatus: null,\r\n },\r\n reducers: {\r\n authLibraryLoaded: (state) => {\r\n state.isAuthLibraryLoaded = true;\r\n },\r\n authLibraryErrored: (state) => {\r\n state.isAuthLibraryLoaded = false;\r\n },\r\n googleOneTapLibraryLoadingStatus: (state, action) => {\r\n state.googleOneTapLibraryLoadingStatus = action.payload.name;\r\n },\r\n },\r\n});\r\n\r\nconst modalSlice = createSlice({\r\n name: 'modal',\r\n initialState: {\r\n isAuthModalOpen: false\r\n },\r\n reducers: {\r\n onOpen: (state) => {\r\n state.isAuthModalOpen = true;\r\n },\r\n onClose: (state) => {\r\n state.isAuthModalOpen = false;\r\n }\r\n },\r\n});\r\n\r\n// Extract the action creators object and the reducer\r\nexport { userProfileSlice, authenticationSlice, modalSlice };\r\n","import { createSelector } from '@reduxjs/toolkit';\r\n\r\nexport const selectUtmSource = (state) => state?.utmParameters?.utmSource;\r\nexport const selectUtmMedium = (state) => state?.utmParameters?.utmMedium;\r\nexport const selectUtmCampaign = (state) => state?.utmParameters?.utmCampaign;\r\nexport const selectUtmTerm = (state) => state?.utmParameters?.utmTerm;\r\nexport const selectUtmContent = (state) => state?.utmParameters?.utmContent;\r\nexport const selectEntranceUrl = (state) => state?.utmParameters?.entranceUrl;\r\nexport const selectGoogleClickId = (state) => state?.utmParameters?.googleClickId;\r\nexport const selectHttpReferer = (state) => state?.utmParameters?.httpReferer;\r\nexport const selectRefer = (state) => state?.utmParameters?.refer;\r\n\r\n/**\r\n * Returns true if the map is fetching results from the server.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const isLoading = (state) => state?.utmParameters?.isLoading;\r\n\r\nexport const selectUtmTrackingCommonProperties = createSelector(selectRefer, (refer) => ({ refer }));\r\n","import { store$ } from '@redux/store';\r\nimport { map, distinctUntilChanged, filter } from 'rxjs';\r\n\r\nconst userLocationSelector = (state) => state?.userProfile?.userLocation;\r\nconst validValuesFilter = (value) => !!value;\r\nconst isDataLayerValid = () => !!window.dataLayer;\r\n\r\n/**\r\n * A function that push information to dataLayer.\r\n */\r\nconst updateDataLayer = (data) => {\r\n setTimeout(() => window.dataLayer.push(data), 0);\r\n};\r\n\r\n/**\r\n * Update the dataLayer when user information is ready.\r\n * The user location information must be pushed to the dataLayer always.\r\n */\r\nstore$\r\n .pipe(filter(isDataLayerValid), map(userLocationSelector), distinctUntilChanged(), filter(validValuesFilter))\r\n .subscribe(updateDataLayer);\r\n\r\nexport default updateDataLayer;\r\n","export default class PageLayout {\r\n static get Communities() {\r\n return this.getInstance('communities-communities');\r\n }\r\n\r\n static get Homes() {\r\n return this.getInstance('homes-homes');\r\n }\r\n\r\n static get Builders() {\r\n return this.getInstance('AllProducts-builders');\r\n }\r\n \r\n static get BoylLocations() {\r\n return this.getInstance('boyl-locations');\r\n }\r\n\r\n static get CustomHomes() {\r\n return this.getInstance('custom-homes');\r\n }\r\n\r\n static get ManufacturedLocations() {\r\n return this.getInstance('manufactured-locations');\r\n }\r\n\r\n static get ManufacturedHomes() {\r\n return this.getInstance('manufactured-homes');\r\n }\r\n\r\n static fromKey(key) {\r\n const statusMap = {\r\n 'communities-communities': PageLayout.Communities,\r\n 'homes-homes': PageLayout.Homes,\r\n 'AllProducts-builders': PageLayout.Builders,\r\n 'boyl-locations': PageLayout.BoylLocations,\r\n 'custom-homes': PageLayout.CustomHomes,\r\n 'manufactured-locations': PageLayout.ManufacturedLocations,\r\n 'manufactured-homes': PageLayout.ManufacturedHomes\r\n };\r\n return statusMap[key];\r\n }\r\n\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new PageLayout(key);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(PageLayout, 'instances', { value: {} });\r\n","export default class ResultPresentationType {\r\n\r\n /**\r\n * The static get Pagination function returns an instance of the 'Pagination' class.\r\n * @returns The method is returning an instance of the 'Pagination' class.\r\n */\r\n static get Pagination() {\r\n return this.getInstance('Pagination');\r\n }\r\n \r\n /**\r\n * The function returns an instance of the 'InfiniteScrolling' class.\r\n * @returns The method `get InfiniteScrolling()` is returning the result of calling the `getInstance`\r\n * method with the argument `'InfiniteScrolling'`.\r\n */\r\n static get InfiniteScrolling() {\r\n return this.getInstance('InfiniteScrolling');\r\n }\r\n \r\n /**\r\n * The function \"fromKey\" takes a key as input and returns the corresponding value from a\r\n * predefined map.\r\n * @param key - The `key` parameter is a string that represents a key in the `statusMap` object.\r\n * @returns The value associated with the given key in the statusMap object is being returned.\r\n */\r\n static fromKey(key) {\r\n const statusMap = {\r\n 'Pagination': ResultPresentationType.Pagination,\r\n 'InfiniteScrolling': ResultPresentationType.InfiniteScrolling,\r\n };\r\n return statusMap[key];\r\n }\r\n \r\n /**\r\n * Gets an instance of a ResultPresentationType object based on a given name.\r\n * If the instance does not already exist, it creates a new instance using the configuration provided.\r\n *\r\n * @param name a unique identifier used to retrieve or create an instance of the ResultPresentationType class.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the ResultPresentationType class that is being created.\r\n *\r\n * @returns an instance of `ResultPresentation` that corresponds to the given `name`.\r\n */\r\n static getInstance(key) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new ResultPresentationType(key);\r\n }\r\n return this.instances[key];\r\n }\r\n \r\n /**\r\n * This is a constructor function that takes a name as a parameter and sets the name\r\n * @param name -The `name` property is a string that represents the name of the\r\n * configuration\r\n */\r\n constructor(name) {\r\n this.name = name;\r\n }\r\n \r\n /**\r\n * Method that returns the name property of an object as a string.\r\n * @returns returns the `name` property of that object as a string.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n }\r\n \r\n Object.defineProperty(ResultPresentationType, 'instances', { value: {} });\r\n ","/* \r\n * Enum for layout breakpoints. Represents the minimum width values for different layout sizes.\r\n*/\r\nexport default class LayoutBreakpoint { \r\n /*\r\n * Represents small screens with a minimum width of 380px and max 768px\r\n */\r\n static get Small() {\r\n return this.getInstance(380, `(max-width: 768px)`, \"Small\");\r\n }\r\n \r\n /*\r\n * Represents medium screens with a minimum width of 768px and max 1023px\r\n */\r\n static get Medium() {\r\n return this.getInstance(768, `(min-width: 768px) and (max-width: 1023px)`, \"Medium\");\r\n }\r\n \r\n /*\r\n * Represents Big screens with a minimum width of 1024px\r\n */\r\n static get Big() {\r\n return this.getInstance(1024, `(min-width: 1024px)`, \"Big\");\r\n }\r\n\r\n static getInstance(key, mediaQuery, text) {\r\n if (!this.instances[key]) {\r\n this.instances[key] = new LayoutBreakpoint(key, mediaQuery, text);\r\n }\r\n\r\n return this.instances[key];\r\n }\r\n \r\n /*\r\n * Get the layoutBreakpoint by the media query\r\n */\r\n static getLayoutBreakpointByMediaQuery(mediaQuery){\r\n switch(mediaQuery){\r\n case LayoutBreakpoint.Small.getMediaQuery():\r\n return LayoutBreakpoint.Small;\r\n case LayoutBreakpoint.Medium.getMediaQuery():\r\n return LayoutBreakpoint.Medium;\r\n case LayoutBreakpoint.Big.getMediaQuery():\r\n return LayoutBreakpoint.Big;\r\n default:\r\n return LayoutBreakpoint.Small;\r\n }\r\n }\r\n\r\n /*\r\n * All LayoutBreakpoints values\r\n */\r\n static toList(){\r\n return [\r\n LayoutBreakpoint.Small,\r\n LayoutBreakpoint.Medium,\r\n LayoutBreakpoint.Big,\r\n ];\r\n }\r\n\r\n constructor(value, mediaQuery, text) {\r\n this.value = value;\r\n this.mediaQuery = mediaQuery;\r\n this.text = text;\r\n }\r\n \r\n toString() {\r\n return this.text;\r\n }\r\n\r\n getValue(){\r\n return this.value;\r\n }\r\n\r\n getMediaQuery(){\r\n return this.mediaQuery;\r\n }\r\n\r\n\r\n}\r\n \r\nObject.defineProperty(LayoutBreakpoint, 'instances', { value: {} });\r\n ","import { createSelector } from '@reduxjs/toolkit';\r\n\r\nexport const selectUiState = (state) => state?.uiState;\r\nexport const selectFetchingModal = (state) => state?.uiState.isFetchingModal;\r\nexport const selectDisplaySkeleton = (state) => state?.uiState?.displayCardGridSkeleton;\r\nexport const selectPageLayout = (state) => state?.uiState?.pageLayout;\r\nexport const selectResultsPresentationType = (state) => state?.uiState?.resultsPresentationType;\r\nexport const selectModal = (state) => state?.uiState?.modalInformation;\r\nexport const selectModalListingInformation = (state) => state?.uiState?.modalInformation?.listingInformation;\r\nexport const selectLoading = (state) => state?.configuration?.loading;\r\nexport const selectConfigurationResourceDomain = (state) => state?.configuration?.resourceDomain;\r\nexport const selectConfigurationSegmentApiKey = (state) => state?.configuration?.segmentApiKey;\r\nexport const selectConfigurationNeustarApiKey = (state) => state?.configuration?.neustarApiKey;\r\nexport const selectConfigurationImageResizeService = (state) => state?.configuration?.imageResizeService;\r\nexport const selectConfigurationGoogleOneTapClientId = (state) => state?.configuration?.googleOneTapClientId;\r\nexport const selectIsMarkerAutoScrollFeatureEnabled = (state) => state?.configuration?.isMarkerAutoScrollFeatureEnabled;\r\nexport const selectLayoutBreakpoint = (state) => state?.uiState?.layoutBreakpoint;\r\n\r\n/**\r\n * Selector to get all the host name used in NewHomeSource site.\r\n */\r\nexport const selectResourcesHostNames = createSelector(\r\n selectConfigurationResourceDomain,\r\n selectConfigurationImageResizeService,\r\n (resourceDomain, imageResizeService) => ({\r\n staticImagesHostName: resourceDomain,\r\n imageResizeService,\r\n })\r\n);","import PageLayout from \"layout/constants/pageLayoutNames\";\r\nimport ResultPresentationType from \"layout/constants/resultPresentationType\";\r\n\r\nconst lookup = {\r\n [PageLayout.Communities]: ResultPresentationType.Pagination.toString(),\r\n [PageLayout.Homes]: ResultPresentationType.Pagination.toString(),\r\n [PageLayout.Builders]: ResultPresentationType.InfiniteScrolling.toString(),\r\n [PageLayout.BoylLocations]: ResultPresentationType.Pagination.toString(),\r\n [PageLayout.CustomHomes]: ResultPresentationType.Pagination.toString(),\r\n [PageLayout.ManufacturedLocations]: ResultPresentationType.Pagination.toString(),\r\n [PageLayout.ManufacturedHomes]: ResultPresentationType.Pagination.toString(),\r\n};\r\n\r\nconst getResultPresentationByLayoutName = (layoutName) => lookup[layoutName];\r\n\r\nexport default getResultPresentationByLayoutName;","import { createSlice } from '@reduxjs/toolkit';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport getResultPresentationByLayoutName from 'layout/services/resultsPresentationService';\r\n\r\nconst uiStateSlice = createSlice({\r\n name: 'uiState',\r\n initialState: {\r\n isFetchingModal: false,\r\n modalInformation: null,\r\n },\r\n reducers: {\r\n clearModal: (state) => {\r\n state.isFetchingModal = false;\r\n state.modalInformation = null;\r\n },\r\n fetchModal: (state, action) => {\r\n state.isFetchingModal = action.payload.isFetchingModal;\r\n },\r\n fetchModalError: (state) => {\r\n state.isFetchingModal = false;\r\n },\r\n fetchModalFulfilled: (state) => {\r\n state.isFetchingModal = false;\r\n },\r\n updatePageLayout: (state, action) => {\r\n state.pageLayout = action.payload;\r\n state.resultsPresentationType = getResultPresentationByLayoutName(action.payload);\r\n },\r\n updateCardGridSkeleton: (state, action) => {\r\n state.displayCardGridSkeleton = action.payload === LoadingStatus.Loading;\r\n },\r\n focusedListingInformation: (state, action) => {\r\n state.focusedListing = action.payload;\r\n },\r\n modalInformation: (state, action) => {\r\n const previousName = state.modalInformation?.name;\r\n const newModalInformation = {...action.payload};\r\n // We don't need to save the events information into the state. So\r\n // we are removing them before assigning to the state.\r\n delete newModalInformation.googleAnalyticsDTO;\r\n\r\n state.modalInformation = {\r\n ...state.modalInformation,\r\n ...newModalInformation,\r\n };\r\n\r\n // the \"previousName\" property should change only when a new name is being set\r\n if (previousName) {\r\n state.modalInformation.previousName = previousName;\r\n }\r\n },\r\n updateLayoutBreakpoint: (state, action) => {\r\n state.layoutBreakpoint = action.payload;\r\n },\r\n /* A reducer that does nothing because it's used for Google Analytics Redux Beacon. */\r\n trackUserEvent: () => {},\r\n },\r\n});\r\n\r\nexport default uiStateSlice;\r\n","import { Subject } from 'rxjs';\r\n\r\nconst subject = new Subject();\r\n\r\nexport default {\r\n getMessage: () => subject.asObservable(),\r\n sendMessage: (message) => subject.next(message),\r\n}","import { Subject } from 'rxjs';\r\n\r\nconst subject = new Subject();\r\n\r\nexport default {\r\n clearHtml: () => subject.next({ action: 'clearHtml' }),\r\n getHtml: () => subject.asObservable(),\r\n onHtmlReady: (data) => subject.next({ action: 'onHtmlReady', ...data }),\r\n onHtmlRemoved: (data) => subject.next({ action: 'onHtmlRemoved', ...data }),\r\n setHtml: (data) => subject.next({ action: 'setHtml', value: data.payload }),\r\n setPreviousHtml: () => subject.next({ action: 'setPreviousHtml' }),\r\n};\r\n","(function (global, factory) {\r\n if (typeof define === 'function' && define.amd) {\r\n // If supports for AMD is available return the value to the AMD Loader\r\n // and to the global (window) object in case any JS module is expecting\r\n // the AppNexusModule to exists on the window object.\r\n define([], () => (global.AppNexus = factory(global)));\r\n } else if (typeof exports === 'object') {\r\n // If supports for Common JS is available export the module\r\n // and pass is value to the global (window) object in case non Common JS code\r\n // is expected to work with this AppNexusModule.\r\n module.exports = global.AppNexus = factory(global);\r\n } else {\r\n // If not support for AMD or Common JS is available register the module in the global scope.\r\n global.AppNexus = factory(global);\r\n }\r\n})(typeof window !== 'undefined' ? window : {}, (root) => {\r\n /* In order to avoid AppNexus running twice or more. Flag is set to true once AppNexus ran. */\r\n if (root.apntag) {\r\n return;\r\n }\r\n\r\n const baseElementUrl = document.querySelector('base')?.attributes?.href?.value;\r\n const baseUrl = baseElementUrl || window.location.origin;\r\n /**\r\n *\r\n * Using module pattern to avoid unintended modifications to the constants values needed during the execution of the script. ECMAScript5 limitation not const word exists.\r\n *\r\n * @constant\r\n */\r\n const CONFIGURATION = (function () {\r\n //\r\n const constants = {\r\n ASTURL: '//acdn.adnxs.com/ast/ast.js', // URL were the AST JS resource is located.\r\n PARAMETERSURL: `${baseUrl}/GetAdParameters?url=`, // URL of the AJAX call to get the parameters.\r\n HTMLDIVPREFIX: 'nhs_', // Prefix shared by the ID propert of all DIV elements where we are expecting an ad.\r\n MEMBERID: 3232,\r\n SKINADID: 'nhs_Sponsorship',\r\n };\r\n\r\n const retrieveValue = function (constantName) {\r\n return constants[constantName];\r\n };\r\n\r\n return {\r\n get: retrieveValue, // Expose a get method to return the value of the constants that have being defined in this module.\r\n };\r\n })();\r\n\r\n /**\r\n * @var Empty apntag.\r\n */\r\n let apntag;\r\n\r\n /**\r\n * @var Empty parameter object to stored the backend values passed as keywords to AppNexus.\r\n */\r\n let parameters;\r\n\r\n /**\r\n * @var Flag to indicate if the AST JS Library has already being loaded. If the AST Library has not being loaded value will be 'false', otherwise 'true'.\r\n */\r\n let isAstLoaded = false;\r\n\r\n /**\r\n * @var Flag to indicate if the request to load the AST JS Library has been started. If the AST Library has is being loaded value will be 'false', otherwise 'true'.\r\n */\r\n let isAstLoading = false;\r\n\r\n /**\r\n * @var Flag to indicate if the AJAX request to load the parameters to being sent to AppNexus has being retrived from the server. If the parameters has been loaded value will be 'true', otherwise 'false'.\r\n */\r\n let areParametersDefined = false;\r\n\r\n /**\r\n * @event Custom event to indicate a new call for Ads at AppNexus must be executed.\r\n */\r\n const loadAdsEvent = document.createEvent('Event');\r\n\r\n /**\r\n * @event Custom event to indicate the AST JS library has been loaded.\r\n */\r\n const atsLoadedEvent = document.createEvent('Event');\r\n\r\n /**\r\n * @type {Function[]} List of functions to run after the Parameters get loaded\r\n */\r\n let onParametersLoaded = [];\r\n\r\n /**\r\n * @type {object} to store in memory the native ads templates.\r\n */\r\n const nativeAdTemplates = {};\r\n\r\n function getNodeIdsFromSelectors(selectors) {\r\n const adsIds = selectors.reduce((accumulator, selector) => {\r\n const elements = document.querySelectorAll(selector);\r\n return accumulator.concat(getIdsFromElements(elements));\r\n }, []);\r\n\r\n return adsIds;\r\n }\r\n\r\n /**\r\n * Gets all the UT calls group the page should run.\r\n *\r\n * @returns an array of CSS selectors. The array contains selectors that will be used to group ads in UT calls\r\n */\r\n const getUtCallGroups = () => {\r\n // Get all elements with the \"data-native-ad-ut-call\" attribute\r\n const elements = document.querySelectorAll('[data-native-ad-ut-call]:not([data-loaded])');\r\n\r\n // Create an empty Set to store unique attribute values\r\n const values = new Set();\r\n\r\n // Iterate through the NodeList and add each unique value to the Set\r\n elements.forEach((element) => {\r\n const value = parseInt(element.getAttribute('data-native-ad-ut-call'));\r\n\r\n if (!isNaN(value)) {\r\n values.add(value);\r\n }\r\n });\r\n\r\n const uniqueValues = Array.from(values).sort((a, b) => a - b);\r\n const groupsAsQuerySelector = uniqueValues.map((value) => `[data-native-ad-ut-call=\"${value}\"]:not([data-loaded])`);\r\n\r\n groupsAsQuerySelector.push('.nhs_ASTAboveDiv');\r\n groupsAsQuerySelector.push('.nhs_ASTBelowDiv');\r\n\r\n // Convert the Set to an array and log the result\r\n return groupsAsQuerySelector;\r\n };\r\n\r\n /**\r\n *\r\n * Executes an XML Http Request for a given URL.\r\n *\r\n * @param {string} url URL where the file being requested lives.\r\n */\r\n function requestHttpGet(url) {\r\n const request = new XMLHttpRequest();\r\n request.open('GET', url);\r\n request.send();\r\n }\r\n\r\n /**\r\n * Replaces the content of a template with the response data.\r\n * @param {HTMLElement} template - The template element to use for the content.\r\n * @param {Object} response - The response data to use for populating the template.\r\n * @returns {HTMLElement} - The copy of the template with the response data.\r\n */\r\n function replaceTemplateContent(template, response) {\r\n const clone = template.querySelector('div').cloneNode(true);\r\n\r\n clone.querySelector('[data-native-image]').src = response.image.url;\r\n clone.querySelector('[data-native-image]').alt = `${response.title} - ${response.sponsoredBy}`;\r\n clone.querySelector('[data-native-contact]').href = response.clickUrl;\r\n clone.querySelector('[data-native-contact]').textContent = `Sponsored by ${response.sponsoredBy}`;\r\n\r\n clone.querySelector('[data-native-head]').textContent = response.title;\r\n clone.querySelector('[data-native-description]').textContent = response.body;\r\n clone.querySelector('[data-native-builder-logo]').src = response.icon.url;\r\n clone.querySelector('[data-native-builder-logo]').alt = response.sponsoredBy;\r\n clone.querySelector('[data-native-cta]').textContent = response.cta;\r\n clone.removeAttribute('hidden');\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n *\r\n * Method to insert a Native Ad into a page.\r\n *\r\n * @param {string} element HTML Element where the Native Ad is going to be added.\r\n * @param {object} response AppNexus response with the Native Ad information.\r\n */\r\n function createNativeAd(element, response) {\r\n if (!response || !response.native) {\r\n return;\r\n }\r\n const nativeAdKey = response.targetId.split('--')[1];\r\n const template = (\r\n nativeAdTemplates[nativeAdKey] ||\r\n document.querySelector(`[data-native-ad-template=\"${response.width}x${response.height}\"]`)\r\n ).content.cloneNode(true);\r\n const regex = /(?:<\\/script>/g;\r\n\r\n if (element) {\r\n const impressionTrackers = response.native.impressionTrackers || [];\r\n const clickTrackers = response.native.clickTrackers || [];\r\n const jsTrackers = [];\r\n let result;\r\n\r\n const iframeForNativeAd = document.createElement('iframe');\r\n iframeForNativeAd.setAttribute('aria-label', 'Sponsored');\r\n\r\n const content = replaceTemplateContent(template, response.native);\r\n\r\n iframeForNativeAd.onload = function () {\r\n const cssForIframe = document.querySelector('[data-native-ad-styles]').value;\r\n\r\n const circularFontPath = 'https://beta-nhs-static-secure.akamaized.net/wwwroot/fonts/CircularXX-variable.woff2';\r\n const souvenirFontPath = 'https://beta-nhs-static-secure.akamaized.net/wwwroot/fonts/SouvenirStd-Light.woff2';\r\n\r\n const styleElement = document.createElement('style');\r\n styleElement.textContent = `\r\n @font-face {\r\n font-display: swap;\r\n font-family: \"Circular XX\";\r\n src: url('${circularFontPath}') format('woff2');\r\n font-weight: 400 700;\r\n unicode-range: U+0020-007E, U+00A0-00A1, U+00A7, U+00A9-00AC, U+00AE, U+00B4, U+00BB, U+00BF-00C2, U+00C4, U+00C6-00CF, U+00D1-00D4, U+00D6, U+00D9-00DC, U+00E0-00E2, U+00E4, U+00E6-00EF, U+00F1-00F4, U+00F6, U+00F9-00FC, U+00FF, U+0152-0153, U+0178, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+20AC, U+2122, U+2212, U+2215;\r\n }\r\n \r\n @font-face {\r\n font-display: swap;\r\n font-family: 'ITC Souvenir Std';\r\n src: url('${souvenirFontPath}') format('woff2');\r\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\r\n }\r\n `;\r\n\r\n const iframeStyles = document.createElement('link');\r\n iframeStyles.setAttribute('href', cssForIframe);\r\n iframeStyles.setAttribute('rel', 'stylesheet');\r\n\r\n // impression trackers\r\n let i;\r\n for (i = 0; i < impressionTrackers.length; i += 1) {\r\n const image = new Image();\r\n image.src = impressionTrackers[i];\r\n image.style.display = 'none';\r\n iframeForNativeAd.contentWindow.document.body.appendChild(image);\r\n }\r\n\r\n // JS trackers\r\n while ((result = regex.exec(response.native.javascriptTrackers)) !== null) {\r\n jsTrackers.push(result[1]);\r\n }\r\n\r\n for (i = 0; i < jsTrackers.length; i += 1) {\r\n const scr = document.createElement('script');\r\n\r\n scr.type = 'text/javascript';\r\n scr.async = true;\r\n scr.src = jsTrackers[i];\r\n iframeForNativeAd.contentWindow.document.head.appendChild(scr);\r\n }\r\n\r\n iframeForNativeAd.contentWindow.document.head.appendChild(iframeStyles);\r\n iframeForNativeAd.contentWindow.document.head.appendChild(styleElement);\r\n iframeForNativeAd.contentWindow.document.body.appendChild(content);\r\n\r\n bindEventsToNativeAdCard(iframeForNativeAd, element, clickTrackers);\r\n };\r\n\r\n element.appendChild(iframeForNativeAd);\r\n element.classList.add('loaded');\r\n element.removeAttribute('hidden');\r\n element.dataset.loaded = 'true';\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * Method to clone an orignal object except for one property.\r\n *\r\n * @private\r\n * @param {object} original Object to be cloned.\r\n * @param {string[]} undesiredKeys name of the keys we do not want to exist on the cloned object.\r\n * @returns {object} a clone version of the original object with all properties except one.\r\n */\r\n const _omit = function (original, undesiredKeys) {\r\n const clonedObject = {};\r\n\r\n if (!Array.isArray(undesiredKeys)) {\r\n return original;\r\n }\r\n\r\n for (const key in original) {\r\n if (!undesiredKeys.includes(key)) {\r\n clonedObject[key] = original[key];\r\n }\r\n }\r\n\r\n return clonedObject;\r\n };\r\n\r\n /**\r\n *\r\n * Executes a GET request via AJAX to the URL specified and executes the callback once the action has returned.\r\n * Parses the information obtained as a JSON before passing it to the callback function\r\n *\r\n * @private\r\n * @param {string} url Location of the server where the GET action will be executed\r\n * @param {function} callback JavaScript function to execute if the AJAX request is succesfull.\r\n */\r\n const _ajaxRequest = function (url, callback) {\r\n _dispatchAdParametersStartEvent();\r\n const xmlHttpRequest = new XMLHttpRequest();\r\n\r\n xmlHttpRequest.onreadystatechange = function () {\r\n if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {\r\n let data;\r\n\r\n try {\r\n data = JSON.parse(xmlHttpRequest.responseText);\r\n } catch (err) {\r\n return;\r\n }\r\n\r\n _dispatchAdParametersEndEvent();\r\n // If callback function was passed execute it, once the AJAX has returned.\r\n if (typeof callback === 'function' && data !== null) {\r\n callback(data);\r\n }\r\n }\r\n };\r\n\r\n xmlHttpRequest.open('GET', url, true);\r\n xmlHttpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\r\n xmlHttpRequest.setRequestHeader('Cache-Control', 'no-cache');\r\n xmlHttpRequest.setRequestHeader('Content-type', 'application/json; charset=utf-8');\r\n xmlHttpRequest.send();\r\n };\r\n\r\n /**\r\n *\r\n * Handles the Ad Available event for the apntag.\r\n * Handles the render of the ad if the available ad is native, otherwise does nothing as the AST library handles the rendering of banner ads.\r\n * Handles the render of the ad if the available ad is native, otherwise does nothing as the AST library handles the rendering of banner ads.\r\n *\r\n * @private\r\n * @param {object} response Available ad information.\r\n */\r\n const _astAdAvailableHandler = function (response) {\r\n const element = document.getElementById(response.targetId);\r\n\r\n if (element) {\r\n element.dataset.loaded = true;\r\n }\r\n\r\n if (\r\n response.adType.indexOf('native') !== -1 &&\r\n !!response.native &&\r\n !!response.native.image &&\r\n !!response.native.image.url\r\n ) {\r\n // clear the target element to remove the hidden template\r\n element.innerHTML = '';\r\n\r\n createNativeAd(element, response);\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Handles the Ad no bid event for apntag.\r\n * If the ad has not been bid then hide the parent div so that the space without the ad is not shown.\r\n * \"No bid\" means no offer in an ad auction, resulting in an empty advertising space.\r\n * We use an OnEvent to listen if the ad is noBid: true, the latter is a property that comes in the response\r\n * if the ad was bid the response says noBid:False.\r\n * @param {object} response - Ad information, if it was not bid.\r\n * See more details at.\r\n * @see {@link https://docs.xandr.com/bundle/seller-tag/page/seller-tag/on-event.html}\r\n * @see {@link https://docs.xandr.com/bundle/seller-tag/page/seller-tag/ad-object-api.html}\r\n */\r\n const _astAdNoBidHandler = function (response) {\r\n _printAdInformation('Ad no bid ');\r\n _printAdInformation(response);\r\n _dispatchAdRequestEndEvent(response);\r\n const element = document.getElementById(response.targetId);\r\n if (!element || element?.dataset.noRemove === 'true') {\r\n element.dataset.loaded = 'true';\r\n return;\r\n }\r\n\r\n const parentElement = element.closest('[data-native=\"true\"]');\r\n if (parentElement) {\r\n parentElement.remove();\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Initialize the apntag object with the global page options.\r\n *\r\n * @private\r\n */\r\n const _astGlobalOptions = function () {\r\n apntag.setPageOpts({\r\n member: CONFIGURATION.get('MEMBERID'),\r\n disablePsa: true,\r\n });\r\n };\r\n /**\r\n *\r\n * Define an Ad Tag to the apntag object.\r\n *\r\n * @private\r\n * @param {String} divElementId div Element Id\r\n * @param {Number} width width\r\n * @param {Number} height height\r\n * @param {Number} index index\r\n */\r\n const _astDefineTag = function (divElementId, width, height, index) {\r\n let nativeLayouts;\r\n let allowedFormatsArray = ['banner'];\r\n const data = JSON.parse(parameters);\r\n const keywords = _omit(data, ['placements', 'useLazyLoad']);\r\n const element = document.getElementById(divElementId);\r\n const nativeAdKey = divElementId.split('--')[1];\r\n const isNativeSupported = element.dataset.native === 'true' || nativeAdTemplates[nativeAdKey];\r\n let currentPlacement = data.placements.filter((el) => {\r\n const elementId = divElementId.toLowerCase().replace(CONFIGURATION.get('HTMLDIVPREFIX'), '');\r\n return elementId.split('--')[1].toLowerCase() === el.split('|')[1].toLowerCase();\r\n });\r\n\r\n if (typeof currentPlacement === 'undefined' || currentPlacement === null || currentPlacement.length === 0) {\r\n return;\r\n }\r\n\r\n if (divElementId.indexOf('native') !== -1 || isNativeSupported) {\r\n allowedFormatsArray = ['native'];\r\n nativeLayouts = {\r\n title: { required: true, max_length: 70 },\r\n body: { required: true, max_length: 120 },\r\n image: { required: false },\r\n sponsoredBy: { required: true, max_length: 60 },\r\n icon: { required: false },\r\n cta: { required: false },\r\n };\r\n }\r\n\r\n currentPlacement = currentPlacement[0].split('|')[0];\r\n keywords.ref = ++index; // Ad ref parameter to Ad call.\r\n\r\n apntag.defineTag({\r\n member: CONFIGURATION.get('MEMBERID'),\r\n tagId: currentPlacement * 1, // Placement ID in console.\r\n sizes: [width, height],\r\n allowedFormats: allowedFormatsArray,\r\n targetId: divElementId,\r\n keywords,\r\n native: nativeLayouts,\r\n customIframeProps: {\r\n title: 'Advertising',\r\n },\r\n });\r\n apntag.showTag(divElementId);\r\n };\r\n\r\n /**\r\n *\r\n * Executes a request to App Nexus servers for new ads.\r\n *\r\n * @private\r\n * @param {String} divElementId div Element Id\r\n * @param {Number} width width\r\n * @param {Number} height height\r\n * @param {Number} index index\r\n * @return {Function} Function with the parameters defined for an ad placement.\r\n */\r\n const _executeRequestToAppNexus = function (divElementId, width, height, index) {\r\n return function () {\r\n _astGlobalOptions();\r\n _astDefineTag(divElementId, width, height, index);\r\n };\r\n };\r\n\r\n /**\r\n *\r\n * Search for HTML elements with the class \"nhs_AstDiv\" and execute a define call to AppNexus server for that position\r\n *\r\n * @private\r\n * @param {Boolean} overwriteAds Overwrite Ads flag\r\n * @param {String} selector Element class name or CSS Selector\r\n */\r\n const _createAppNexusRequest = function (overwriteAds, selector) {\r\n let index;\r\n let elementId;\r\n let element;\r\n let width;\r\n let height;\r\n const appNexusRequests = [];\r\n\r\n // We receive parameter named \"selector\" for load Ads regarding to class name sent from each View or PartialView (https://builderhomesite.atlassian.net/browse/BDXNHS-1569)\r\n var adElements = document.querySelectorAll(selector);\r\n var adElements = Array.prototype.slice.call(adElements);\r\n\r\n adElements = adElements.sort((a, b) => {\r\n let indexA = a && a.id && a.id.indexOf('native') > 1;\r\n let indexB = b && b.id && b.id.indexOf('native') > 1;\r\n const widthA = 1000 - Math.round(a.getAttribute('data-width'));\r\n const heightA = Math.round(a.getAttribute('data-height'));\r\n const widthB = 1000 - Math.round(b.getAttribute('data-width'));\r\n const heightB = Math.round(b.getAttribute('data-height'));\r\n\r\n indexA = indexA * 1000 + widthA + heightA;\r\n indexB = indexB * 1000 + widthB + heightB;\r\n\r\n return indexB - indexA;\r\n });\r\n\r\n if (!adElements || adElements.length === 0) {\r\n return;\r\n }\r\n\r\n let length = adElements.length;\r\n\r\n for (index = 0; index < length; index += 1) {\r\n element = adElements[index];\r\n elementId = element.id;\r\n width = Math.round(element.getAttribute('data-width'));\r\n height = Math.round(element.getAttribute('data-height'));\r\n const internalNativeAdTemplate = element.querySelector('[data-native-ad-template]');\r\n const isNativeSupported =\r\n elementId.includes('native') || element.dataset.native === 'true' || internalNativeAdTemplate;\r\n const nativeAdKey = elementId.split('--')[1];\r\n if (!nativeAdTemplates[nativeAdKey] && internalNativeAdTemplate) {\r\n nativeAdTemplates[nativeAdKey] = internalNativeAdTemplate;\r\n }\r\n\r\n if (width === 0 && height === 0 && elementId !== CONFIGURATION.get('SKINADID')) {\r\n continue;\r\n }\r\n\r\n // Ignore Ad containers that already have some content inside them, and ignore any element hidden via CSS.\r\n // Making an exception for Skin Ad. The offsetParent is null for elements with position \"Fixed\" as its the case of the Skin Ad.\r\n if (\r\n (!!element.querySelector('iFrame') && !overwriteAds) ||\r\n (element.offsetParent === null && elementId !== CONFIGURATION.get('SKINADID') && !isNativeSupported)\r\n ) {\r\n continue;\r\n }\r\n\r\n appNexusRequests.push(_executeRequestToAppNexus(elementId, width, height, index));\r\n }\r\n\r\n length = appNexusRequests.length;\r\n for (index = 0; index < length; index += 1) {\r\n apntag.anq.push(appNexusRequests[index]);\r\n }\r\n\r\n // All tags have been sent to AppNexus, ask AppNexus to load all the ads at once.\r\n apntag.loadTags();\r\n };\r\n\r\n const _astAdLoadedHandler = (event) => {\r\n _printAdInformation('Ad loaded ');\r\n _printAdInformation(event);\r\n _dispatchAdRequestEndEvent(event);\r\n };\r\n\r\n /**\r\n *\r\n * Indicates the AST JS Library is already loaded, and trigger the loadAdsEvent.\r\n */\r\n const _astLoadedCallback = function () {\r\n isAstLoaded = true;\r\n isAstLoading = false;\r\n apntag = root.apntag;\r\n\r\n if (!apntag) {\r\n return;\r\n }\r\n\r\n apntag.onEvent('adLoaded', _astAdLoadedHandler);\r\n apntag.onEvent('adAvailable', _astAdAvailableHandler);\r\n apntag.onEvent('adNoBid', _astAdNoBidHandler);\r\n root.dispatchEvent(loadAdsEvent);\r\n };\r\n\r\n /**\r\n *\r\n * Attachs an event to the object, checks the browser supports to choose the better option to handle the load event.\r\n *\r\n * @private\r\n * @param {object} object - Object where the load event will be attached.\r\n * @param {function} event - Function that will be executed when the event load for the object is triggered.\r\n */\r\n const _attachEventToLoad = function (object, event) {\r\n if (object.addEventListener) {\r\n object.addEventListener('load', event, false);\r\n } else if (root.attachEvent) {\r\n object.attachEvent('onload', event);\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Load the AST Script async.\r\n *\r\n * @private\r\n * @param {function} callback - Function to execute when the load of the AST.js file has finished.\r\n */\r\n const _loadAstScriptAsync = function () {\r\n if (isAstLoaded) {\r\n // AST JS Library has already been loaded. Do not load it again.\r\n return;\r\n }\r\n _dispatchAdsScriptStartEvent();\r\n const tag = document.getElementsByTagName('meta')[0];\r\n const script = document.createElement('script');\r\n\r\n _attachEventToLoad(script, () => {\r\n root.dispatchEvent(atsLoadedEvent);\r\n _dispatchAdsScriptEndEvent();\r\n });\r\n script.async = true;\r\n script.src = document.location.protocol + CONFIGURATION.get('ASTURL');\r\n script.type = 'text/javascript';\r\n script.dataset.resource = 'ast';\r\n tag.parentNode.insertBefore(script, tag);\r\n isAstLoading = true;\r\n };\r\n\r\n /**\r\n *\r\n * Callback function to be executed when the AJAX to retrieve the Ad Parameters has returned. Stores the data in the global parameters variable and changes the value of the areParametersDefined flag to true.\r\n *\r\n * @private\r\n * @callback\r\n * @param {object} data JSON object with the parameters.\r\n */\r\n const _adParametersLoadedCallback = function (data) {\r\n parameters = data;\r\n areParametersDefined = true;\r\n\r\n for (let i = 0; i < onParametersLoaded.length; i++) {\r\n const callback = onParametersLoaded[i];\r\n if (typeof callback === 'function') {\r\n callback();\r\n }\r\n }\r\n onParametersLoaded = [];\r\n };\r\n\r\n /**\r\n *\r\n * Callback function to be executed when the AJAX to retrieve the Ad Parameters and refresh the parameters.\r\n *\r\n * @private\r\n * @callback\r\n * @param {object} data JSON object with the parameters.\r\n */\r\n const _adParametersLoadedAndRefreshCallback = function (data) {\r\n parameters = data;\r\n areParametersDefined = true;\r\n for (var i = 0; i < onParametersLoaded.length; i++) {\r\n const callback = onParametersLoaded[i];\r\n if (typeof callback === 'function') {\r\n callback();\r\n }\r\n }\r\n onParametersLoaded = [];\r\n if (\r\n typeof apntag === 'undefined' ||\r\n apntag === null ||\r\n typeof apntag.refresh !== 'function' ||\r\n !areParametersDefined\r\n ) {\r\n return;\r\n }\r\n\r\n const utCalls = getUtCallGroups();\r\n const adIds = getNodeIdsFromSelectors(utCalls);\r\n const keywords = JSON.parse(parameters);\r\n delete keywords.placements;\r\n delete keywords.useLazyLoad;\r\n apntag.clearRequest();\r\n\r\n for (var i = 0; i < adIds.length; i++) {\r\n apntag.setKeywords(adIds[i], keywords);\r\n\r\n const element = document.getElementById(adIds[i]);\r\n if (element.dataset.override === 'true') {\r\n fastdom.mutate(() => {\r\n element.innerHTML = '';\r\n });\r\n }\r\n }\r\n\r\n utCalls.forEach((utCall) => {\r\n _createAppNexusRequest(true, utCall);\r\n });\r\n };\r\n\r\n /**\r\n * logs event and time information if a appnexus cookie is present.\r\n * @param event - a string that represents an event or action that occurred\r\n * in the application.\r\n * @param time - is a variable that represents the time associated with the event being logged.\r\n */\r\n const _printInformation = (event, time) => {\r\n if (localStorage.getItem('debugAppNexus')) {\r\n console.info(`${event} time: ${time}`);\r\n }\r\n };\r\n\r\n /**\r\n * logs the provided text to the console if a specific cookie 'debugAppNexus' is present.\r\n * @param text - The `text` parameter is a string that contains information to be printed.\r\n */\r\n const _printAdInformation = (text) => {\r\n if (localStorage.getItem('debugAppNexus')) {\r\n console.info(text);\r\n }\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'astStart' and records the timing of the event.\r\n */\r\n const _dispatchAdsScriptStartEvent = () => {\r\n root.dispatchEvent(new CustomEvent('adScriptStart'));\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'astEnd' and prints\r\n * information about the time taken for the AST script to download.\r\n */\r\n const _dispatchAdsScriptEndEvent = () => {\r\n root.dispatchEvent(new CustomEvent('adScriptEnd'));\r\n _printInformation('Ads script', performance.now());\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'adParametersStart' and records the timing when it is called.\r\n */\r\n const _dispatchAdParametersStartEvent = () => {\r\n root.dispatchEvent(new CustomEvent('adParametersStart'));\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'adParametersEnd' and calculates the time taken for ad parameters to end.\r\n */\r\n const _dispatchAdParametersEndEvent = () => {\r\n root.dispatchEvent(new CustomEvent('adParametersEnd'));\r\n _printInformation('Ad parameters', performance.now());\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'adRequestStart' and records the timing of the ad request start.\r\n */\r\n const _dispatchAdRequestStartEvent = () => {\r\n root.dispatchEvent(new CustomEvent('adRequestStart'));\r\n };\r\n\r\n /**\r\n * dispatches a custom event named 'adRequestEnd' with details about the element ID and timing information.\r\n * @param event - object containing information related to an ad request.\r\n */\r\n const _dispatchAdRequestEndEvent = (event) => {\r\n root.dispatchEvent(\r\n new CustomEvent('adRequestEnd', {\r\n detail: {\r\n elementId: event.targetId,\r\n },\r\n })\r\n );\r\n _printInformation(`${event.targetId}`, performance.now());\r\n };\r\n\r\n /**\r\n *\r\n * Initialize and executes the process to load the Ads from AppNexus.\r\n *\r\n * @private\r\n */\r\n const _loadAds = function () {\r\n _dispatchAdRequestStartEvent();\r\n let url = CONFIGURATION.get('PARAMETERSURL') + escape(window.location.href) + '&_=' + new Date().getTime();\r\n const params = document.querySelectorAll('[data-ads-parameter]');\r\n for (let i = 0; i < params.length; i++) {\r\n const value = params[i].value;\r\n const name = params[i].dataset.paramname;\r\n url += `&${name}=${value}`;\r\n }\r\n const skinAd = document.getElementById(CONFIGURATION.get('SKINADID'));\r\n\r\n if (skinAd !== 'undefined' && skinAd !== null) {\r\n document.body.insertBefore(skinAd, document.body.firstChild);\r\n }\r\n\r\n // Trigger an AJAX Request to obtain the parameters we need to pass into AppNexus calls while we wait until the AST Library is ready.\r\n _ajaxRequest(url, _adParametersLoadedCallback);\r\n\r\n if (isAstLoaded) {\r\n // The AST JS library has been loaded we can make calls to AppNexus.\r\n // Trigger onLoadAdsEvent to execute the call to AppNexus and generate the Ads.\r\n root.dispatchEvent(loadAdsEvent);\r\n } else if (!isAstLoading) {\r\n // The AST JS library has not been loaded and there's not request to load it.\r\n // Trigger a request to load the AST JS library and add a request to load Ads in the adRequestsQueue.\r\n _loadAstScriptAsync(_astLoadedCallback);\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Causes a new ad server call and refreshes the specific ad element on the page.\r\n *\r\n * @public\r\n * @param {string} divElementId The unique identifier of a specific ad slot. One or more identifiers can be specified in an array.\r\n */\r\n const refreshAd = function (divElementId) {\r\n if (\r\n typeof apntag === 'undefined' ||\r\n apntag === null ||\r\n typeof apntag.refresh !== 'function' ||\r\n !areParametersDefined\r\n ) {\r\n return;\r\n }\r\n\r\n apntag.refresh([divElementId]);\r\n };\r\n\r\n /**\r\n *\r\n * Causes a new ad server call and refreshes all the ad elements on the page.\r\n *\r\n * @public\r\n */\r\n const refreshAllAds = function () {\r\n if (\r\n typeof apntag === 'undefined' ||\r\n apntag === null ||\r\n typeof apntag.refresh !== 'function' ||\r\n !areParametersDefined\r\n ) {\r\n return;\r\n }\r\n\r\n const utCalls = getUtCallGroups();\r\n utCalls.forEach((utCall) => {\r\n const elements = getIdsFromElements(document.querySelectorAll(utCall));\r\n apntag.refresh(elements);\r\n });\r\n };\r\n\r\n /**\r\n *\r\n * Causes a new ad server call and refreshes all the ad elements on the page.\r\n *\r\n * @public\r\n */\r\n const refreshAllAdsAndUpdateParams = function () {\r\n _dispatchAdRequestStartEvent();\r\n let url = CONFIGURATION.get('PARAMETERSURL') + escape(window.location.href) + '&_=' + new Date().getTime();\r\n const params = document.querySelectorAll('[data-ads-parameter]');\r\n for (let i = 0; i < params.length; i++) {\r\n const value = params[i].value;\r\n const name = params[i].dataset.paramname;\r\n url += `&${name}=${value}`;\r\n }\r\n _ajaxRequest(url, _adParametersLoadedAndRefreshCallback);\r\n };\r\n\r\n /**\r\n *\r\n * Get the element Id from Array.\r\n *\r\n * @param {String} elements Array of elements.\r\n */\r\n var getIdsFromElements = function (elements) {\r\n return Array.prototype.slice.call(elements).map((element) => element.id);\r\n };\r\n\r\n /**\r\n *\r\n * Delete an element from the AppNexus Call.\r\n *\r\n * @param {String} tagId Identifier of the ad impression, usually the ID of the HTML container for the Ad.\r\n */\r\n const deleteAdOnDemand = function (tagId) {\r\n if (apntag && apntag.requests && apntag.requests.tags) {\r\n delete apntag.requests.tags[tagId];\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Delete an element from the AppNexus Call.\r\n *\r\n * @param {String} tagId Identifier of the ad impression, usually the ID of the HTML container for the Ad.\r\n */\r\n const deleteAdsOnDemand = function (tagsId) {\r\n if (apntag && apntag.requests && apntag.requests.tags) {\r\n Array.prototype.map.call(tagsId, (tagId) => {\r\n delete apntag.requests.tags[tagId];\r\n });\r\n }\r\n };\r\n\r\n /**\r\n *\r\n * Simplify the Ads creation in one only call\r\n *\r\n * @param {Boolean} param Decides if ad its going to be overwritten.\r\n * @public\r\n */\r\n const generateAllAds = function (param) {\r\n param = typeof param === 'undefined' ? true : !!param;\r\n\r\n if (\r\n typeof apntag === 'undefined' ||\r\n apntag === null ||\r\n typeof apntag.refresh !== 'function' ||\r\n !areParametersDefined\r\n ) {\r\n return;\r\n }\r\n\r\n const utCalls = getUtCallGroups();\r\n utCalls.forEach((utCall) => {\r\n _createAppNexusRequest(param, utCall);\r\n });\r\n };\r\n\r\n /**\r\n *\r\n * Causes a new ad server call. This method should be used only when the elements where the ads are going to be displayed are added via JavaScript.\r\n *\r\n * @param {Boolean} overwrite overwrite\r\n * @public\r\n */\r\n const regenerateAdCalls = function (overwrite) {\r\n _dispatchAdRequestStartEvent();\r\n if (\r\n typeof apntag === 'undefined' ||\r\n apntag === null ||\r\n typeof apntag.refresh !== 'function' ||\r\n !areParametersDefined\r\n ) {\r\n return;\r\n }\r\n\r\n const utCalls = getUtCallGroups();\r\n utCalls.forEach((utCall) => {\r\n _createAppNexusRequest(overwrite, utCall);\r\n });\r\n };\r\n\r\n /**\r\n *\r\n * Creates a new ad request on demand to the given query selector expression passed as parameter.\r\n *\r\n * @param {String | HTMLElement[]} selector - query selector expression that will be used to find the ad(s) we want to create on demand.\r\n * @public\r\n */\r\n const createAdOnDemand = function (selector) {\r\n let index;\r\n let elementId;\r\n let element;\r\n let width;\r\n let height;\r\n const appNexusRequests = [];\r\n\r\n // This is to validate if the global variable is undefined and if contains the push method.\r\n if (typeof apntag === 'undefined' || apntag === null || typeof apntag.anq.push !== 'function') {\r\n return;\r\n }\r\n\r\n // If the parameters has not being defined call the function itself to wait for the AJAX to get the parameters to end.\r\n if (!areParametersDefined) {\r\n onParametersLoaded.push(() => {\r\n _createAppNexusRequest(false, selector);\r\n });\r\n return;\r\n }\r\n\r\n if (typeof selector !== 'string' && !Array.isArray(selector)) {\r\n return;\r\n }\r\n\r\n const adElements = Array.isArray(selector) ? selector : document.querySelectorAll(selector);\r\n\r\n if (!adElements || adElements.length === 0) {\r\n return;\r\n }\r\n\r\n let length = adElements.length;\r\n const randomNumber = Math.floor(Math.random() * 2000) + 100;\r\n\r\n for (index = 0; index < length; index += 1) {\r\n element = adElements[index];\r\n elementId = element.id;\r\n width = Math.round(element.getAttribute('data-width'));\r\n height = Math.round(element.getAttribute('data-height'));\r\n\r\n if (width === 0 && height === 0) {\r\n continue;\r\n }\r\n\r\n // HACK: Index parameter could be tracked in AppNexus code to identify each ad so we are using the index plus a random base to avoid collisions.\r\n // This code can be improved.\r\n appNexusRequests.push(_executeRequestToAppNexus(elementId, width, height, index + randomNumber));\r\n }\r\n\r\n length = appNexusRequests.length;\r\n\r\n for (index = 0; index < length; index += 1) {\r\n apntag.anq.push(appNexusRequests[index]);\r\n }\r\n\r\n // All tags have been sent to AppNexus, ask AppNexus to load all the ads at once.\r\n apntag.loadTags();\r\n };\r\n\r\n /**\r\n *\r\n * Deletes an ad tag previously requested from the AppNexus manager. This method prevents tags removed from the HTML to be requested to the ads server.\r\n * @param {String} selector a string containing one or more selectors to match. This string must be a valid CSS selector string.\r\n */\r\n const deleteAdsBySelector = function (selector) {\r\n const nativeIds = [];\r\n const elements = document.querySelectorAll(selector);\r\n\r\n if (elements && elements.length > 0) {\r\n Array.prototype.map.call(elements, (div) => {\r\n nativeIds.push(div.id);\r\n });\r\n }\r\n\r\n if (nativeIds.length > 0) {\r\n deleteAdsOnDemand(nativeIds);\r\n }\r\n };\r\n\r\n // Attach an event listener to the root object (window) for the custom onLoadAdsEvent event.\r\n loadAdsEvent.initEvent('onLoadAdsEvent', false, false);\r\n\r\n // Initial load with default parameters for _createAppNexusRequest, related to ticket https://builderhomesite.atlassian.net/browse/BDXNHS-1569\r\n root.addEventListener(\r\n 'onLoadAdsEvent',\r\n () => {\r\n const createRequestsCallback = function () {\r\n const utCalls = getUtCallGroups();\r\n utCalls.forEach((utCall) => {\r\n _createAppNexusRequest(false, utCall);\r\n });\r\n };\r\n\r\n if (!areParametersDefined) {\r\n onParametersLoaded.push(createRequestsCallback);\r\n } else {\r\n createRequestsCallback();\r\n }\r\n },\r\n false\r\n );\r\n\r\n // Attach an event listener to the root object (window) for the custom onLoadAdsEvent event.\r\n atsLoadedEvent.initEvent('onAstLoadedEvent', false, false);\r\n root.addEventListener('onAstLoadedEvent', _astLoadedCallback, false);\r\n\r\n if (document.readyState === 'complete') {\r\n _loadAds();\r\n } else {\r\n // On the load event of the root element (window) trigger a call to load Ads.\r\n _attachEventToLoad(root, _loadAds);\r\n }\r\n\r\n /**\r\n *\r\n * Attaches the click event to the native ad card of the SRP\r\n *\r\n * @public\r\n */\r\n var bindEventsToNativeAdCard = function (iframeForNativeAd, nativePosition, clickTrackers, isMobileDevice) {\r\n const iframeBody = iframeForNativeAd.contentWindow.document.body;\r\n\r\n const onBeginTouch = function (e) {\r\n iframeBody.addEventListener('touchend', clickAdFunction);\r\n };\r\n\r\n const onMove = function (e) {\r\n iframeBody.removeEventListener('touchend', clickAdFunction);\r\n };\r\n\r\n var clickAdFunction = function (e) {\r\n e.preventDefault();\r\n for (let j = 0; j < clickTrackers.length; j += 1) {\r\n requestHttpGet(clickTrackers[j]);\r\n }\r\n\r\n const url = iframeBody.querySelector('[data-native-contact]').href;\r\n window.open(url, '_blank');\r\n\r\n return false;\r\n };\r\n\r\n iframeBody.addEventListener('click', clickAdFunction);\r\n };\r\n\r\n return {\r\n refreshAds: refreshAllAds,\r\n refreshAdsAndUpdateParams: refreshAllAdsAndUpdateParams,\r\n refreshAdByName: refreshAd,\r\n regenerateAds: regenerateAdCalls,\r\n generateAllAds,\r\n loadAdOnDemand: createAdOnDemand,\r\n deleteAdByTagName: deleteAdOnDemand,\r\n deleteAllAdsBySelector: deleteAdsBySelector,\r\n };\r\n});\r\n","const authObject = {\r\n isAuth0Loaded: false,\r\n isAuth0Loading: false,\r\n lock: null,\r\n settings: null,\r\n Auth0Lock: null,\r\n};\r\n\r\nconst authLoadSampleRate = 300;\r\n\r\n/**\r\n * @private\r\n * onAuth0Error: reject the promise when authetication library is loaded.\r\n *\r\n * @param {Function} reject the promise.\r\n */\r\nconst onAuth0Error = (reject) => {\r\n authObject.isAuth0Loading = false;\r\n authObject.isAuth0Loaded = false;\r\n reject(new Error(`Unable to load Auth0 API.`));\r\n};\r\n\r\n/**\r\n * @private\r\n * onAuth0Loaded: resolve the promise when authentication library is loaded \r\n * @param {Function} resolve the promise.\r\n */\r\nconst onAuth0Loaded = (resolve) => {\r\n authObject.isAuth0Loaded = true;\r\n resolve();\r\n};\r\n\r\n/**\r\n * @private\r\n * loadAuth0Module: import the auth0 lock module.\r\n *\r\n * @param {Function} resolve the promise\r\n * @param {Function} reject the promise\r\n */\r\nconst loadAuth0Module = async (resolve, reject) => {\r\n await import('../../styles/components/auth0.scss');\r\n import('auth0-lock').then(({ Auth0Lock }) => {\r\n authObject.Auth0Lock = Auth0Lock;\r\n onAuth0Loaded.call(this, resolve);\r\n })\r\n .catch(onAuth0Error.bind(this, reject));\r\n};\r\n\r\n/**\r\n * @private\r\n * isAuthLoaded: resolve the promise when auth0 is loaded. Retry when auth0 is loading.\r\n *\r\n * @param {Function} resolve the promise. \r\n */\r\nconst isAuthLoaded = (resolve) => {\r\n if (authObject.isAuth0Loaded) {\r\n resolve();\r\n } else {\r\n setTimeout(isAuthLoaded.bind(null, resolve), authLoadSampleRate);\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n * waitForAuth: wait for Authentication library, waiting a @see authLoadSampleRate milliseconds.\r\n * \r\n * @returns {Promise} notify that authentication library is loaded.\r\n */\r\nconst waitForAuth = () =>\r\n new Promise((resolve) => {\r\n setTimeout(isAuthLoaded.bind(null, resolve), authLoadSampleRate);\r\n});\r\n\r\n/**\r\n * @private\r\n * getSignUpFieldByName: get the sign up field by name in setting authetication object.\r\n * @param {String} name of the sign up field.\r\n * \r\n * @returns {Object} with the sign up field information. \r\n */\r\nconst getSignUpFieldByName = (name) => authObject.settings.options\r\n.additionalSignUpFields.find(item => item.name === name) || {};\r\n\r\n/**\r\n * @private\r\n * goToNextPageAfterLogIn: redirect to the next page after user is autheticated.\r\n * @param {String} config with the next page to go.\r\n * \r\n */\r\nconst goToNextPageAfterLogIn = (nextPage) => {\r\n if (nextPage) {\r\n window.location = nextPage;\r\n } else {\r\n window.location.reload();\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n * onSignUpReady: method to execute when sign up form is visible to the user.\r\n * This method helps to:\r\n * Avoid numbers in zip code input\r\n * Disable zip code when user is outside of United States.\r\n */\r\nconst onSignUpReady = () => {\r\n const zip = document.querySelector('[name=\"PostalCode\"]');\r\n zip.setAttribute('maxlength', 5);\r\n zip.onkeypress = function (evt) {\r\n const charCode = (evt.which) ? evt.which : evt.keyCode;\r\n if (charCode > 31 && (charCode < 48 || charCode > 57)) { return false; }\r\n return true;\r\n };\r\n const outsideUS = document.querySelector('[name=\"OutsideUS\"]');\r\n outsideUS.onchange = function () {\r\n zip.disabled = outsideUS.checked;\r\n };\r\n const outSideUsItem = getSignUpFieldByName(\"OutsideUS\");\r\n if (outSideUsItem.prefill === 'true') {\r\n zip.disabled = true;\r\n }\r\n\r\n const outsideUSContainer = outsideUS.closest('div');\r\n const fieldsContainer = outsideUSContainer.parentElement;\r\n const lastFormElement = fieldsContainer.lastElementChild;\r\n\r\n lastFormElement.after(authObject.settings.legalContentSection.content.cloneNode(true));\r\n};\r\n\r\n/**\r\n * @private\r\n * onAuthenticated: method to execute after user is autheticated.\r\n * It helps to request NHS servers to create the cookies and get the main information of the user.\r\n * \r\n * @param {Object} authResult information with the user token. \r\n */\r\nconst onAuthenticated = async (authResult) => {\r\n document.querySelectorAll('.auth0-lock-close-button').forEach((element) => {\r\n element.remove();\r\n });\r\n\r\n const accessToken = authResult.accessToken;\r\n const keepMeLogged = document.querySelector('[name=\"KeepMeLogged\"]');\r\n let keepMeLoggedValue = false;\r\n if (keepMeLogged) {\r\n keepMeLoggedValue = keepMeLogged.checked;\r\n }\r\n const url = authObject.settings.basic.auth0Authenticated;\r\n const parameters = {\r\n accessToken,\r\n keepMeLogged: keepMeLoggedValue\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify(parameters),\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n });\r\n\r\n if (response.ok) {\r\n const data = await response.json();\r\n\r\n if (data.Success) {\r\n if (authObject.settings.afterLogin) {\r\n authObject.settings.afterLogin();\r\n }\r\n goToNextPageAfterLogIn(authObject.settings.nextPage);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n * onSigninReady: method to execute when sign in form is visible to the user.\r\n * This method helps to:\r\n * Create the keep me login checkbox from authentication modal.\r\n */\r\nconst onSigninReady = () => {\r\n const referenceElement = document.querySelector('.auth0-lock-alternative');\r\n const parentContainer = referenceElement.parentElement;\r\n parentContainer.insertBefore(\r\n authObject.settings.keepMeLoggedSection.content.cloneNode(true),\r\n referenceElement);\r\n referenceElement.after(authObject.settings.legalContentSection.content.cloneNode(true));\r\n};\r\n\r\n/**\r\n * @public\r\n * loadAuth0: load the auth0 library.\r\n * @param {Function} authLoaded to be executed when the promise is resolved.\r\n * @param {*} authError to be executed when the promise is reject.\r\n *\r\n * @returns {Promise} that will be resolved. \r\n */\r\nexport function loadAuth0(authLoaded, authError) {\r\n if (!authObject.isAuth0Loading) {\r\n authObject.isAuth0Loading = true;\r\n return new Promise(loadAuth0Module).then(authLoaded).catch(authError);\r\n }\r\n\r\n if (authObject.isAuth0Loaded) {\r\n return Promise.resolve().then(authLoaded).catch(authError);\r\n }\r\n\r\n return waitForAuth().then(authLoaded).catch(authError);\r\n};\r\n\r\n/**\r\n * @public\r\n * createAuthInstance: create the authetication instance\r\n * @param {Object} settings of the authentication modal.\r\n * @param {Function} onCloseModal callback to be execute in hide event.\r\n */\r\nexport function createAuthInstance(settings, onCloseModal) {\r\n authObject.settings = settings;\r\n authObject.lock = new authObject.Auth0Lock(\r\n settings.basic.auth0ClientId,\r\n settings.basic.auth0Domain,\r\n settings.options);\r\n authObject.lock.on('signup ready', onSignUpReady);\r\n authObject.lock.on('authenticated', onAuthenticated);\r\n authObject.lock.on('signin ready', onSigninReady);\r\n authObject.lock.on('hide', onCloseModal);\r\n\r\n}\r\n\r\n/**\r\n * @public\r\n * showModal: open the authentication modal.\r\n *\r\n */\r\nexport function showModal() {\r\n authObject.lock.show();\r\n}","/*\r\n * MapLibrary is a facade for accessing a subset of functions of a third-party map provider subsystem.\r\n * By having a facade, non of the map components will ever need to know how to perform map operations,\r\n * instead of that they will rely on the facade in order to accomplish that.\r\n * For example, if we need to draw a boundary, we are going to ask the facade to draw it for us. The\r\n * facade internally will know how to retrieve a map center point, and how to draw a boundary around it,\r\n * these 2 map operations don't need to be know by any map component, they are known just by the facade.\r\n * From the previous example, notice how we achieved the interaction of 2 map operations just by\r\n * calling the facade and without knowing how the boundary drawing function works internally in order to\r\n * obtain the desired outcome of having a boundary represented in the map.\r\n */\r\n\r\n// State object for the map library facade.\r\n\r\nconst mapInstance = {\r\n isGoogleMapLoaded: false,\r\n isGoogleMapsLoading: false,\r\n map: null,\r\n locationBoundary: null,\r\n mapId: 'bdxproducts',\r\n markers: [],\r\n markersHashed: new Map(),\r\n sitePlans: [],\r\n interactiveMarkersOverlays: [],\r\n};\r\n\r\n/**\r\n * map cursosr values supported by Google Maps.\r\n */\r\nconst mapCursor = Object.freeze({\r\n pointer: 'pointer',\r\n grab: 'grab',\r\n grabbing: 'grabbing',\r\n default: '',\r\n});\r\n\r\n// Interval to sample waiting for the load event; this number is arbitrary.\r\nconst googleMapsLoadSampleRate = 100;\r\n\r\n// Lazy-dev, the facade should be able to load the Google Maps script by itself but to remove the complexity\r\n// of sharing the Google Maps API key with the JavaScript, we are defining the script in an HTML element from the page.\r\nconst googleMapsSource = document.querySelector('[google-maps-source]')?.href;\r\n\r\n/**\r\n * If the Google Maps API fails to load, set the loading and loaded flags to false and reject the promise.\r\n * @param reject - A function that rejects the promise.\r\n */\r\nconst onGoogleMapsError = (reject) => {\r\n mapInstance.isGoogleMapsLoading = false;\r\n mapInstance.isGoogleMapLoaded = false;\r\n reject(new Error(`Unable to load Google Maps API.`));\r\n};\r\n\r\n/**\r\n * When the Google Maps API is loaded, set the isGoogleMapLoaded property of the mapInstance object to\r\n * true and resolve the promise.\r\n * @param resolve - A function that is called when the promise is resolved.\r\n */\r\nconst onGoogleMapsLoaded = (resolve) => {\r\n mapInstance.isGoogleMapLoaded = true;\r\n resolve();\r\n};\r\n\r\n/**\r\n * Create a script element, set its source to the googlemapssource,\r\n * set its onerror property to a function that rejects the promise,\r\n * set its onload property to a function that resolves the promise.\r\n * @param resolve - The function to call when the script has loaded.\r\n * @param reject - A function that is called when the promise is rejected.\r\n */\r\nconst appendGoogleMapsScript = (resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = googleMapsSource;\r\n script.async = true;\r\n script.onerror = onGoogleMapsError.bind(this, reject);\r\n mapInstance.onload = onGoogleMapsLoaded.bind(this, resolve);\r\n document.head.appendChild(script);\r\n};\r\n\r\nwindow.initMap = () => mapInstance.onload();\r\n\r\n/**\r\n * If the map is loaded, resolve the promise.\r\n * If not, wait the amount of time from googleMapsLoadSampleRate and try again.\r\n * @param resolve - The resolve function of the promise.\r\n */\r\nconst isGoogleMapsLoaded = (resolve) => {\r\n if (mapInstance.isGoogleMapLoaded) {\r\n resolve();\r\n } else {\r\n setTimeout(isGoogleMapsLoaded.bind(null, resolve), googleMapsLoadSampleRate);\r\n }\r\n};\r\n\r\n/**\r\n * Wait the amount of time from googleMapsLoadSampleRate for Google Maps to load, and then resolve the promise.\r\n * @returns A promise that will resolve when the google maps api is loaded.\r\n */\r\nconst waitForGoogleMaps = () =>\r\n new Promise((resolve) => {\r\n setTimeout(isGoogleMapsLoaded.bind(null, resolve), googleMapsLoadSampleRate);\r\n });\r\n\r\n/**\r\n * Creates the hashed key to represent markers on the map. Hash key is used to several markers sharing the same\r\n * location can be allocated under the same key.\r\n */\r\nexport function createMarkerHashedKey(latitude, longitude) {\r\n return `${(+latitude).toFixed(2)},${(+longitude).toFixed(2)}`;\r\n}\r\n\r\n/**\r\n * cloneAndAppendTooltipToAdvanceMarker: this function clones a tooltip from sourceMarker and appends it to the tooltips\r\n * that destinationMarker holds, as destinationMarker is the physical redendered marker in the map that will\r\n * represent the sourceMarker on high/mid level zoom interactions.\r\n * @param {*} destinationMarker to append the tooltip\r\n * @param {*} sourceMarker to obtain the tooltip\r\n */\r\nconst cloneAndAppendTooltipToAdvanceMarker = (destinationMarker, sourceMarker) => {\r\n const clonedTooltip = sourceMarker.content.querySelector('[data-tooltip]').cloneNode(true);\r\n clonedTooltip.setAttribute('hidden', '');\r\n destinationMarker.content.appendChild(clonedTooltip);\r\n};\r\n\r\n/**\r\n * setMultipleInformationInSingleMarker: we share space in a latitude and longitude position for several markers\r\n * that could occupy the same geolocation. In those scenarios, only one marker among them is going to be represented\r\n * in the map. This function makes sure that one selected main marker can display useful information on behalf of\r\n * all the rest of markers it is representing.\r\n * @param markers - an array of markers occupying the same geolocation space.\r\n * @param advancedMarker - a new marker that will join the \"markers\" collection.\r\n */\r\nconst setMultipleInformationInSingleMarker = (markers, advancedMarker) => {\r\n const mainMarker = markers.find((marker) => marker.content.dataset.mainMarker);\r\n\r\n if (!mainMarker) {\r\n // There isn't a main marker yet, so the very first marker in the collection becomes the main marker.\r\n cloneAndAppendTooltipToAdvanceMarker(markers[0], advancedMarker);\r\n markers[0].content.dataset.mainMarker = true;\r\n } else if (advancedMarker?.zIndex <= mainMarker.zIndex) {\r\n // Append the advancedMarker tooltip to the mainMarker if it has lower or equal priority.\r\n cloneAndAppendTooltipToAdvanceMarker(mainMarker, advancedMarker);\r\n } else {\r\n // Set advancedMarker as the mainMarker since it has higher priority.\r\n advancedMarker.content.dataset.mainMarker = true;\r\n\r\n /**\r\n * if there was a main marker, it is not longer the one in charge since a higher priority\r\n * marker appeared for this location, so we remove the \"data-main-marker\" attribute from it.\r\n */\r\n mainMarker?.content.removeAttribute('data-main-marker');\r\n\r\n /**\r\n * since we now have a new main marker, we are going to move the information stored in the previous\r\n * priority marker to the new main marker since this last one is the one that will have a physical\r\n * representation in the map.\r\n */\r\n const markerToolTips = mainMarker.content.querySelectorAll('[data-tooltip]');\r\n\r\n const [firstTooltip, ...otherTooltips] = Array.from(markerToolTips);\r\n\r\n /**\r\n * Clone the first tooltip and append it to the advancedMarker. We clone it because the individual marker in the\r\n * map at a very low zoom level needs to have that tooltip to be shown when directly hovered. For all the other\r\n * ones besides the first one, they just need to be phisically removed from the previous main marker, and taken\r\n * to the new priority marker as it will be treated as a main marker from this point on.\r\n */\r\n const clonedFirstTooltip = firstTooltip.cloneNode(true);\r\n clonedFirstTooltip.setAttribute('hidden', '');\r\n advancedMarker.content.appendChild(clonedFirstTooltip);\r\n\r\n // Append the rest of the tooltips to the new main marker with highest priority.\r\n otherTooltips.forEach((tooltip) => {\r\n advancedMarker.content.appendChild(tooltip);\r\n });\r\n }\r\n};\r\n\r\nconst hashMarker = (marker, advancedMarker) => {\r\n const key = createMarkerHashedKey(marker.markerPosition.lat, marker.markerPosition.lng);\r\n\r\n if (mapInstance.markersHashed.has(key)) {\r\n const markersOnThisPosition = mapInstance.markersHashed.get(key);\r\n\r\n setMultipleInformationInSingleMarker(markersOnThisPosition, advancedMarker);\r\n\r\n const values = [...markersOnThisPosition, advancedMarker];\r\n mapInstance.markersHashed.set(key, values);\r\n } else {\r\n const values = [advancedMarker];\r\n mapInstance.markersHashed.set(key, values);\r\n }\r\n};\r\n\r\n/**\r\n * It creates a new marker if the marker doesn't already exist.\r\n * @param marker - object with the information to build the marker.\r\n * @returns A promise that resolves to a new marker.\r\n */\r\nconst createMarker = (marker) => {\r\n const advancedMarker = new window.google.maps.marker.AdvancedMarkerElement({\r\n content: marker.icon,\r\n position: marker.markerPosition,\r\n zIndex: marker.zIndex,\r\n title: marker.description,\r\n gmpClickable: true,\r\n });\r\n\r\n advancedMarker.communityId = marker.metaData.communityId;\r\n advancedMarker.ignoreVisibilityUpdates = marker.ignoreVisibilityUpdates;\r\n\r\n // Add the data-marker-element=\"true\" to the container element of the AdvancedMarkerElement,\r\n // with the purpose getting the main div of the marker.\r\n advancedMarker.element.dataset.markerElement = 'true';\r\n advancedMarker.element.setAttribute('aria-label', marker.description);\r\n\r\n advancedMarker.addListener('click', marker.events.click.bind(null, marker));\r\n mapInstance.markers.push(advancedMarker);\r\n hashMarker(marker, advancedMarker);\r\n};\r\n\r\n/**\r\n * It hides or show a marker if it's inside the map boundaries.\r\n * @param marker - an object the contains the information of the market to delete.\r\n */\r\nconst setMarkerVisibility = (marker, bounds, zoom) => {\r\n if (marker.ignoreVisibilityUpdates) {\r\n return;\r\n }\r\n\r\n const isVisible = bounds.contains(marker.position);\r\n\r\n if (zoom < 8) {\r\n marker.collisionBehavior = google.maps.CollisionBehavior.OPTIONAL_AND_HIDES_LOWER_PRIORITY;\r\n } else {\r\n marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED;\r\n }\r\n\r\n if (!isVisible && marker.map) {\r\n marker.map = null;\r\n }\r\n\r\n if (isVisible && !marker.map) {\r\n marker.map = mapInstance.map;\r\n }\r\n};\r\n\r\n/**\r\n * A function that is called when the map is visible or not.\r\n */\r\nconst onMapVisibilityChange = (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.intersectionRatio > 0 && entry.isIntersecting) {\r\n entry.target.dispatchEvent(new CustomEvent('mapVisible'));\r\n } else {\r\n entry.target.dispatchEvent(new CustomEvent('mapHide'));\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Creating an observer to detect when the map is visible or not.\r\n */\r\nconst mapObserver = (container) => {\r\n const options = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 1.0,\r\n };\r\n const observer = new IntersectionObserver(onMapVisibilityChange, options);\r\n observer.observe(container);\r\n};\r\n\r\n/**\r\n * If the Google Maps instance is not loading, load it.\r\n * If it is loading, wait for it to load.\r\n * If it is loaded, resolve the promise\r\n * @param googleMapsLoaded - A function that is called when the Google Maps instance has loaded.\r\n * @param googleMapsErrored - A function that will be called if the Google Maps script fails to load.\r\n * @returns A promise.\r\n */\r\nexport default function loadGoogleMaps(googleMapsLoaded, googleMapsErrored) {\r\n if (!mapInstance.isGoogleMapsLoading) {\r\n // Set the Google Maps instance as loading to prevent multiple requests.\r\n mapInstance.isGoogleMapsLoading = true;\r\n return new Promise(appendGoogleMapsScript).then(googleMapsLoaded).catch(googleMapsErrored);\r\n }\r\n\r\n if (mapInstance.isGoogleMapLoaded) {\r\n // If the Google Maps instance is already loaded resolve the promise.\r\n return Promise.resolve().then(googleMapsLoaded).catch(googleMapsErrored);\r\n }\r\n\r\n // Otherwise wait to review if the Google Maps instance has loaded.\r\n return waitForGoogleMaps().then(googleMapsLoaded).catch(googleMapsErrored);\r\n}\r\n\r\n/**\r\n * Create a new map instance and add a listener to the map's tilesloaded event.\r\n *\r\n * @param container - The DOM element that will contain the map.\r\n * @param settings - The settings object that you would normally pass to the Google Maps constructor.\r\n * @param events - An object with the functions that will be added to the map events is loaded.\r\n */\r\nexport function createMapInstance(container, settings, events) {\r\n settings.mapId = settings.mapId || mapInstance.mapId;\r\n mapInstance.map = new window.google.maps.Map(container, settings);\r\n\r\n window.google.maps.event.addListenerOnce(mapInstance.map, 'tilesloaded', () => {\r\n const mapInitialInformation = {\r\n zoom: mapInstance.map.getZoom(),\r\n };\r\n\r\n events.mapLoaded(mapInitialInformation);\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.map, 'idle', function () {\r\n const bounds = this.getBounds();\r\n events.coordinatesChanged(bounds);\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.map, 'dragstart', () => {\r\n container.dispatchEvent(new CustomEvent('mapDragStart'));\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.map, 'dragend', () => {\r\n container.dispatchEvent(new CustomEvent('mapDragEnd'));\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.map, 'click', (event) => {\r\n container.dispatchEvent(\r\n new CustomEvent('mapClick', {\r\n detail: {\r\n latLng: event.latLng,\r\n },\r\n })\r\n );\r\n });\r\n\r\n let currentZoom = mapInstance.map.getZoom();\r\n window.google.maps.event.addListener(mapInstance.map, 'zoom_changed', () => {\r\n const newZoom = mapInstance.map.getZoom();\r\n container.dispatchEvent(\r\n new CustomEvent('zoomChanged', {\r\n detail: {\r\n zoomLevel: newZoom,\r\n isZoomIn: newZoom > currentZoom,\r\n },\r\n })\r\n );\r\n currentZoom = newZoom;\r\n });\r\n\r\n mapObserver(container);\r\n}\r\n\r\n/**\r\n * removeMarkers: Clear the markers from the map and from the mapInstance memory.\r\n * @public\r\n */\r\nexport function removeMarkers() {\r\n mapInstance.markers.forEach((item) =>\r\n setTimeout(() => {\r\n item.map = null;\r\n }, 0)\r\n );\r\n mapInstance.markers = [];\r\n mapInstance.markersHashed = new Map();\r\n}\r\n\r\n/**\r\n * paintMarker: It takes an array of markers configuration, and adds them from the map.\r\n * @param {object} markersToAdd: array of marker config object.\r\n * @public\r\n */\r\nexport function paintMarker(markers) {\r\n const markersToCreate = markers.filter(\r\n (item) =>\r\n !mapInstance.markers.some(\r\n (marker) => marker.position.lat === item.markerPosition.lat && marker.position.lng === item.markerPosition.lng\r\n )\r\n );\r\n\r\n markersToCreate.forEach((item) => setTimeout(() => createMarker(item), 0));\r\n}\r\n\r\n/**\r\n * updateBoundaries: this function creates a logical squared area that grows depending on the markers plotted in a map.\r\n * In order to create that area, we rely in North, South, East and West boundaries received as parameter. These 4\r\n * points represent the MinLatitude, MinLongitude, MaxLatitude and MaxLongitude new boundaries to set on the map.\r\n * @param {Array} mapCorners: Object containing a MinLatitude, MinLongitude, MaxLatitude and MaxLongitude. These\r\n * coordinates will determine the boundaries of the map.\r\n * @public\r\n */\r\nexport function updateBoundaries(mapBoundaries) {\r\n const properties = ['MinLatitude', 'MinLongitude', 'MaxLatitude', 'MaxLongitude'];\r\n const isValidBoundary = properties.every((property) => Object.prototype.hasOwnProperty.call(mapBoundaries, property));\r\n\r\n if (!isValidBoundary) {\r\n return;\r\n }\r\n\r\n /*\r\n A LatLngBounds is a rectangular area defined by two points (the southwest and northeast corners)\r\n */\r\n const bounds = new google.maps.LatLngBounds();\r\n const southwestPoint = new google.maps.LatLng(mapBoundaries.MinLatitude, mapBoundaries.MinLongitude);\r\n\r\n bounds.extend(southwestPoint);\r\n\r\n const northeastPoint = new google.maps.LatLng(mapBoundaries.MaxLatitude, mapBoundaries.MaxLongitude);\r\n\r\n bounds.extend(northeastPoint);\r\n\r\n mapInstance.map.fitBounds(bounds);\r\n}\r\n\r\n/**\r\n * updateMarkers: From the instance array of markers, adjust visiblity them from the map.\r\n */\r\nexport function updateMarkersVisibility() {\r\n const bounds = mapInstance.map.getBounds();\r\n const zoom = mapInstance.map.getZoom();\r\n\r\n if (zoom < 12) {\r\n setTimeout(() => {\r\n mapInstance.markersHashed.forEach((value) => {\r\n const marker = value.sort((markerA, markerB) => markerB.zIndex - markerA.zIndex)[0];\r\n setTimeout(() => setMarkerVisibility(marker, bounds, zoom), 0);\r\n });\r\n }, 0);\r\n } else {\r\n setTimeout(\r\n () => mapInstance.markers.forEach((item) => setTimeout(() => setMarkerVisibility(item, bounds, zoom), 0)),\r\n 0\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * updateMapCenter: It takes an object with coordinates, and updates the map center.\r\n * @param coordinates - {latitude: number, longitude: number}\r\n */\r\nexport function updateMapCenter(coordinates) {\r\n mapInstance.map.setCenter({ lat: coordinates.latitude, lng: coordinates.longitude });\r\n}\r\n\r\n/**\r\n * showMarker function will find an Advanced Marker and execute the function setMarkerVisibility on it.\r\n * @param {int} communityId is the identifier of the marker we want to show.\r\n */\r\nexport function showMarkers(communityId) {\r\n const markersToShow = mapInstance.markers.filter((item) => item.communityId === communityId);\r\n\r\n markersToShow.forEach((markerToShow) => {\r\n const bounds = mapInstance.map.getBounds();\r\n const zoom = mapInstance.map.getZoom();\r\n markerToShow.ignoreVisibilityUpdates = false;\r\n setMarkerVisibility(markerToShow, bounds, zoom);\r\n });\r\n}\r\n\r\n/**\r\n * hideMarker function will find an Advanced Marker and set it's map property to null.\r\n * @param {int} communityId is the identifier of the marker we want to hide.\r\n */\r\nexport function hideMarkers(communityId) {\r\n const markersToHide = mapInstance.markers.filter((item) => item.communityId === communityId);\r\n\r\n markersToHide.forEach((markerToHide) => {\r\n markerToHide.ignoreVisibilityUpdates = true;\r\n markerToHide.setMap(null);\r\n });\r\n}\r\n\r\n/**\r\n * Updats the minimum zoom level of the map. If the current zoom level is less than the new zoom limit,\r\n * then update the map zoom level to the new zoom limit.\r\n *\r\n * In this context minimum zoom level refers to the zoom out level that the map can be set to.\r\n * The lower the zoom level the more zoomed out the map is.\r\n *\r\n * @param newZoomLimit - The new minimum zoom level that the map should be set to.\r\n * @returns A boolean value indicating if the map current zoom level was updated.\r\n */\r\nexport function updateMinimumZoomLevel(newZoomLimit) {\r\n const currentZoom = mapInstance.map.getZoom();\r\n const currentMinZoom = mapInstance.map.minZoom;\r\n const doesZoomLevelNeedToBeUpdated = currentZoom < newZoomLimit;\r\n\r\n if (currentMinZoom !== newZoomLimit) {\r\n mapInstance.map.setOptions({ minZoom: newZoomLimit });\r\n }\r\n\r\n // Google Maps the zoom level lower values indicate a higher zoomed out level.\r\n if (doesZoomLevelNeedToBeUpdated) {\r\n mapInstance.map.setZoom(newZoomLimit);\r\n }\r\n\r\n return doesZoomLevelNeedToBeUpdated;\r\n}\r\n\r\n/**\r\n * dispatchCustomEventOnDocument: dispatches a custom event on the document that holds the map.\r\n *\r\n * @param eventName - The event identifier for any subscriber expecting to listen a custom event on the document.\r\n * @param eventDetail - The event information for the subscriber to a given custom event on the document.\r\n */\r\nconst dispatchCustomEventOnDocument = (eventName, eventDetail) => {\r\n const event = new CustomEvent(eventName, { detail: eventDetail });\r\n document.dispatchEvent(event);\r\n};\r\n\r\n/**\r\n * drawBoundary: draws a boundary in the map. The boundary shape should be a KML (Keyhole Markup Language)\r\n * and it must be requested from an url.\r\n * For details check: https://developers.google.com/maps/documentation/javascript/kml\r\n *\r\n * @param boundaryUrl - The boundary url with the shape to be draw on the map.\r\n */\r\nexport function drawBoundary(boundaryUrl) {\r\n mapInstance.locationBoundary?.setMap(null);\r\n const boundaries = {};\r\n\r\n if (!boundaryUrl) {\r\n dispatchCustomEventOnDocument('newBoundariesShown', { boundaries });\r\n } else {\r\n mapInstance.locationBoundary = new window.google.maps.KmlLayer(boundaryUrl, {\r\n suppressInfoWindows: true,\r\n preserveViewport: true,\r\n map: mapInstance.map,\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.locationBoundary, 'defaultviewport_changed', () => {\r\n boundaries.MaxLatitude = mapInstance.locationBoundary.getDefaultViewport().getNorthEast().lat();\r\n boundaries.MaxLongitude = mapInstance.locationBoundary.getDefaultViewport().getNorthEast().lng();\r\n boundaries.MinLatitude = mapInstance.locationBoundary.getDefaultViewport().getSouthWest().lat();\r\n boundaries.MinLongitude = mapInstance.locationBoundary.getDefaultViewport().getSouthWest().lng();\r\n\r\n dispatchCustomEventOnDocument('newBoundariesShown', { boundaries });\r\n });\r\n\r\n window.google.maps.event.addListener(mapInstance.locationBoundary, 'status_changed', () => {\r\n if (mapInstance.locationBoundary.getStatus() !== 'OK') {\r\n dispatchCustomEventOnDocument('newBoundariesShown', { boundaries });\r\n }\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * addOverlay function is the first step for rendering an OverlayView. It is in charge of adding the container of the\r\n * OverlayView in the desired map.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn, for instance: north,\r\n * south, east and west values where the OverlayView will be rendered.\r\n */\r\nconst addOverlay = function (resource) {\r\n const panes = this.getPanes();\r\n const mainWrapper = panes.overlayLayer.querySelector(`[data-community-map-wrapper-id=\"${resource.communityId}\"]`);\r\n panes.overlayMouseTarget.appendChild(resource.overlay);\r\n\r\n if (resource.isInteractiveSitePlan && resource.polygonsContainer) {\r\n panes.overlayLayer.appendChild(resource.polygonsContainer);\r\n }\r\n\r\n if (!mainWrapper) {\r\n panes.mapPane.appendChild(resource.container.parentElement);\r\n }\r\n};\r\n\r\n/**\r\n * isOverlayInViewport will return true if the overlay is within map vieport, false if not.\r\n * @param {Object} sitePlanId to check if is inside of the viewport.\r\n */\r\nexport function isSitePlanInViewport(sitePlanId) {\r\n const overlay = mapInstance.sitePlans.find((sitePlan) => sitePlan.sitePlanId === sitePlanId);\r\n\r\n if (!overlay) {\r\n return false;\r\n }\r\n\r\n const mapBounds = mapInstance.map.getBounds();\r\n return mapBounds.intersects(overlay.overlayBounds);\r\n}\r\n\r\n/**\r\n * isSitePlanIntersectingMapBounds function will check if a given siteplan is intersecting the map viewport.\r\n * @param {Object} sitePlan to identify if it is intersecting user viewport or not.\r\n * @returns a flag indicating whether a siteplan is intersecting map viewport or not.\r\n */\r\nexport function isSitePlanIntersectingMapBounds(sitePlan) {\r\n const sitePlanBounds = new google.maps.LatLngBounds(\r\n new google.maps.LatLng(sitePlan.south, sitePlan.west),\r\n new google.maps.LatLng(sitePlan.north, sitePlan.east),\r\n );\r\n \r\n const mapBounds = mapInstance.map.getBounds();\r\n return mapBounds.intersects(sitePlanBounds);\r\n}\r\n\r\n/**\r\n * drawOverlay function will be called every time the map is dragged around. It is in charge of moving the OverlayView\r\n * along with the map so it keeps fitting in the provided creation coordinates.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn, for instance: north,\r\n * south, east and west values where the OverlayView will be rendered.\r\n */\r\nconst drawOverlay = function (resource) {\r\n const overlayProjection = this.getProjection();\r\n\r\n const overlayBounds = new google.maps.LatLngBounds(\r\n new google.maps.LatLng(resource.south, resource.west),\r\n new google.maps.LatLng(resource.north, resource.east)\r\n );\r\n\r\n const southWestPoint = overlayProjection.fromLatLngToDivPixel(overlayBounds.getSouthWest());\r\n const northEastPoint = overlayProjection.fromLatLngToDivPixel(overlayBounds.getNorthEast());\r\n\r\n this.overlayBounds = overlayBounds;\r\n\r\n resource.onDraw?.(resource, southWestPoint, northEastPoint);\r\n};\r\n\r\n/**\r\n * removeOverlay function will remove an overlay from the map.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn, for instance: north,\r\n * south, east and west values where the OverlayView will be rendered.\r\n */\r\nconst removeOverlay = function (resource) {\r\n resource.onRemove?.(resource);\r\n};\r\n\r\n/**\r\n * createSitePlanOverlay is the way map library facade exposes the OverlayView of Google Maps. By calling\r\n * this function, the interested caller will get an OverlayView rendered in the Search Results' map.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn, for instance: north,\r\n * south, east and west values where the OverlayView will be rendered.\r\n */\r\nexport function createSitePlanOverlay(resource) {\r\n const overlay = mapInstance.sitePlans.find((plan) => plan.sitePlanId === resource.sitePlanId);\r\n\r\n if (overlay) {\r\n return;\r\n }\r\n\r\n const overlayView = new google.maps.OverlayView();\r\n overlayView.communityId = resource.communityId;\r\n overlayView.sitePlanId = resource.sitePlanId;\r\n overlayView.communityMapUrl = resource.imageUrl;\r\n mapInstance.sitePlans.push(overlayView);\r\n\r\n overlayView.onAdd = addOverlay.bind(overlayView, resource);\r\n overlayView.draw = drawOverlay.bind(overlayView, resource);\r\n overlayView.onRemove = removeOverlay.bind(overlayView, resource);\r\n\r\n overlayView.setMap(mapInstance.map);\r\n}\r\n\r\n/**\r\n * removeSitePlanOverlay removes a given Community Ma by setting its OverlayView's map to null.\r\n * The removeOverlay function of the map will be invoked as a result of setting the map property to null,\r\n * removing any OverlayView related HTML from the DOM.\r\n * @param {int} communityId is the community map identifier.\r\n */\r\nexport function removeSitePlanOverlay(communityId) {\r\n const sitePlans = mapInstance.sitePlans.filter((map) => map.communityId === communityId);\r\n\r\n sitePlans.forEach((map) => {\r\n map.setMap(null);\r\n });\r\n\r\n mapInstance.sitePlans = mapInstance.sitePlans.filter((map) => map.communityId !== communityId);\r\n}\r\n\r\n/**\r\n * getSitePlansOutOfViewport function will identify and return those community maps\r\n * that are no longer contained within the user's viewport.\r\n * @returns a collection of community maps no longer contained in user's viewport.\r\n */\r\nexport function getSitePlansOutOfViewport() {\r\n const mapBounds = mapInstance.map.getBounds();\r\n\r\n const sitePlansOutOfViewport = mapInstance.sitePlans\r\n .filter((sitePlan) => {\r\n try {\r\n const overlayBounds = sitePlan.overlayBounds;\r\n const isOverlayVisible = mapBounds.intersects(overlayBounds);\r\n\r\n return !isOverlayVisible;\r\n } catch (error) {\r\n return false;\r\n }\r\n })\r\n .map((sitePlan) => ({\r\n communityId: sitePlan.communityId,\r\n url: sitePlan.communityMapUrl,\r\n }));\r\n\r\n return sitePlansOutOfViewport;\r\n}\r\n\r\n/**\r\n * toggleDoubleClickZoom function will toggle the capability of\r\n * zoomin in when double clicking or double tapping.\r\n * @param {boolean} isDoubleClickZoomEnabled flag indicating whether\r\n * double click zoom has to be disabled or not.\r\n */\r\nexport function toggleDoubleClickZoom(isDoubleClickZoomEnabled) {\r\n mapInstance.map.setOptions({\r\n disableDoubleClickZoom: isDoubleClickZoomEnabled,\r\n });\r\n}\r\n\r\n/**\r\n * addOverlayMarkers function will add the container for interactive\r\n * markers into the overlay mouse target pane of the map.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be add,\r\n * for instance: markers to represent, community identifier where those markers belong, the\r\n * container where the overlay will be shown.\r\n */\r\nconst addOverlayMarkers = function (resource) {\r\n const panes = this.getPanes();\r\n panes.markerLayer.appendChild(resource.container);\r\n\r\n resource.onAdd?.(resource);\r\n};\r\n\r\n/**\r\n * drawOverlayMarkers function will be called every time the markers overlay changed zoon level\r\n * or was dragged around in the map.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn,\r\n * for instance: markers to represent, community identifier where those markers belong, the\r\n * container where the overlay will be shown.\r\n */\r\nconst drawOverlayMarkers = function (resource) {\r\n const overlayProjection = this.getProjection();\r\n resource.scale = mapInstance.map.getZoom();\r\n const mapBounds = mapInstance.map.getBounds();\r\n\r\n resource.markers.forEach((marker) => {\r\n const position = {\r\n latitude: parseFloat(marker.Latitude),\r\n longitude: parseFloat(marker.Longitude),\r\n };\r\n\r\n const center = new google.maps.LatLng(position.latitude, position.longitude);\r\n marker.center = overlayProjection.fromLatLngToDivPixel(center);\r\n marker.isVisible = mapBounds.contains(center);\r\n });\r\n\r\n resource.onDraw?.(resource);\r\n};\r\n\r\n/**\r\n * createInteractiveSitePlanMarkersOverlay function will create an overlay dedicated\r\n * to the interactive markers on top of a site plan.\r\n * @param {Object} resource with the basic information of the desired OverlayView to be drawn, for instance:\r\n * markers to represent, community identifier where those markers belong, the container where the overlay will be shown.\r\n */\r\nexport function createInteractiveSitePlanMarkersOverlay(resource) {\r\n const overlay = mapInstance.interactiveMarkersOverlays.find((markers) => markers.sitePlanId === resource.sitePlanId);\r\n\r\n if (overlay) {\r\n return;\r\n }\r\n\r\n const overlayView = new google.maps.OverlayView();\r\n overlayView.communityId = resource.communityId;\r\n mapInstance.interactiveMarkersOverlays.push(overlayView);\r\n\r\n overlayView.onAdd = addOverlayMarkers.bind(overlayView, resource);\r\n overlayView.draw = drawOverlayMarkers.bind(overlayView, resource);\r\n overlayView.onRemove = removeOverlay.bind(overlayView, resource);\r\n\r\n overlayView.setMap(mapInstance.map);\r\n}\r\n\r\n/**\r\n * removeInteractiveMarkersOverlay removes a set of interactive markers by setting its OverlayView's map to null.\r\n * The removeOverlay function of the interactive markers will be invoked as a result of setting the map property\r\n * to null, removing any OverlayView related HTML from the DOM.\r\n * @param {int} id is the site plan identifier.\r\n */\r\nexport function removeInteractiveMarkersOverlay(id) {\r\n const interactiveOverlays = mapInstance.interactiveMarkersOverlays.filter((map) => map.communityId === id);\r\n\r\n interactiveOverlays.forEach((overlay) => overlay.setMap(null));\r\n\r\n mapInstance.interactiveMarkersOverlays = mapInstance.interactiveMarkersOverlays.filter(\r\n (map) => map.communityId !== id\r\n );\r\n}\r\n\r\n/**\r\n * setZoomLevel: will set the map zoom level.\r\n * @param {int} zoomLevel to set.\r\n */\r\nexport function setZoomLevel(zoomLevel) {\r\n if (zoomLevel) {\r\n mapInstance.map.setZoom(zoomLevel);\r\n }\r\n}\r\n\r\n/**\r\n * changeMapCursorPointer function adjusts the cursor pointer option on the map\r\n * @param {string} cursorOption to be used on the map cursor.\r\n */\r\nexport function changeMapCursorPointer(cursorOption) {\r\n const cursor = mapCursor[cursorOption] || mapCursor.default;\r\n mapInstance.map.setOptions({ draggableCursor: cursor });\r\n}\r\n","import { IdleQueue } from 'idlize/IdleQueue';\r\n/* Class that represents the redux beacon target to track Google Tag Manager events */\r\nclass GoogleTagManager {\r\n constructor() {\r\n this.events = [];\r\n this.queue = new IdleQueue({ ensureTasksRun: true });\r\n\r\n this.target = (events) => {\r\n this.startTime = this.startTime || +new Date();\r\n this.events = [...this.events, ...events];\r\n this.queue.pushTask(this.trackEvent.bind(this));\r\n };\r\n }\r\n\r\n /* Function to track the event that will have the time from when starts to queue and will stop after 15000ms */\r\n trackEvent() {\r\n const timeLapsed = +new Date() - this.startTime;\r\n const isTimeExpired = timeLapsed < 15000;\r\n\r\n /* If data layer is not defined and the time has not expired we shouldnt queue the event again */\r\n if (!window.dataLayer && isTimeExpired) {\r\n this.queue.pushTask(this.trackEvent.bind(this));\r\n return;\r\n }\r\n\r\n /* The event is not in queue anymore because the time has passed BUT the we need to continue to \r\n validate the datalayer */\r\n if (!window.dataLayer) {\r\n this.events = [];\r\n return;\r\n }\r\n\r\n while (this.events.length !== 0) {\r\n const event = this.events.shift();\r\n window.dataLayer.push(event);\r\n window.dataLayer.push({ params: null });\r\n }\r\n\r\n this.startTime = +new Date();\r\n }\r\n\r\n /* Gets event target */\r\n getTarget() {\r\n return this.target;\r\n }\r\n}\r\n\r\nexport default GoogleTagManager;\r\n","import GoogleTagManager from \"./services/googleTagManager\";\r\n\r\nexport default GoogleTagManager;","import { store$ } from '@redux/store';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\nimport { \r\n LocationType,\r\n selectCounties,\r\n selectListingCount,\r\n selectLocation,\r\n selectPage\r\n} from 'features/searchResultsFacets';\r\nimport updateDataLayer from 'layout/components/dataLayer';\r\nimport { selectModal } from 'layout/redux/selectors';\r\nimport { distinctUntilChanged, filter, map, merge, skip } from 'rxjs';\r\nimport { getPageType } from 'services/googleAnalytics';\r\nimport cleanObjectsEmptyProperties from 'utils/cleanObject';\r\nimport UrlExtensions from 'utils/urlExtension';\r\n\r\n/**\r\n * getEventForLocationChange: function to get an object for location change event\r\n * @param {object} location location object\r\n * @returns an object with properties for location change event\r\n */\r\nconst getEventForLocationChange = (location) => {\r\n let city = null;\r\n if (location.locationType !== LocationType.RectangularArea.toString()) {\r\n city = location.city || '';\r\n }\r\n\r\n return {\r\n event: 'location_change',\r\n [GoogleAnalyticsCustomDimensions.MarketId().getName()]: location.marketId,\r\n [GoogleAnalyticsCustomDimensions.City().getName()]: city,\r\n [GoogleAnalyticsCustomDimensions.MarketName().getName()]: location.marketName && location.marketState \r\n ? `${location.marketName}, ${location.marketState}` \r\n : undefined,\r\n [GoogleAnalyticsCustomDimensions.Location().getName()]: location.city\r\n ? `${location.city} ${location.marketStateName}`\r\n : location.marketStateName,\r\n };\r\n};\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the location leaf change, map the object to city, location, marketName and marketId custom dimensions.\r\n * Skip the first time for inital load.\r\n * Send the event location_change to notify tags in tag maanager when location change\r\n */\r\nconst locationChanged$ = store$.pipe(\r\n map(selectLocation),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n skip(1),\r\n map(getEventForLocationChange),\r\n map(cleanObjectsEmptyProperties)\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the page property change, map the object to currentPageNumber custom dimensions.\r\n * Skip the first time for inital load.\r\n * Send the event pagination_change to notify tags in tag maanager when pagination change\r\n */\r\nconst paginationChanged$ = store$.pipe(\r\n map(selectPage),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n skip(1),\r\n map((page) => ({\r\n event: 'pagination_change',\r\n [GoogleAnalyticsCustomDimensions.CurrentPageNumber().getName()]: page,\r\n }))\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the results type change, map the the selector to get the page type custom dimension.\r\n * Skip the first time for inital load.\r\n * Send the event product_change to notify tags in tag maanager when hosuing change\r\n */\r\nconst housingTypeChanged$ = store$.pipe(\r\n map((state) => state?.routingState?.currentUrl),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n map(UrlExtensions.getSubdirectory),\r\n distinctUntilChanged(),\r\n map((page) => ({\r\n event: 'product_change',\r\n [GoogleAnalyticsCustomDimensions.PageType().getName()]: getPageType(page),\r\n }))\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the counts change, map the the selector to get the page type custom dimension.\r\n * Skip the first time for inital load.\r\n */\r\nconst countsChanged$ = store$.pipe(\r\n map(selectListingCount),\r\n distinctUntilChanged(),\r\n skip(1),\r\n map((listingCount) => ({\r\n event: 'results_change',\r\n [GoogleAnalyticsCustomDimensions.MatchingResults().getName()]: listingCount,\r\n }))\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the counties change, map the the selector to get the counties custom dimension.\r\n */\r\nconst countiesChanged$ = store$.pipe(\r\n map(selectCounties),\r\n distinctUntilChanged(),\r\n filter(Boolean),\r\n map((counties) => ({\r\n event: 'counties_change',\r\n [GoogleAnalyticsCustomDimensions.Counties().getName()]: counties.map((county) => county.Value),\r\n }))\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the counties change, map the the selector to get the counties custom dimension.\r\n */\r\nconst leadModalOpened$ = store$.pipe(\r\n map(selectModal),\r\n distinctUntilChanged(),\r\n filter((modal) => modal?.name === 'leadGenerator'),\r\n map((modal) => ({\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: modal.listingInformation?.priceReductionLabel,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()]: modal.listingInformation?.communityName,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()]: modal.listingInformation?.brandName,\r\n [GoogleAnalyticsCustomDimensions.SpecId().getName()]: modal.listingInformation?.specId,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()]: modal.listingInformation?.planId,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()]: modal.listingInformation?.communityId,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()]: modal.listingInformation?.isBasic !== \"true\",\r\n }))\r\n);\r\n\r\n/**\r\n * Subscribing to the store.\r\n * When the counties change, map the the selector to get the counties custom dimension.\r\n */\r\nconst leadModalClosed$ = store$.pipe(\r\n map(selectModal),\r\n distinctUntilChanged(),\r\n filter((modal) => modal === null),\r\n map(() => ({\r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.SpecId().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()]: null,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()]: null,\r\n }))\r\n);\r\n\r\nmerge(\r\n countiesChanged$,\r\n countsChanged$,\r\n housingTypeChanged$,\r\n locationChanged$,\r\n paginationChanged$,\r\n leadModalOpened$,\r\n leadModalClosed$\r\n ).subscribe(\r\n updateDataLayer\r\n);\r\n","/**\r\n * This file is designed only for the events related to facets. For example, when we filter by beds,\r\n * baths, prices and so on.\r\n * It usually means that usually the action should have to save information on the store.\r\n */\r\n\r\nimport { ProductType, searchParametersActions } from 'features/searchResultsFacets';\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport { AvailableNow, ReadyToBuild } from 'constants/homeStatusTypesConstants';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { routingStateActions } from 'features/routing';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\n\r\nconst searchEvents = 'Search Events';\r\nconst searchRefinement = 'Search Refinement';\r\n\r\nfunction getPriceAction(price) {\r\n const { maximumPrice, minimumPrice } = price;\r\n const separator = maximumPrice && minimumPrice ? ',' : '';\r\n const action = `Price selected: ${minimumPrice ? 'low' : ''}${separator} ${maximumPrice ? 'high' : ''}`;\r\n // removing extra spaces and triming\r\n return action.replace(/\\s+/g, ' ').trim();\r\n}\r\n\r\nfunction getPriceLabel(price) {\r\n const { maximumPrice, minimumPrice } = price;\r\n const separator = maximumPrice && minimumPrice ? ',' : '';\r\n // removing extra spaces and triming\r\n const label = `${minimumPrice ? `Low: ${minimumPrice}` : ''}\r\n ${separator} ${maximumPrice ? `High: ${maximumPrice}` : ''}`;\r\n return label.replace(/\\s+/g, ' ').trim();\r\n}\r\n\r\nconst priceChanged = (action) =>\r\n new GoogleAnalyticsEvent(searchEvents, getPriceAction(action.payload), getPriceLabel(action.payload));\r\n\r\nconst bedChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Bedrooms: ${action.payload}`);\r\n\r\nconst bathChanged = (action) =>\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Bathrooms: ${action.payload}`); \r\n\r\nconst customHousingBoxClick = () =>\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, 'Custom & Build On Your Lot Tab');\r\n\r\nconst manufacturedHousingBoxClick = () =>\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, 'Home Type: Manufactured Homes');\r\n\r\nconst builderChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Builders: ${action.payload.brand.name}`);\r\n\r\nconst livingAreasChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Living Areas: ${action.payload}`);\r\n\r\nconst storiesChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Stories: ${action.payload}`);\r\n\r\nconst primaryBedroomChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Primary Bedroom: ${action.payload === '1' ? 'Up' : 'Down' }`);\r\n\r\nconst garagesChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Garages: ${action.payload}`);\r\n\r\nconst searchChanged = (action) => new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Search: ${action.payload.marketName}, ${action.payload.geoLocationState}`);\r\n\r\n// Function to know when a checkbox filter is active or not:\r\n// [Hot Deals, RV Garage, Only with Reviews, Active Adult Community]\r\nconst filterLabelDictionary = {\r\n [searchParametersActions.fetchConsumerPromos.type]: 'Hot Deals',\r\n [searchParametersActions.fetchPriceReduction.type]: 'Price Reduction',\r\n [searchParametersActions.fetchRvGarages.type]: 'RV Garage',\r\n [searchParametersActions.fetchBuilderReviews.type]: 'Only with Reviews',\r\n [searchParametersActions.fetchActiveAdult.type]: 'Active Adult Community'\r\n};\r\n\r\nconst filterSelected = (action) => {\r\n const isfilterActivated = action.payload;\r\n if (isfilterActivated === true) {\r\n return new GoogleAnalyticsEvent(searchEvents, searchRefinement, filterLabelDictionary[action.type]);\r\n }\r\n return [];\r\n};\r\n\r\n// Schools Advance Filters\r\n\r\nconst schoolsChanged = (action) => {\r\n const schoolsList = action.payload;\r\n const schoolsSelected = schoolsList.map((school) => school.name);\r\n\r\n if (schoolsSelected.length > 0) {\r\n return new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Schools: ${schoolsSelected.join(', ')}`);\r\n }\r\n\r\n return [];\r\n};\r\n\r\n// Amenities Advance Filters\r\n\r\nconst amenitiesLabelDictionary = {\r\n natureAreas: 'Nature Areas',\r\n pool: 'Pool',\r\n golfCourse: 'Golf Course',\r\n green: 'Green Areas',\r\n sportsFacilities: 'Sports Facilities',\r\n parks: 'Parks',\r\n views: 'Views',\r\n waterfront: 'Waterfront',\r\n gatedCommunity: 'Gated Community'\r\n};\r\n\r\nconst amenitiesChanged = (action) => {\r\n const amenitiesList = Object.keys(action.payload);\r\n const amenitiesSelected = amenitiesList.map((amenity) => amenitiesLabelDictionary[amenity]);\r\n\r\n if (amenitiesSelected.length > 0) {\r\n return new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Amenities: ${amenitiesSelected.join(', ')}`);\r\n }\r\n\r\n return [];\r\n};\r\n\r\n// The following logic is to setup the events for sort by\r\nconst sortSelectOpt = document.querySelector('[data-sort-select]');\r\n\r\nconst sortChanged = (action) => {\r\n const sortingValue = `${action.payload.sortBy},${action.payload.sortOrder}`;\r\n const sortingOption = sortSelectOpt.querySelector(`[value=\"${sortingValue}\"]`);\r\n \r\n return new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Sort: ${sortingOption?.innerHTML ?? \"default\"}`);\r\n};\r\n\r\n// The following logic is to setup the events for the hometype filters\r\n\r\nconst homeTypeLabelDictionary = {\r\n [searchParametersActions.fetchSingleFamily.type] : 'Single Family',\r\n [searchParametersActions.fetchLuxury.type] : 'Luxury Homes',\r\n [searchParametersActions.fetchCondosAndTownHomes.type] : 'Condos And TownHomes'\r\n};\r\n\r\nconst homeTypeNameDictionary = {\r\n [searchParametersActions.fetchSingleFamily.type]: 'singleFamily',\r\n [searchParametersActions.fetchLuxury.type]: 'luxury',\r\n [searchParametersActions.fetchCondosAndTownHomes.type]: 'condosAndTownHomes'\r\n};\r\n\r\nconst homeTypeChanged = (action) => {\r\n const homeTypeName = homeTypeNameDictionary[action.type];\r\n const isHomeTypeActivated = action.payload[homeTypeName];\r\n\r\n if (isHomeTypeActivated) {\r\n return new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Home Type: ${homeTypeLabelDictionary[action.type]}`);\r\n }\r\n\r\n return []; \r\n};\r\n\r\nconst moveInLabels = {\r\n '': 'Move-In Date',\r\n [AvailableNow]: 'Move now',\r\n '1-2': '1-2 Months',\r\n '3-6': '3-6 Months',\r\n [ReadyToBuild]: 'Buildable plans',\r\n};\r\n\r\nconst moveInChanged = (action) =>\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, `Move-In: ${moveInLabels[action.payload]}`);\r\n\r\n/**\r\n * This function returns an object with a key of event and a value of url_change.\r\n * This event is pushed to dataLayer and fired the pageview event\r\n */\r\nconst urlChange = () => ({\r\n event: 'url_change',\r\n});\r\n\r\nconst eventsMapper = (action) => {\r\n const { payload } = action;\r\n switch (action.type) {\r\n case searchParametersActions.fetchPrice.type:\r\n return debounceEvent(1000, priceChanged);\r\n case searchParametersActions.fetchBedrooms.type:\r\n return debounceEvent(1000, bedChanged);\r\n case searchParametersActions.fetchBathrooms.type:\r\n return debounceEvent(1000, bathChanged);\r\n case searchParametersActions.fetchCustom.type:\r\n return payload?.productType === ProductType.Custom.toString() ? debounceEvent(1000, customHousingBoxClick) : [];\r\n // These cases is for all the options of the Move In filter.\r\n case searchParametersActions.fetchMoveInDateByStatus.type:\r\n case searchParametersActions.clearMoveInDateFilter.type:\r\n case searchParametersActions.fetchMoveInDateByRange.type:\r\n return debounceEvent(1000, moveInChanged);\r\n case routingStateActions.updateUrl.type:\r\n return debounceEvent(1000, urlChange);\r\n // These cases is for all the checkbox options of the advance filters.\r\n case searchParametersActions.fetchConsumerPromos.type:\r\n case searchParametersActions.fetchPriceReduction.type:\r\n case searchParametersActions.fetchRvGarages.type:\r\n case searchParametersActions.fetchBuilderReviews.type:\r\n case searchParametersActions.fetchActiveAdult.type:\r\n return debounceEvent(100, filterSelected);\r\n case searchParametersActions.fetchLivingAreas.type:\r\n return debounceEvent(100, livingAreasChanged);\r\n case searchParametersActions.fetchStories.type:\r\n return debounceEvent(100, storiesChanged);\r\n case searchParametersActions.fetchPrimaryBedroom.type:\r\n return debounceEvent(100, primaryBedroomChanged);\r\n case searchParametersActions.fetchGarages.type:\r\n return debounceEvent(100, garagesChanged);\r\n // These cases is for all the options of the Home Type filter.\r\n case searchParametersActions.fetchSingleFamily.type:\r\n case searchParametersActions.fetchLuxury.type:\r\n case searchParametersActions.fetchCondosAndTownHomes.type:\r\n return debounceEvent(100, homeTypeChanged);\r\n case searchParametersActions.fetchBrandId.type:\r\n return debounceEvent(100, builderChanged);\r\n case searchParametersActions.fetchAmenities.type:\r\n return debounceEvent(100, amenitiesChanged);\r\n case searchParametersActions.fetchSchools.type:\r\n return debounceEvent(100, schoolsChanged);\r\n case searchParametersActions.fetchSort.type:\r\n return debounceEvent(100, sortChanged);\r\n case searchParametersActions.fetchLocations.type:\r\n return debounceEvent(100, searchChanged);\r\n case searchParametersActions.fetchManufactured.type:\r\n return payload?.productType === ProductType.Manufactured.toString() \r\n ? debounceEvent(1000, manufacturedHousingBoxClick) : [];\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);\r\n","import debounceEvent from '@redux-beacon/debounce-event';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport { userProfileActions } from 'features/userProfile';\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\n\r\n\r\nconst favoritesSaved = (action) => action.payload.housingProductType.getFavoriteGoogleAnalyticsEvent();\r\n\r\nconst eventsMapper = (action) => {\r\n switch (action.type) {\r\n case userProfileActions.saveFavoriteFulfilled.type:\r\n return debounceEvent(100, favoritesSaved);\r\n default:\r\n return [];\r\n }\r\n};\r\n \r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware); ","/**\r\n * This file is designed only for the events related to lead stuff. For example, when we submit one.\r\n * It usually means that usually the action should have to save information on the store.\r\n */\r\n\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\n\r\nconst getGoogleAnalyticsDTO = (action) => action.payload.googleAnalyticsDTO;\r\nconst uiStateActions = uiStateSlice.actions;\r\n\r\nconst eventsMapper = (action) => {\r\n switch (action.type) {\r\n case uiStateActions.fetchModal.type: {\r\n const isValid = getGoogleAnalyticsDTO(action);\r\n return isValid ? getGoogleAnalyticsDTO : [];\r\n }\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);\r\n","/**\r\n * This file is designed only for the events related to the pagination.\r\n */\r\n\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport debounceEvent from '@redux-beacon/debounce-event';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { buildNewUrl, getPaging, routingSelectors } from 'features/routing';\r\nimport { store } from '@redux/store';\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nfunction getURL(pageNumber) {\r\n const state = store.getState();\r\n const urlComponents = urlComponentsSelector(state);\r\n \r\n urlComponents.urlPaging = getPaging(pageNumber);\r\n const newURL = buildNewUrl(urlComponents);\r\n\r\n return newURL;\r\n}\r\n\r\nconst searchEvents = 'Search Events';\r\n \r\nconst pageNumberChanged = (action) => new GoogleAnalyticsEvent(searchEvents, action.payload, getURL(action.payload));\r\n\r\nconst pageSizeChanged = (action) => new GoogleAnalyticsEvent(searchEvents, 'Sort Option Selected', `${action.payload} per page`);\r\n\r\nconst pagingControlsClickPrevious = (action) => new GoogleAnalyticsEvent(searchEvents, 'Previous', \r\n getURL(action.payload));\r\n\r\nconst pagingControlsClickNext = (action) => new GoogleAnalyticsEvent(searchEvents, 'Next', getURL(action.payload));\r\n\r\nconst eventsMapper = (action) => {\r\n switch (action.type) {\r\n case searchParametersActions.fetchPagingControlsPrev.type:\r\n return debounceEvent(1000, pagingControlsClickPrevious);\r\n case searchParametersActions.fetchPagingControlsNext.type:\r\n return debounceEvent(1000, pagingControlsClickNext);\r\n case searchParametersActions.fetchPageSize.type:\r\n return debounceEvent(1000, pageSizeChanged);\r\n case searchParametersActions.fetchPageNumber.type:\r\n return debounceEvent(1000, pageNumberChanged);\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\n\r\ndocument.body.addEventListener('phoneAnchorClick', () => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('TDV Events', 'Phone Number Views', \r\n 'PhoneNumber Displayed - Lead Form');\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n})\r\n\r\ndocument.body.addEventListener('phoneAnchorTrackingClick', () => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('TDV Events', 'Calls Placed', \r\n 'Convirza Phone Number Click-Lead Form');\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n})","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\n\r\ndocument.body.addEventListener('schedulerAnchorClick', () => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('TDV Events', 'Clickthrough', \r\n 'Thank you page');\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n})","import { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\n\r\ndocument.body.addEventListener('closeAnchorClick', () => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Lead Events', 'Thank you page', \r\n 'Click on x');\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n})\r\n\r\ndocument.body.addEventListener('createAccountAnchorClick', () => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Sign In Pop Up', 'Sign In form Open - Thank you', \r\n 'Sign In Clicks');\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n})","/**\r\n * This file is designed only for the events related to UI changes. For example, when we open cards, forms, etc.\r\n * It usually means that usually the action does not save information on the store.\r\n */\r\n\r\nimport GoogleTagManager from 'middlewares/googleTagManager';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { createMiddleware } from 'redux-beacon';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\n\r\nconst getGoogleAnalyticsDTO = (action) => action.payload.googleAnalyticsDTO;\r\n\r\nconst uiStateActions = uiStateSlice.actions;\r\n\r\nconst eventsMapper = (action) => {\r\n switch (action.type) {\r\n case uiStateActions.modalInformation.type:\r\n case uiStateActions.trackUserEvent.type: {\r\n const isValid = getGoogleAnalyticsDTO(action);\r\n return isValid ? getGoogleAnalyticsDTO : [];\r\n }\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\nconst googleTagManager = new GoogleTagManager();\r\nconst searchResultsGoogleTagManagerMiddleware = createMiddleware(eventsMapper, googleTagManager.getTarget());\r\naddMiddleware(searchResultsGoogleTagManagerMiddleware);\r\n","// The pushState event changes the URL in the \\routing\\redux\\listeners.js file, but we still need\r\n// to reload the page when the browser's back/forward buttons are clicked. That is done here.\r\nwindow.addEventListener(\"popstate\", () => {\r\n window.location.reload();\r\n});\r\n","import { store$ } from '@redux/store';\r\nimport { distinctUntilChanged, fromEvent, map } from 'rxjs';\r\nimport { selectListingCount } from 'features/searchResultsFacets';\r\nimport fastdom from 'fastdom';\r\n\r\nconst backToTopButtonElement = document.querySelector('[data-back-to-top]');\r\n\r\nconst initBackToTopElement = () => {\r\n const clickBackToTop$ = fromEvent(backToTopButtonElement, 'click');\r\n\r\n /**\r\n * listening to changes on the store. When new results arrived to the search results page, this observable\r\n * will emit the amount of results shown to the user.\r\n */\r\n const onNewListings$ = store$.pipe(map(selectListingCount), distinctUntilChanged());\r\n\r\n /**\r\n * toggleBackToTopVisibility: when no results, hides the back to top button. Shows back to top when there\r\n * are results to display.\r\n * @param listingCount - an integer representing the amount of listings in the current search results page.\r\n */\r\n const toggleBackToTopVisibility = (listingCount) => {\r\n if (listingCount > 0) {\r\n backToTopButtonElement.removeAttribute('hidden');\r\n } else {\r\n backToTopButtonElement.setAttribute('hidden', '');\r\n }\r\n };\r\n\r\n clickBackToTop$.subscribe(() => {\r\n fastdom.mutate(() => {\r\n window.scrollTo({\r\n top: 0,\r\n behavior: 'smooth'\r\n });\r\n }, window);\r\n });\r\n onNewListings$.subscribe(toggleBackToTopVisibility);\r\n}\r\n\r\nif (backToTopButtonElement) {\r\n initBackToTopElement();\r\n}","import { fromEvent, filter, tap } from \"rxjs\";\r\nimport { store } from '@redux/store';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { LocationType, searchParametersActions } from 'features/searchResultsFacets';\r\nimport GoogleAnalyticsCustomDimensions from \"constants/googleAnalyticsCustomDimension\";\r\n\r\nconst listViewContainer = document.querySelector('[data-list-view-element]');\r\n\r\n// create a stream of click events on the listViewContainer element\r\nconst containerClick$ = fromEvent(listViewContainer, 'click');\r\n\r\nconst isBrandCard = (event) => !!event.target.closest('[data-builder-brand-card]');\r\nconst isBasicBrandCard = (event) => !!event.target.closest('[data-basic-card]');\r\nconst doesCardApplyBrandFilter = (event) => !!event.target.closest('[data-apply-brand-filter]');\r\nconst doesCardPointToReviewsBuilderShowcasePage = (event) => !!event.target.closest('[data-reviews-bsp]');\r\nconst isViewHomesLinkClick = (event) => {\r\n const anchorLink = event.target.closest('[data-brand-view-homes-link]');\r\n return !!anchorLink;\r\n};\r\nconst isViewCommunitiesLinkClick = (event) => {\r\n const anchorLink = event.target.closest('[data-brand-view-communities-link]');\r\n return !!anchorLink;\r\n};\r\nconst isBrandNameLinkClick = (event) => {\r\n const anchorLink = event.target.closest('a[data-builder-brand-name-about-url]') ||\r\n event.target.closest('a[data-builder-brand-name-reviews-url]');\r\n return !!anchorLink;\r\n};\r\nconst isBrandLogoLinkClick = (event) => {\r\n const anchorLink = event.target.closest('a[data-brand-logo-link]') || \r\n event.target.closest('a[data-brand-logo]');\r\n return !!anchorLink;\r\n};\r\n\r\nconst hasAboutPage = (event) => {\r\n const anchorLink = event.target.closest('[data-has-about-page]');\r\n return !!anchorLink;\r\n};\r\nconst isLearnMoreLinkClick = (event) => {\r\n const anchorLink = event.target.closest('a[data-brand-learn-more-link]');\r\n return !!anchorLink;\r\n};\r\n\r\n/**\r\n * Function to add GA Events and Custom Dimensions.\r\n */\r\n\r\nfunction addCustomDimensions (event){\r\n const card = event.target.closest('[data-builder-brand-card]');\r\n const brandName = card.dataset.brandName;\r\n\r\n const customDimensions = {\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()]: brandName,\r\n };\r\n return customDimensions;\r\n}; \r\n\r\n/**\r\n * This function build the Google Analytic object to set the event tracking.\r\n */\r\nconst emitGoogleAnalyticsEvent = (category, action, label, dimensions) => {\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent(category, action, label, dimensions);\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n}\r\n\r\n// Set the GA Events in the \"Builder Logo\" link.\r\ncontainerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(event => isBrandLogoLinkClick(event)),\r\n).subscribe( (event) => { \r\n emitGoogleAnalyticsEvent(\r\n 'Search Events', \r\n 'Search Refinement', \r\n 'All Builders Logo Clicked', \r\n addCustomDimensions(event)); \r\n }\r\n);\r\n\r\n// Set the GA Events on the basic card.\r\ncontainerClick$.pipe(\r\n filter(isBasicBrandCard),\r\n).subscribe( (event) => { \r\n emitGoogleAnalyticsEvent(\r\n 'Search Events', \r\n 'Search Refinement', \r\n 'Basic Builders Card Clicked', \r\n addCustomDimensions(event)); \r\n }\r\n);\r\n\r\n// Set the GA Events in the \"Learn More\" link.\r\ncontainerClick$.pipe(\r\n filter(isBasicBrandCard),\r\n filter(event => isLearnMoreLinkClick(event))\r\n).subscribe( () => { emitGoogleAnalyticsEvent('Search Events', 'Search Refinement',\r\n 'Basic Builders Learn More Clicked'); });\r\n\r\n// filter the stream to only include click events that are made on the card.\r\n// also filters the cards that shouldn't apply the custom click, \r\nconst cardClick$ = containerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(event => !isViewHomesLinkClick(event)),\r\n filter(event => !isBrandNameLinkClick(event)),\r\n filter(event => !isBrandLogoLinkClick(event)),\r\n filter(event => !hasAboutPage(event)),\r\n filter(doesCardApplyBrandFilter),\r\n tap((event) => {\r\n event.preventDefault();\r\n })\r\n);\r\n\r\nconst reviewsCardClick$ = containerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(event => !isViewHomesLinkClick(event)),\r\n filter(event => !isViewCommunitiesLinkClick(event)),\r\n filter(event => !isBrandLogoLinkClick(event)),\r\n filter(event => !isBrandNameLinkClick(event)),\r\n filter(doesCardPointToReviewsBuilderShowcasePage),\r\n );\r\n\r\ncontainerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(event => isBrandNameLinkClick(event))\r\n).subscribe((event) => {\r\n emitGoogleAnalyticsEvent(\r\n 'Search Events',\r\n 'Search Refinement',\r\n 'All Builders Name Clicked',\r\n addCustomDimensions(event));\r\n}\r\n);\r\n\r\nconst viewHomesClick$ = containerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(isViewHomesLinkClick),\r\n tap((event) => event.preventDefault())\r\n);\r\n\r\nconst viewCommunitiesClick$ = containerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(isViewCommunitiesLinkClick),\r\n tap((event) => event.preventDefault())\r\n);\r\n\r\nconst emitFetchBrandAction = (event) => {\r\n const card = event.target.closest('[data-builder-brand-card]');\r\n const resultType = event.target.dataset.resultTypeRedirect || card.dataset.resultTypeRedirect;\r\n const productType = event.target.dataset.productTypeRedirect || card.dataset.productTypeRedirect;\r\n const locationType = event.target.dataset.locationTypeRedirect || card.dataset.locationTypeRedirect;\r\n const brand = { name: card.dataset.brandName, id: card.dataset.brandId }\r\n const searchParametersState = store?.getState()?.searchParameters;\r\n\r\n // if the card is a no results card, all of their links are going to point to a market search by design\r\n if (searchParametersState.location.locationType !== LocationType.RectangularArea.name &&\r\n !!card.dataset.suggestedResultsCard\r\n ) {\r\n store.dispatch(searchParametersActions.fetchViewBrandMarketResults({\r\n brand, resultType, productType, locationType\r\n }));\r\n\r\n return;\r\n }\r\n\r\n store.dispatch(searchParametersActions.fetchViewBrandResults({\r\n brand, resultType, productType\r\n }));\r\n}\r\n\r\nconst redirectClickEventToUrl = (url) => {\r\n window.open(url, '_blank');\r\n }\r\n\r\ncontainerClick$.pipe(\r\n filter(isBrandCard),\r\n filter(event => !isViewHomesLinkClick(event)),\r\n filter(event => !isViewCommunitiesLinkClick(event)),\r\n filter(event => !isBrandNameLinkClick(event)),\r\n filter(event => !isBrandLogoLinkClick(event)),\r\n filter(event => !doesCardPointToReviewsBuilderShowcasePage(event)),\r\n filter(event => hasAboutPage(event)),\r\n ).subscribe((event) => {\r\n const brandCardElement = event.target.closest('[data-paid-builder-brand-card]');\r\n const url = brandCardElement?.querySelector('a[data-brand-logo-link]')?.href;\r\n redirectClickEventToUrl(url);\r\n emitGoogleAnalyticsEvent('Search Events', 'Search Refinement', 'All Builders Clicked');\r\n });\r\n\r\n\r\n// subscribe to the cardClick$ stream and execute a dispatch to update the brand.\r\ncardClick$.subscribe((event) => {\r\n emitFetchBrandAction(event)\r\n});\r\n\r\n// subscribe to the cardClick$ stream and execute a dispatch to update the brand.\r\nreviewsCardClick$.subscribe((event) => {\r\n const brandCardElement = event.target.closest('[data-builder-brand-card]');\r\n const url = brandCardElement?.querySelector('a[data-builder-brand-name-reviews-url]')?.href;\r\n redirectClickEventToUrl(url);\r\n emitGoogleAnalyticsEvent('Search Events', 'Search Refinement', 'All Builders Reviews Clicked');\r\n });\r\n\r\n// subscribe to the viewHomesClick$ stream and execute a dispatch to update the brand.\r\nviewHomesClick$.subscribe((event) => {\r\n emitFetchBrandAction(event);\r\n emitGoogleAnalyticsEvent('Search Events', 'Search Refinement', 'Community & Homes Tab', addCustomDimensions(event));\r\n});\r\n\r\n// subscribe to the viewCommunitiesClick$ stream and execute a dispatch to update the brand.\r\nviewCommunitiesClick$.subscribe((event) => {\r\n emitFetchBrandAction(event);\r\n emitGoogleAnalyticsEvent('Search Events', 'Search Refinement', 'Community & Homes Tab', addCustomDimensions(event));\r\n});","import { store$ } from '@redux/store';\r\nimport { map, filter, distinctUntilChanged, pairwise } from 'rxjs';\r\nimport PageLayout from '../../../layout/constants/pageLayoutNames';\r\n\r\nconst pageLayoutDivContainer = document.querySelector('[data-page-layout-container]');\r\n\r\n/**\r\n * changes the class of the srp container which determines how the page displays different elements\r\n * @param {*} layoutName\r\n */\r\nconst changePageLayoutClass = (layoutName) => {\r\n const [lastValue, newValue] = layoutName;\r\n if (pageLayoutDivContainer) {\r\n const lastPageLayoutName = PageLayout.fromKey(lastValue);\r\n const newPageLayoutName = PageLayout.fromKey(newValue);\r\n const newLayoutClass = [`nhs-c-wrapper--${newPageLayoutName}`, `nhs-mq-wrapper--${newPageLayoutName}-medium`];\r\n const layoutClassToRemove = [\r\n `nhs-c-wrapper--${lastPageLayoutName}`,\r\n `nhs-mq-wrapper--${lastPageLayoutName}-medium`,\r\n ];\r\n pageLayoutDivContainer.classList.remove(...layoutClassToRemove);\r\n pageLayoutDivContainer.classList.add('srp-content', ...newLayoutClass);\r\n }\r\n};\r\n\r\n// used to select the page layout from the UI store\r\nconst selectPageLayout = (state) => state?.uiState?.pageLayout;\r\n\r\n// create an observable that will emit the page layout when they change\r\nconst onPageLayoutChange$ = store$.pipe(map(selectPageLayout), filter(Boolean), distinctUntilChanged(), pairwise());\r\n\r\n// subscribe to the observable and call the toggleClearAllButton function\r\nonPageLayoutChange$.subscribe(changePageLayoutClass);\r\n","import { store, store$ } from '@redux/store';\r\nimport googleAdsEvent from 'features/googleAds';\r\nimport LeadFormType from 'features/leadGenerators';\r\nimport { selectUiState } from 'layout/redux/selectors';\r\nimport { recommendedCommunitiesSubmitted$ } from 'pages/searchResults/redux/observables';\r\nimport { distinctUntilKeyChanged, filter, map } from 'rxjs';\r\n\r\nconst excludeForms = [LeadFormType.InformationFormBasic.toString(), LeadFormType.AskQuestionFormPaid.toString()];\r\n\r\nconst paidModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => !excludeForms.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst trackPaidFormSend = () => store.dispatch(googleAdsEvent({ eventName: 'paidForm' }));\r\n\r\npaidModalSubmission$.subscribe(trackPaidFormSend);\r\n\r\nconst trackRecommendationModalSend = () => store.dispatch(googleAdsEvent({ eventName: 'recommendationModal' }));\r\n\r\nrecommendedCommunitiesSubmitted$.subscribe(trackRecommendationModalSend);\r\n","/**\r\n * Determines the click target based on the provided settings.\r\n *\r\n * @param {Object} settings - The settings object.\r\n * @param {boolean} settings.isNoResultsPage - Indicates whether the current page is a \"no results\" page.\r\n * @param {string} settings.clickTarget - The click target value that comes from the HTML.\r\n * @returns {string} The click target determined based on the provided settings.\r\n */\r\nfunction getClickTarget(settings) {\r\n if (settings.isNoResultsPage) {\r\n return \"Zero Results Card\";\r\n }\r\n\r\n return settings.clickTarget;\r\n}\r\n\r\nexport default getClickTarget;","import { store, store$ } from '@redux/store';\r\nimport HousingProductType from 'constants/housingProductType';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport googleAnalytics4Event from 'features/googleAnalytics4';\r\nimport {\r\n selectFetchCountsStatusAndsCounts,\r\n facetsPanelSelector,\r\n homeFactsSelectors,\r\n selectLinkedPopularPillsFilters,\r\n selectSorting\r\n} from 'features/searchResultsFacets';\r\nimport { MarkerType, locationSearchParameters } from 'features/searchResultsMap';\r\nimport { FavoriteType } from 'features/userProfile';\r\nimport {\r\n paidAskAQuestionLocationModalSubmission$,\r\n paidAskAQuestionPlanModalSubmission$,\r\n paidAskAQuestionSpecModalSubmission$,\r\n paidCommunityModalSubmission$,\r\n basicCommunityModalSubmission$,\r\n paidHomeModalSubmission$,\r\n basicPlanModalSubmission$,\r\n basicSpecModalSubmission$,\r\n basicListingModalSubmission$,\r\n paidManufacturedLocationModalSubmission$,\r\n paidManufacturedPlanModalSubmission$,\r\n paidManufacturedSpecModalSubmission$,\r\n paidMasterPlanCommunityModalSubmission$,\r\n recommendedCommunitiesSubmitted$,\r\n summaryCardCtaClicked$,\r\n summaryCardLinkClicked$,\r\n markerUrlOpened$,\r\n recommendedCommunitiesSubmittedBasic$,\r\n modalCloseButtonClicked$,\r\n onPendingFavoritesChanged$,\r\n markerPinClicked$,\r\n nearbyListingsCarouselScrolled$,\r\n carouselCloseButtonClicked$,\r\n communityStaticMapHovered$,\r\n communityStaticMapClicked$,\r\n communityStaticMapDoubleClicked$,\r\n communityStaticMapZoomChanged$,\r\n recommendedCommunitiesShow$,\r\n} from 'pages/searchResults/redux/observables';\r\nimport getClickTarget from 'pages/searchResults/services/eventTracking';\r\nimport {\r\n debounceTime,\r\n delay,\r\n distinctUntilChanged,\r\n distinctUntilKeyChanged,\r\n filter,\r\n fromEvent,\r\n fromEventPattern,\r\n map,\r\n merge,\r\n skip,\r\n withLatestFrom,\r\n} from 'rxjs';\r\nimport { getLocation, getMarketSession } from 'services/googleAnalytics4EventBuilder';\r\nimport RecommendedType from 'constants/RecommendedType';\r\n\r\nconst siteLinksEventName = 'site_links';\r\nconst outboundLinksEventName = 'outbound_links';\r\nconst buyingGuideEventsName = 'buyingguide_events';\r\n\r\nconst pageWindowClick$ = fromEvent(document, 'click');\r\n\r\n// #region List View Section\r\n/**\r\n * ! List View Section\r\n * All events related elements located in the list view should be placed in this region\r\n */\r\nconst recommendationLinkDetailClick$ = fromEvent(document.body, 'click').pipe(\r\n filter((event) => event.target.closest('[data-recommendation-detail-link]')),\r\n map((event) => event.target.closest('[data-recommendation-community-item]')),\r\n filter(Boolean)\r\n);\r\nconst listViewSection = document.querySelector('[data-list-view-element]');\r\nconst listViewSectionClicks$ = fromEvent(listViewSection, 'click');\r\n\r\nconst cardFavoriteButtonSelector = '[data-favorite-button]';\r\n\r\nconst noResultsListingLink = '[data-no-results-listings-link]';\r\nconst noResultsClearButton = '[data-no-results-clear-button]';\r\n\r\nconst paidMasterPlanCommunityCardSelector = '[data-standard-card][data-master-plan-community]';\r\nconst basicListingCardSelector = '[data-standard-card][data-basic-listing]';\r\n\r\nconst paidCommunityCardSelector = '[data-standard-card][data-paid-community]';\r\nconst paidPlanCardSelector = '[data-standard-card][data-paid-plan]';\r\nconst paidSpecCardSelector = '[data-standard-card][data-paid-spec]';\r\nconst basicCommunityCardSelector = '[data-standard-card][data-basic-community]';\r\nconst basicPlanCardSelector = '[data-standard-card][data-basic-plan]';\r\nconst basicSpecCardSelector = '[data-standard-card][data-basic-spec]';\r\nconst defaultMarketingStatus = 'Normal';\r\n\r\nconst paidBuilderCardSelector = '[data-builder-brand-card][data-paid-builder-brand-card]';\r\nconst basicBuilderCardSelector = '[data-builder-brand-card][data-basic-card]';\r\nconst brandNameLink = '[data-builder-brand-name-about-url]';\r\nconst viewCommunitiesLink = '[data-brand-view-communities-link]';\r\nconst viewHomesLink = '[data-brand-view-homes-link]';\r\nconst brandLogoLink = '[data-brand-logo-link]';\r\nconst reviewsArea = '[data-brand-reviews-score]';\r\nconst learnMoreLink = '[data-brand-learn-more-link]';\r\n\r\nconst paginationSection = document.querySelector('[data-pagination]');\r\nconst paginationSectionClicks$ = fromEvent(paginationSection, 'click');\r\nconst previousButtonSelector = '[data-previous]';\r\nconst nextButtonSelector = '[data-next]';\r\nconst pageNumberSelector = '[data-page]';\r\nconst pageSizeElement = document.querySelector('[data-page-size]');\r\nconst pageSizeChange$ = fromEvent(pageSizeElement, 'change');\r\n\r\nconst popularSearchSection = document.querySelector('[data-content-popular-searches]');\r\nconst popularSearchSectionClicks$ = fromEvent(popularSearchSection, 'click');\r\nconst popularSearchPillSelector = '[data-content-popular-searches] a';\r\nconst marketSnapshotsSection = document.querySelector('[data-content-market-snapshots]');\r\nconst marketSnapshotsSectionClicks$ = fromEvent(marketSnapshotsSection, 'click');\r\nconst syntheticGeoSearchSelector = '#nhs_SynthGeo a';\r\nconst citiesSearchSelector = '#nhs_TopResults a';\r\nconst topCommunitiesSearchSelector = '#nhs_TopCommunities a';\r\n\r\nconst geoLocationSearchSection = document.querySelector('[data-content-geo-location-proximity]');\r\nconst geoLocationSearchSectionClicks$ = fromEvent(geoLocationSearchSection, 'click');\r\n\r\nconst paidBoylLocationCardSelector = '[data-standard-card][data-paid-boyl-location]';\r\nconst paidBoylPlanCardSelector = '[data-standard-card][data-paid-boyl-plan]';\r\nconst paidBoylSpecCardSelector = '[data-standard-card][data-paid-boyl-spec]';\r\nconst basicBoylLocationCardSelector = '[data-standard-card][data-basic-boyl-location]';\r\nconst basicBoylPlanCardSelector = '[data-standard-card][data-basic-boyl-plan]';\r\nconst basicBoylSpecCardSelector = '[data-standard-card][data-basic-boyl-spec]';\r\n\r\nconst paidCustomLocationCardSelector = '[data-standard-card][data-paid-custom-location]';\r\nconst paidCustomPlanCardSelector = '[data-standard-card][data-paid-custom-plan]';\r\nconst paidCustomSpecCardSelector = '[data-standard-card][data-paid-custom-spec]';\r\nconst basicCustomLocationCardSelector = '[data-standard-card][data-basic-custom-location]';\r\nconst basicCustomPlanCardSelector = '[data-standard-card][data-basic-custom-plan]';\r\nconst basicCustomSpecCardSelector = '[data-standard-card][data-basic-custom-spec]';\r\n\r\nconst paidManufacturedLocationCardSelector = '[data-standard-card][data-paid-manufactured-location]';\r\nconst paidManufacturedPlanCardSelector = '[data-standard-card][data-paid-manufactured-plan]';\r\nconst paidManufacturedSpecCardSelector = '[data-standard-card][data-paid-manufactured-spec]';\r\nconst basicManufacturedLocationCardSelector = '[data-standard-card][data-basic-manufactured-location]';\r\nconst basicManufacturedPlanCardSelector = '[data-standard-card][data-basic-manufactured-plan]';\r\nconst basicManufacturedSpecCardSelector = '[data-standard-card][data-basic-manufactured-spec]';\r\n\r\nconst paidCommunityAndPaidLocationSelector = `${paidCommunityCardSelector}, ${paidBoylLocationCardSelector}, ${paidCustomLocationCardSelector}, ${paidManufacturedLocationCardSelector}`;\r\nconst paidPlanSelector = `${paidPlanCardSelector}, ${paidBoylPlanCardSelector}, ${paidCustomPlanCardSelector}, ${paidManufacturedPlanCardSelector}`;\r\nconst paidSpecSelector = `${paidSpecCardSelector}, ${paidBoylSpecCardSelector}, ${paidCustomSpecCardSelector}, ${paidManufacturedSpecCardSelector}`;\r\nconst basicCommunityAndBasicLocationSelector = `${basicCommunityCardSelector}, ${basicBoylLocationCardSelector}, ${basicCustomLocationCardSelector}, ${basicManufacturedLocationCardSelector}`;\r\nconst basicPlanSelector = `${basicPlanCardSelector}, ${basicBoylPlanCardSelector}, ${basicCustomPlanCardSelector}, ${basicManufacturedPlanCardSelector}`;\r\nconst basicSpecSelector = `${basicSpecCardSelector}, ${basicBoylSpecCardSelector}, ${basicCustomSpecCardSelector}, ${basicManufacturedSpecCardSelector}`;\r\n\r\nconst areaClickedPerCardElement = {\r\n image: 'Image Clicked',\r\n priceReduction: 'Price Link Clicked',\r\n communityName: 'Comm Link Clicked',\r\n planName: 'Home Link Clicked',\r\n specAddress: 'Home Link Clicked',\r\n default: 'Card Clicked',\r\n};\r\n\r\n// #region Regional Content\r\n/**\r\n * All events related elements located in the Regional Content section\r\n */\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any link in the Seo Content Area is clicked.\r\n */\r\nconst seoContentSection = document.querySelector('[data-regional-content]');\r\nconst seoContentSectionClicks$ = fromEvent(seoContentSection, 'click');\r\nconst seoContentSelector = '[data-regional-content] .location-table a';\r\n\r\nconst triggerSeoContentClickEvent = (element) => {\r\n const elementParent = element.parentElement;\r\n const elementTitle = elementParent.previousElementSibling\r\n\r\n const customProperties = {\r\n click_target: 'Seo Content Area',\r\n search_value: `${elementTitle.innerText}: ${element.innerText}`,\r\n click_target1: element.href,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst seoContentClicked$ = seoContentSectionClicks$.pipe(\r\n filter((event) => event.target.closest(seoContentSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nseoContentClicked$.subscribe(triggerSeoContentClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the Read More link is clicked.\r\n */\r\nconst readMoreSelector = '[data-read-more-footer]';\r\n\r\nconst triggerReadMoreClickEvent = () => {\r\n const customProperties = {\r\n click_target: 'Read More Bottom SRP',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst readMoreClicked$ = seoContentSectionClicks$.pipe(\r\n filter((event) => event.target.closest(readMoreSelector))\r\n);\r\n\r\nreadMoreClicked$.subscribe(triggerReadMoreClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the Read Less link is clicked.\r\n */\r\nconst readLessSelector = '[data-read-less-footer]';\r\n\r\nconst triggerReadLessClickEvent = () => {\r\n const customProperties = {\r\n click_target: 'Read Less Bottom SRP',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst readLessClicked$ = seoContentSectionClicks$.pipe(\r\n filter((event) => event.target.closest(readLessSelector))\r\n);\r\n\r\nreadLessClicked$.subscribe(triggerReadLessClickEvent);\r\n\r\n// #region Geo Location Content\r\n/**\r\n * All events related elements located in the Geo Location Content section\r\n */\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when a City is clicked.\r\n */\r\nconst triggerCityGeoSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'SRP Cities',\r\n search_value: element.innerText,\r\n click_target1: element.href,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst cityGeoSearchClicked$ = geoLocationSearchSectionClicks$.pipe(\r\n filter((event) => event.target.id.includes('FooterLinkCity')),\r\n map((event) => event.target)\r\n);\r\n\r\ncityGeoSearchClicked$.subscribe(triggerCityGeoSearchClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when a Zip is clicked.\r\n */\r\n\r\nconst triggerZipGeoSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'SRP Zips',\r\n search_value: element.innerText,\r\n click_target1: element.href,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst zipGeoSearchClicked$ = geoLocationSearchSectionClicks$.pipe(\r\n filter((event) => event.target.id.includes('FooterLinkZipCode')),\r\n map((event) => event.target)\r\n);\r\n\r\nzipGeoSearchClicked$.subscribe(triggerZipGeoSearchClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when a County is clicked.\r\n */\r\nconst triggerCountyGeoSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'SRP Counties',\r\n search_value: element.innerText,\r\n click_target1: element.href,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst countyGeoSearchClicked$ = geoLocationSearchSectionClicks$.pipe(\r\n filter((event) => event.target.id.includes('FooterLinkCounty')),\r\n map((event) => event.target)\r\n);\r\n\r\ncountyGeoSearchClicked$.subscribe(triggerCountyGeoSearchClickEvent);\r\n\r\n// #region Snippets\r\n/**\r\n * All events related elements located in the Popular Searches and Snippets\r\n */\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the Popular Search pills are clicked.\r\n */\r\nconst triggerPopularSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'Snippet - Popular Searches',\r\n search_value: element.innerText,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst popularSearchClicked$ = popularSearchSectionClicks$.pipe(\r\n filter((event) => event.target.closest(popularSearchPillSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\npopularSearchClicked$.subscribe(triggerPopularSearchClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any Synthetic Geo search is clicked.\r\n */\r\nconst triggerSyntheticSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'Snippet - Synthetic',\r\n search_value: element.innerText,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst syntheticSearchClicked$ = marketSnapshotsSectionClicks$.pipe(\r\n filter((event) => event.target.closest(syntheticGeoSearchSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nsyntheticSearchClicked$.subscribe(triggerSyntheticSearchClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any Newest Community is clicked.\r\n */\r\nconst topCommunitiesSearchClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'Snippet - Newest community table',\r\n search_value: element.innerText,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst topCommunitiesSearchClicked$ = marketSnapshotsSectionClicks$.pipe(\r\n filter((event) => event.target.closest(topCommunitiesSearchSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\ntopCommunitiesSearchClicked$.subscribe(topCommunitiesSearchClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any city search is clicked.\r\n */\r\nconst triggerCitiesSearchesClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'Snippet - Cities',\r\n search_value: element.innerText,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst citySearchClicked$ = marketSnapshotsSectionClicks$.pipe(\r\n filter((event) => event.target.closest(citiesSearchSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\ncitySearchClicked$.subscribe(triggerCitiesSearchesClickEvent);\r\n\r\n// #region Pagination\r\n/**\r\n * All events related elements located in the Pagination should be placed in this region\r\n */\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the previous button in the pagination is clicked.\r\n */\r\nconst triggerPreviousButtonClickEvent = () => {\r\n const customProperties = {\r\n click_target: 'Previous Button',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pagination_events', customProperties }));\r\n};\r\n\r\nconst previousButtonClicked$ = paginationSectionClicks$.pipe(\r\n filter((event) => event.target.closest(previousButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\npreviousButtonClicked$.subscribe(triggerPreviousButtonClickEvent);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the next button in the pagination is clicked.\r\n */\r\nconst triggerNextButtonClickEvent = () => {\r\n const customProperties = {\r\n click_target: 'Next Button',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pagination_events', customProperties }));\r\n};\r\n\r\nconst nextButtonClicked$ = paginationSectionClicks$.pipe(\r\n filter((event) => event.target.closest(nextButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nnextButtonClicked$.subscribe(triggerNextButtonClickEvent);\r\n\r\n/**\r\n * The triggerPageNumberClickEvent function is used to track the page number click on the pagination.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerPageNumberClickEvent = (element) => {\r\n const customProperties = {\r\n click_target: 'Page Select',\r\n search_value: element.dataset.page,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pagination_events', customProperties }));\r\n};\r\n\r\nconst pageNumberClicked$ = paginationSectionClicks$.pipe(\r\n filter((event) => event.target.closest(pageNumberSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\npageNumberClicked$.subscribe(triggerPageNumberClickEvent);\r\n\r\n/**\r\n * triggerPageSizeChangeEvent: Triggers when the page size changes.\r\n * @param {Event} event Change event object\r\n */\r\nconst triggerPageSizeChangeEvent = (event) => {\r\n const customProperties = {\r\n click_target: 'Page Count Select',\r\n search_value: event.target.value,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pagination_events', customProperties }));\r\n};\r\n\r\npageSizeChange$.subscribe(triggerPageSizeChangeEvent);\r\n\r\n// #region Builder Directory\r\n\r\n/**\r\n * Check if the element clicked is the brand name.\r\n */\r\nconst isBrandNameLinkClick = (event) => {\r\n const anchorLink = event.target.closest('a[data-builder-brand-name-about-url]') ||\r\n event.target.closest('a[data-builder-brand-name-reviews-url]');\r\n return !!anchorLink;\r\n};\r\n\r\n/**\r\n * All events related elements located in the Builder Directory tab should be placed in this region\r\n */\r\nconst getPaidBuilderCardProperties = (dataset) => ({\r\n brand_name: dataset.brandName,\r\n brand_id: dataset.brandId,\r\n is_paid: 'True',\r\n position: Number(dataset.index) + 1,\r\n});\r\n\r\n/*\r\nCard clicks in a brand card with reviews\r\n*/\r\nconst paidBuilderCardClickedWithReviews$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidBuilderCardSelector)),\r\n filter((event) => !event.target.closest(viewCommunitiesLink)),\r\n filter((event) => !event.target.closest(viewHomesLink)),\r\n filter((event) => !event.target.closest(brandNameLink)),\r\n filter((event) => !event.target.closest(brandLogoLink)),\r\n map((event) => ({\r\n cardElement: event.target.closest(paidBuilderCardSelector),\r\n element: event.target,\r\n })),\r\n filter(({ cardElement }) => cardElement.querySelector(reviewsArea)),\r\n);\r\n\r\nconst triggerBuilderCardClickReviewsEvent = ({ cardElement, element }) => {\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const cardLinkElement = cardElement.querySelector('[data-builder-brand-name-reviews-url]');\r\n\r\n const customProperties = {\r\n click_target: 'Reviews BD',\r\n click_target1: cardAreaClicked,\r\n destination: cardLinkElement?.href, \r\n ...getPaidBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'trustbuilder_events', customProperties }));\r\n};\r\n\r\npaidBuilderCardClickedWithReviews$.subscribe(triggerBuilderCardClickReviewsEvent);\r\n\r\n/*\r\nCard clicks in a brand card without reviews\r\n*/\r\nconst paidBuilderCardClickedArea$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidBuilderCardSelector)),\r\n filter((event) => !event.target.closest(viewCommunitiesLink)),\r\n filter((event) => !event.target.closest(viewHomesLink)),\r\n filter((event) => !event.target.closest(brandNameLink)),\r\n filter((event) => !event.target.closest(brandLogoLink)),\r\n filter((event) => !event.target.closest(reviewsArea)),\r\n map((event) => event.target.closest(paidBuilderCardSelector)),\r\n filter((card) => !card.querySelector(reviewsArea))\r\n);\r\n\r\n/**\r\n * The triggerBuilderPaidCommunitiesClickEvent function is used to track the View Communities Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\n\r\nconst triggerBuilderPaidCommunitiesClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuilderCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const cardLinkElement = cardElement.querySelector(viewCommunitiesLink);\r\n\r\n const customProperties = {\r\n click_target: 'View Communities BD',\r\n destination: cardLinkElement?.href,\r\n ...getPaidBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\npaidBuilderCardClickedArea$.subscribe(triggerBuilderPaidCommunitiesClickEvent);\r\n\r\nconst paidCommunityLinkClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(viewCommunitiesLink)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidCommunityLinkClicked$.subscribe(triggerBuilderPaidCommunitiesClickEvent);\r\n\r\n/**\r\n * The triggerBuilderPaidLogoClickEvent function is used to track the Builder Logo Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\n\r\nconst triggerBuilderPaidLogoClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuilderCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const cardLinkElement = cardElement.querySelector(brandLogoLink);\r\n\r\n const customProperties = {\r\n click_target: 'Learn more about builder',\r\n destination: cardLinkElement?.href,\r\n ...getPaidBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'showcase_events', customProperties }));\r\n};\r\n\r\nconst paidBuilderLogoClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(brandLogoLink)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidBuilderLogoClicked$.subscribe(triggerBuilderPaidLogoClickEvent);\r\n\r\nconst paidBuilderNameClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => isBrandNameLinkClick(event)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidBuilderNameClicked$.subscribe(triggerBuilderPaidLogoClickEvent);\r\n\r\npaidBuilderCardClickedArea$.subscribe(triggerBuilderPaidLogoClickEvent);\r\n\r\nconst triggerBuilderCardClickShowcaseEvent = ({ cardElement }) => {\r\n const cardDataset = cardElement.dataset;\r\n const cardLinkElement = cardElement.querySelector(brandLogoLink);\r\n\r\n const customProperties = {\r\n click_target: 'Learn more about builder',\r\n destination: cardLinkElement?.href,\r\n ...getPaidBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'showcase_events', customProperties }));\r\n};\r\n\r\npaidBuilderCardClickedArea$.subscribe(triggerBuilderCardClickShowcaseEvent);\r\n\r\n/**\r\n * The triggerBuilderPaidLinkClickEvent function is used to track the View Homes Link Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\n\r\nconst triggerBuilderPaidLinkClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuilderCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const cardLinkElement = cardElement.querySelector(viewHomesLink);\r\n\r\n const customProperties = {\r\n click_target: 'View Homes BD',\r\n destination: cardLinkElement?.href,\r\n ...getPaidBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_events', customProperties }));\r\n};\r\n\r\nconst paidBuilderLinkClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(viewHomesLink)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidBuilderLinkClicked$.subscribe(triggerBuilderPaidLinkClickEvent);\r\n\r\n// Basic Builder Card Events Below\r\n\r\nconst getBasicBuilderCardProperties = (dataset) => ({\r\n brand_name: dataset.brandName,\r\n brand_id: dataset.brandId,\r\n is_paid: 'False',\r\n position: Number(dataset.index) + 1,\r\n});\r\n\r\nconst basicBuilderClickedCard$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(basicBuilderCardSelector)),\r\n filter((event) => !event.target.closest(learnMoreLink)),\r\n map((event) => event.target)\r\n);\r\n\r\nconst triggerBuilderBasicCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicBuilderCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n\r\n const customProperties = {\r\n click_target: 'Card Clicked',\r\n click_target1: cardAreaClicked,\r\n ...getBasicBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_builder_area', customProperties }));\r\n};\r\n\r\nbasicBuilderClickedCard$.subscribe(triggerBuilderBasicCardClickEvent);\r\n\r\n/**\r\n * The triggerBuilderBasicLinkClickEvent function is used to track the Learn More Link Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\n\r\nconst triggerBuilderBasicLinkClickEvent = (element) => {\r\n const cardElement = element.closest(basicBuilderCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const cardLinkElement = cardElement.querySelector(learnMoreLink);\r\n\r\n const customProperties = {\r\n click_target: cardLinkElement.innerText,\r\n destination: cardLinkElement?.href,\r\n ...getBasicBuilderCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_builder_area', customProperties }));\r\n};\r\n\r\nconst basicBuilderLinkClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(learnMoreLink)),\r\n map((event) => event.target)\r\n);\r\n\r\nbasicBuilderLinkClicked$.subscribe(triggerBuilderBasicLinkClickEvent);\r\n\r\n/**\r\n * Checks if a price is valid and not equal to zero.\r\n * @param price - is a variable that represents the price of a listing\r\n */\r\nconst isPriced = (price) => price && price !== '0';\r\n\r\n/**\r\n * Calculate the position based on an index.\r\n * @param index - is a variable that represents the index of the card in the SRP\r\n */\r\nconst getPosition = (index) => index ? Number(index) + 1 : 0;\r\n\r\nconst getPaidCommunityCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.priceLow,\r\n max_price: dataset.priceHigh,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_status: dataset.marketingStatus || defaultMarketingStatus,\r\n community_id: dataset.communityId,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.priceLow) || isPriced(dataset.priceHigh) ? 'True' : 'False',\r\n is_paid: 'True',\r\n zip_code: dataset.zip,\r\n builder_id: dataset.builderId,\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getBasicCommunityCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.priceLow,\r\n max_price: dataset.priceHigh,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_status: dataset.marketingStatus || defaultMarketingStatus,\r\n community_id: dataset.communityId,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.priceLow) || isPriced(dataset.priceHigh) ? 'True' : 'False',\r\n is_paid: 'False',\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getPaidPlanCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.price,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_id: dataset.communityId,\r\n plan_id: dataset.planId,\r\n home_status: dataset.homeStatus,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.price) ? 'True' : 'False',\r\n is_paid: 'True',\r\n is_spec: 'False',\r\n is_plan: 'True',\r\n zip_code: dataset.zip,\r\n builder_id: dataset.builderId,\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getPaidSpecCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.price,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_id: dataset.communityId,\r\n spec_id: dataset.specId,\r\n home_status: dataset.homeStatus,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.price) ? 'True' : 'False',\r\n is_paid: 'True',\r\n is_spec: 'True',\r\n is_plan: 'False',\r\n zip_code: dataset.zip,\r\n builder_id: dataset.builderId,\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getBasicPlanCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.price,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_id: dataset.communityId,\r\n plan_id: dataset.planId,\r\n home_status: dataset.homeStatus,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.price) ? 'True' : 'False',\r\n is_paid: 'False',\r\n is_spec: 'False',\r\n is_plan: 'True',\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getBasicSpecCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.price,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n community_name: dataset.communityName,\r\n community_id: dataset.communityId,\r\n spec_id: dataset.specId,\r\n home_status: dataset.homeStatus,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.price) ? 'True' : 'False',\r\n is_paid: 'False',\r\n is_spec: 'True',\r\n is_plan: 'False',\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst getBasicListingCardProperties = (dataset) => ({\r\n trustbuilder_reviews: dataset.hasBuilderReviews,\r\n min_price: dataset.price,\r\n market_id: dataset.marketId,\r\n market_name: `${dataset.marketName}, ${dataset.stateAbbreviation}`,\r\n market_session: getMarketSession(dataset.marketId, dataset.marketName, dataset.stateAbbreviation),\r\n location: getLocation(dataset.city, dataset.stateName),\r\n listing_id: dataset.id,\r\n position: getPosition(dataset.index),\r\n price_reduction: dataset.priceReductionLabel,\r\n is_limited_availability: dataset.hasLimitedInformation,\r\n is_priced: isPriced(dataset.price) ? 'True' : 'False',\r\n is_paid: 'False',\r\n builder_name: dataset.brandName,\r\n is_spotlight: !!dataset.isFeaturedListing,\r\n});\r\n\r\nconst isNoResultsPage = () => !!listViewSection.querySelector('[data-no-result=\"true\"]');\r\n\r\nconst getClickTargetText = (isMapCard = false) => {\r\n const srpClickTargetText = isMapCard ? 'SRP Map Card' : 'SRP Card';\r\n return isNoResultsPage() ? 'Zero Results Card' : srpClickTargetText;\r\n}\r\n\r\nconst triggerNoResultImpressionEvent = () =>\r\n store.dispatch(googleAnalytics4Event({ eventName: 'zero_results', customProperties: {} }));\r\n\r\n/**\r\n * Observable checking the changes in the listing counts selector,\r\n * checks if the ajax request is succes and the gets the counts value.\r\n */\r\nconst countsChange$ = store$.pipe(\r\n map(selectFetchCountsStatusAndsCounts),\r\n distinctUntilKeyChanged('resultCountsStatus'),\r\n filter((counts) => counts.resultCountsStatus !== LoadingStatus.Loading),\r\n filter((counts) => counts.listingCounts === 0));\r\n\r\ncountsChange$.subscribe(triggerNoResultImpressionEvent);\r\n\r\nconst noResultsListingLinkClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => ({\r\n clickTarget: clickEvent.target,\r\n })),\r\n filter(isNoResultsPage),\r\n filter(({ clickTarget }) => clickTarget.closest(noResultsListingLink)),\r\n map(({ clickTarget }) => clickTarget)\r\n);\r\n\r\nconst triggerNoResultsListingLink = (element) => {\r\n const anchorElement = element.closest(noResultsListingLink);\r\n const anchorLink = anchorElement?.href;\r\n const anchorText = anchorElement?.text;\r\n\r\n const customProperties = {\r\n click_target: anchorText,\r\n destination: anchorLink,\r\n is_zero_results: true,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'site_links', customProperties }));\r\n}\r\n\r\nnoResultsListingLinkClickedCard$.subscribe(triggerNoResultsListingLink);\r\n\r\nconst noResultsClearFilterButtonClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => ({\r\n clickTarget: clickEvent.target,\r\n })),\r\n filter(isNoResultsPage),\r\n filter(({ clickTarget }) => clickTarget.closest(noResultsClearButton)),\r\n filter(({ clickTarget }) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter(({ clickTarget }) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n map(({ clickTarget }) => clickTarget)\r\n);\r\n\r\nconst triggerNoResultsClearFiltersButton = (element) => {\r\n const cardElement = element.closest(noResultsClearButton);\r\n const anchorText = cardElement?.text;\r\n\r\n const customProperties = {\r\n click_target: anchorText,\r\n filter_name: 'Advanced Search',\r\n is_zero_results: true,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n}\r\n\r\nnoResultsClearFilterButtonClickedCard$.subscribe(triggerNoResultsClearFiltersButton);\r\n\r\nconst paidCommunityClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => ({\r\n clickTarget: clickEvent.target,\r\n })),\r\n filter(({ clickTarget }) => clickTarget.closest(paidCommunityCardSelector)),\r\n filter(({ clickTarget }) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter(({ clickTarget }) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n map(({ clickTarget }) => clickTarget)\r\n);\r\n\r\nconst triggerCommunityCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidCommunityCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getPaidCommunityCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\npaidCommunityClickedCard$.subscribe(triggerCommunityCardClickEvent);\r\n\r\nconst basicCommunityClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => clickEvent.target),\r\n filter((clickTarget) => clickTarget.closest(basicCommunityCardSelector)),\r\n filter((clickTarget) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter((clickTarget) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n);\r\n\r\nconst triggerBasicCommunityCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicCommunityCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n \r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getBasicCommunityCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\nbasicCommunityClickedCard$.subscribe(triggerBasicCommunityCardClickEvent);\r\n\r\nconst paidPlanClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => ({\r\n clickTarget: clickEvent.target,\r\n })),\r\n filter(({ clickTarget }) => clickTarget.closest(paidPlanCardSelector)),\r\n filter(({ clickTarget }) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter(({ clickTarget }) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n map(({ clickTarget }) => clickTarget)\r\n);\r\n\r\nconst triggerPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getPaidPlanCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\npaidPlanClickedCard$.subscribe(triggerPlanCardClickEvent);\r\n\r\nconst basicPlanClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => clickEvent.target),\r\n filter((clickTarget) => clickTarget.closest(basicPlanCardSelector)),\r\n filter((clickTarget) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter((clickTarget) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n);\r\n\r\nconst triggerBasicPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n \r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getBasicPlanCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\nbasicPlanClickedCard$.subscribe(triggerBasicPlanCardClickEvent);\r\n\r\nconst basicListingClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => clickEvent.target),\r\n filter((clickTarget) => clickTarget.closest(basicListingCardSelector)),\r\n filter((clickTarget) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter((clickTarget) => !clickTarget.closest(cardFavoriteButtonSelector))\r\n);\r\n\r\nconst triggerBasicListingCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicListingCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getBasicListingCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\nbasicListingClickedCard$.subscribe(triggerBasicListingCardClickEvent);\r\n\r\nconst paidSpecClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => ({\r\n clickTarget: clickEvent.target,\r\n })),\r\n filter(({ clickTarget }) => clickTarget.closest(paidSpecCardSelector)),\r\n filter(({ clickTarget }) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter(({ clickTarget }) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n map(({ clickTarget }) => clickTarget)\r\n);\r\n\r\nconst triggerSpecCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidSpecCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getPaidSpecCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\npaidSpecClickedCard$.subscribe(triggerSpecCardClickEvent);\r\n\r\nconst basicSpecClickedCard$ = listViewSectionClicks$.pipe(\r\n map((clickEvent) => clickEvent.target),\r\n filter((clickTarget) => clickTarget.closest(basicSpecCardSelector)),\r\n filter((clickTarget) => !clickTarget.dataset?.leadGeneratorOpener),\r\n filter((clickTarget) => !clickTarget.closest(cardFavoriteButtonSelector)),\r\n);\r\n\r\nconst triggerBasicSpecCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicSpecCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = areaClickedPerCardElement[elementName] || areaClickedPerCardElement.default;\r\n const anchorLink = cardElement.querySelector('[data-url]')?.dataset.url;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: cardAreaClicked,\r\n destination: anchorLink,\r\n is_zero_results: isNoResults,\r\n ...getBasicSpecCardProperties(cardDataset),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\nbasicSpecClickedCard$.subscribe(triggerBasicSpecCardClickEvent);\r\n\r\n/* Paid Community Favorited: User not logged in */\r\nconst triggerCommunityFavoritedEvent = (payload) => {\r\n\r\n const itemId = payload?.listingInformation?.id;\r\n const cardElement = document.querySelector(`[data-id=\"${itemId}\"]`);\r\n const cardDataset = cardElement?.dataset ?? {};\r\n const isNoResults = isNoResultsPage();\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const getCommunityCardProperties = cardDataset.isBasic === 'true'\r\n ? getBasicCommunityCardProperties(cardDataset) : getPaidCommunityCardProperties(cardDataset);\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 4,\r\n is_zero_results: isNoResults,\r\n ...getCommunityCardProperties,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'saved', customProperties }));\r\n};\r\n\r\nonPendingFavoritesChanged$.pipe(\r\n filter((favoritedInformation) => favoritedInformation?.type === FavoriteType.Community.toString())\r\n).subscribe(triggerCommunityFavoritedEvent);\r\n\r\n/* Paid Plan Favorited: User not logged in */\r\nconst triggerPlanFavoritedEvent = (payload) => {\r\n\r\n const itemId = payload?.listingInformation?.id;\r\n const cardElement = document.querySelector(`[data-id=\"${itemId}\"]`);\r\n const cardDataset = cardElement?.dataset ?? {};\r\n const isNoResults = isNoResultsPage();\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const getPlanCardProperties = cardDataset.isBasic === 'true'\r\n ? getBasicPlanCardProperties(cardDataset) : getPaidPlanCardProperties(cardDataset);\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 4,\r\n is_zero_results: isNoResults,\r\n ...getPlanCardProperties,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'saved', customProperties }));\r\n\r\n};\r\n\r\nonPendingFavoritesChanged$.pipe(\r\n filter((favoritedInformation) => favoritedInformation?.type === FavoriteType.Plan.toString())\r\n).subscribe(triggerPlanFavoritedEvent);\r\n\r\n/* Paid Spec Favorited: User not logged in */\r\nconst triggerSpecFavoritedEvent = (payload) => {\r\n\r\n const itemId = payload?.listingInformation?.id;\r\n const cardElement = document.querySelector(`[data-id=\"${itemId}\"]`);\r\n const cardDataset = cardElement?.dataset ?? {};\r\n const isNoResults = isNoResultsPage();\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const getSpecCardProperties = cardDataset.isBasic === 'true'\r\n ? getBasicSpecCardProperties(cardDataset) : getPaidSpecCardProperties(cardDataset);\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 4,\r\n is_zero_results: isNoResults,\r\n ...getSpecCardProperties,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'saved', customProperties }));\r\n\r\n};\r\n\r\nonPendingFavoritesChanged$.pipe(\r\n filter((favoritedInformation) => favoritedInformation?.type === FavoriteType.Spec.toString()))\r\n .subscribe(triggerSpecFavoritedEvent);\r\n\r\nfunction triggerRecommendationLinkDetailEvent(item) {\r\n const community = JSON.parse(item.querySelector('[data-recommended-checkbox]').value);\r\n const customProperties = {\r\n click_target: getClickTargetText(),\r\n click_target1: 'Comm Link Clicked',\r\n market_id: community.MarketId,\r\n market_name: community.MarketName,\r\n community_id: community.CommunityId,\r\n community_name: community.CommunityName,\r\n community_status: community.MarketingStatusLabel || defaultMarketingStatus,\r\n min_price: community.PriceLow,\r\n max_price: community.PriceHigh,\r\n market_session: getMarketSession(community.MarketId, community.MarketName, community.StateAbbreviation),\r\n location: getLocation(community.City, community.StateName),\r\n trustbuilder_reviews: community.HasBuilderReviews,\r\n is_limited_availability: community.HasLimitedInformation,\r\n is_priced: isPriced(community.PriceLow) || isPriced(community.PriceHigh) ? 'True' : 'False',\r\n is_paid: 'True',\r\n is_zero_results: isNoResultsPage(),\r\n is_spotlight: !!item.dataset.isFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n}\r\n\r\nrecommendationLinkDetailClick$.subscribe(triggerRecommendationLinkDetailEvent);\r\n\r\n// ! Community Lead Button Click Event //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidCommunityAndPaidLocationSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerCommunityPaidLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerCommunityPaidLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidCommunityAndPaidLocationSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n \r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidCommunityCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\npaidCommunityLeadButtonClicked$.subscribe(triggerCommunityPaidLeadButtonClickEvent);\r\n\r\n\r\nconst paidMasterPlanCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidMasterPlanCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerMasterPlanCommunityPaidLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerMasterPlanCommunityPaidLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidMasterPlanCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n ...getPaidCommunityCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\npaidMasterPlanCommunityLeadButtonClicked$.subscribe(triggerMasterPlanCommunityPaidLeadButtonClickEvent);\r\n\r\nconst triggerBasicCommunityLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicCommunityAndBasicLocationSelector);\r\n const cardDataset = cardElement.dataset;\r\n const buttonDataset = element.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getBasicCommunityCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\nconst basicCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicCommunityAndBasicLocationSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nbasicCommunityLeadButtonClicked$.subscribe(triggerBasicCommunityLeadButtonClickEvent);\r\n\r\n// ! Home (Spec/Plan) Lead Button Click Event //\r\n\r\n/**\r\n * The triggerPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerPaidPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidPlanSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidPlanCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidPlanSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidPlanLeadButtonClicked$.subscribe(triggerPaidPlanLeadButtonClickEvent);\r\n\r\n/**\r\n * The triggerPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the GA4 event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerPaidSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidSpecSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidSpecCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidSpecSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\npaidSpecLeadButtonClicked$.subscribe(triggerPaidSpecLeadButtonClickEvent);\r\n\r\nconst triggerBasicPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicPlanSelector);\r\n const cardDataset = cardElement.dataset;\r\n const buttonDataset = element.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getBasicPlanCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\nconst basicPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicPlanSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nbasicPlanLeadButtonClicked$.subscribe(triggerBasicPlanLeadButtonClickEvent);\r\n\r\nconst triggerBasicSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicSpecSelector);\r\n const cardDataset = cardElement.dataset;\r\n const buttonDataset = element.dataset;\r\n const isNoResults = isNoResultsPage();\r\n \r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getBasicSpecCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\nconst basicSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicSpecSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nbasicSpecLeadButtonClicked$.subscribe(triggerBasicSpecLeadButtonClickEvent);\r\n\r\nconst triggerBasicListingLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicListingCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const buttonDataset = element.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: buttonDataset.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getBasicListingCardProperties(cardDataset),\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n};\r\n\r\nconst basicListingLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicListingCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nbasicListingLeadButtonClicked$.subscribe(triggerBasicListingLeadButtonClickEvent);\r\n\r\n// #endregion List View Section\r\n\r\n// #region Brochure Modal\r\n/**\r\n * ! Brochure Modal Section\r\n * All events related elements located in brochure modal should be placed in this region\r\n */\r\n\r\nconst detailAnchorClicked$ = fromEvent(document.body, 'detailAnchorClicked').pipe(map((event) => event.detail));\r\n\r\n/**\r\n* trackRealtorQuestionAnswerEvent: Tracks the sorted event for the realtor dropdown.\r\n*/\r\nfunction getRealtorQuestionAnswerText() {\r\n const realtorSelect = document.querySelector('[name=\"realtorQuestion\"]');\r\n let realtorQuestionAnswer = '';\r\n if (realtorSelect && realtorSelect.selectedIndex > 0) {\r\n realtorQuestionAnswer = realtorSelect.options[realtorSelect.selectedIndex].text;\r\n }\r\n return realtorQuestionAnswer;\r\n}\r\n\r\n/**\r\n * triggerPaidCommunityModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Free Brochure\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerPaidCommunityModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidCommunityCardProperties(modalInformation.listingInformation),\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'generate_lead', customProperties }));\r\n}\r\n\r\npaidCommunityModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\npaidMasterPlanCommunityModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\npaidManufacturedLocationModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\npaidAskAQuestionLocationModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\n\r\n/**\r\n * Handles the event when a paid community modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handlePaidCommunityModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getPaidCommunityCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Handles the event when a basic community modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handleBasicCommunityModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getBasicCommunityCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a paid community modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Community().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic !== 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedPaid().getName()),\r\n).subscribe(handlePaidCommunityModalFormClosed)\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a basic community modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Community().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic === 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedBasic().getName()),\r\n).subscribe(handleBasicCommunityModalFormClosed)\r\n\r\n/**\r\n * Handles the event when a paid spec modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handlePaidSpecModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getPaidSpecCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Handles the event when a basic spec modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handleBasicSpecModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getBasicSpecCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a paid spec modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Spec().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic !== 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedPaid().getName()),\r\n).subscribe(handlePaidSpecModalFormClosed)\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a basic spec modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Spec().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic === 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedBasic().getName()),\r\n).subscribe(handleBasicSpecModalFormClosed)\r\n\r\n/**\r\n * Handles the event when a paid plan modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handlePaidPlanModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getPaidPlanCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Handles the event when a basic plan modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handleBasicPlanModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getBasicPlanCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a paid plan modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Plan().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic !== 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedPaid().getName()),\r\n).subscribe(handlePaidPlanModalFormClosed)\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a basic plan modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.Plan().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic === 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedBasic().getName()),\r\n).subscribe(handleBasicPlanModalFormClosed)\r\n\r\n/**\r\n * Handles the event when a basic community modal form is closed.\r\n * @param {Object} modalInformation - Information about the modal that was closed.\r\n */\r\nfunction handleBasicListingModalFormClosed(event) {\r\n const { modalInformation } = event.detail;\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n is_zero_results: isNoResults,\r\n click_target: clickTarget,\r\n ...getBasicListingCardProperties(modalInformation.listingInformation),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `modalCloseButtonClicked$` observable and handles the closing of a paid community modal form.\r\n * \r\n */\r\nmodalCloseButtonClicked$.pipe(\r\n filter((event) => event.detail?.modalInformation?.type === HousingProductType.BasicListing().getName()),\r\n filter((event) => event.detail?.modalInformation?.listingInformation?.isBasic === 'true'),\r\n filter((event) => event.detail?.modalInformation?.name !== RecommendedType.RecommendedBasic().getName()),\r\n).subscribe(handleBasicListingModalFormClosed)\r\n\r\n/**\r\n * triggerBasicCommunityModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following form:\r\n * - Learn More\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\n\r\nfunction triggerBasicCommunityModalSubmitted(modalInformation) {\r\n const cardElement = document.querySelector(`[data-community-id=\"${modalInformation.id}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getBasicCommunityCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_lead_submitted', customProperties }));\r\n}\r\n\r\nbasicCommunityModalSubmission$.subscribe(triggerBasicCommunityModalSubmitted);\r\n\r\n/**\r\n * Triggers the events for the recommended basic communities that were selected.\r\n * @param {Object} modalInformation Information related to the modal.\r\n */\r\nfunction triggerRecommendedBasicCommunitySubmittedEvents(modalInformation) {\r\n const { selectedRecommendedCommunities, listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n selectedRecommendedCommunities.forEach((community) => {\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n market_id: community.MarketId,\r\n market_name: community.MarketName,\r\n community_id: community.CommunityId,\r\n community_name: community.CommunityName,\r\n community_status: community.MarketingStatusLabel || defaultMarketingStatus,\r\n min_price: community.PriceLow,\r\n max_price: community.PriceHigh,\r\n market_session: getMarketSession(community.MarketId, community.MarketName, community.StateAbbreviation),\r\n location: getLocation(community.City, community.StateName),\r\n trustbuilder_reviews: community.HasBuilderReviews,\r\n is_limited_availability: community.HasLimitedInformation,\r\n is_priced: isPriced(community.PriceLow) || isPriced(community.PriceHigh) ? 'True' : 'False',\r\n is_paid: 'False',\r\n button_name: 'yes I’m interested',\r\n org_button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_direct_rec_lead', customProperties }));\r\n });\r\n}\r\n\r\nrecommendedCommunitiesSubmittedBasic$.subscribe(triggerRecommendedBasicCommunitySubmittedEvents);\r\n\r\n/**\r\n * Triggers the events for the recommended communities that were selected.\r\n * @param {Object} modalInformation Information related to the modal.\r\n */\r\nfunction triggerRecommendedCommunitySubmittedEvents(modalInformation) {\r\n const { selectedRecommendedCommunities } = modalInformation;\r\n selectedRecommendedCommunities.forEach((community) => {\r\n const customProperties = {\r\n click_target: getClickTargetText(modalInformation.summaryCardCta != null),\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n market_id: community.MarketId,\r\n market_name: community.MarketName,\r\n community_id: community.CommunityId,\r\n community_name: community.CommunityName,\r\n community_status: community.MarketingStatusLabel || defaultMarketingStatus,\r\n min_price: community.PriceLow,\r\n max_price: community.PriceHigh,\r\n market_session: getMarketSession(community.MarketId, community.MarketName, community.StateAbbreviation),\r\n location: getLocation(community.City, community.StateName),\r\n trustbuilder_reviews: community.HasBuilderReviews,\r\n is_limited_availability: community.HasLimitedInformation,\r\n is_priced: isPriced(community.PriceLow) || isPriced(community.PriceHigh) ? 'True' : 'False',\r\n is_paid: 'True',\r\n button_name: 'Get More Info',\r\n org_button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResultsPage(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'direct_rec_lead', customProperties }));\r\n });\r\n}\r\n\r\nrecommendedCommunitiesSubmitted$.subscribe(triggerRecommendedCommunitySubmittedEvents);\r\n\r\n/**\r\n * triggerPaidHomeModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Free Brochure\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerPaidPlanModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidPlanCardProperties(listingInformation),\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'generate_lead', customProperties }));\r\n}\r\n\r\npaidHomeModalSubmission$\r\n .pipe(filter((modalInformation) => modalInformation.type === 'plan'),\r\n filter((modalInformation) => modalInformation.variation !== 'basic'))\r\n .subscribe(triggerPaidPlanModalSubmitted);\r\npaidManufacturedPlanModalSubmission$.subscribe(triggerPaidPlanModalSubmitted);\r\npaidAskAQuestionPlanModalSubmission$.subscribe(triggerPaidPlanModalSubmitted);\r\n\r\n/**\r\n * triggerBasicHomeModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicHomeModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const cardElement = document.querySelector(`[data-plan-id=\"${listingInformation.planId}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidPlanCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_lead_submitted', customProperties }));\r\n}\r\n\r\nbasicPlanModalSubmission$\r\n .pipe(filter((modalInformation) => modalInformation.type === 'plan'),\r\n filter((modalInformation) => modalInformation.variation === 'basic'))\r\n .subscribe(triggerBasicHomeModalSubmitted);\r\n\r\n/**\r\n * triggerBasicSpecModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicSpecModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const cardElement = document.querySelector(`[data-spec-id=\"${listingInformation.specId}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidSpecCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_lead_submitted', customProperties }));\r\n}\r\n\r\nbasicSpecModalSubmission$\r\n .pipe(filter((modalInformation) => modalInformation.type === 'spec'),\r\n filter((modalInformation) => modalInformation.variation === 'basic'))\r\n .subscribe(triggerBasicSpecModalSubmitted);\r\n\r\n/**\r\n * triggerBasicListingModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicListingModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const cardElement = document.querySelector(`[data-id=\"${listingInformation.id}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...getPaidSpecCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'basic_lead_submitted', customProperties }));\r\n}\r\n\r\nbasicListingModalSubmission$\r\n .pipe(filter((modalInformation) => modalInformation.type === 'basicListing'),\r\n filter((modalInformation) => modalInformation.variation === 'basic'))\r\n .subscribe(triggerBasicListingModalSubmitted);\r\n\r\n/**\r\n * triggerPaidPlanModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Free Brochure\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerPaidSpecModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResultsPage(),\r\n ...getPaidSpecCardProperties(listingInformation),\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'generate_lead', customProperties }));\r\n}\r\n\r\npaidHomeModalSubmission$\r\n .pipe(filter((modalInformation) => modalInformation.type === 'spec'),\r\n filter((modalInformation) => modalInformation.variation !== 'basic'))\r\n .subscribe(triggerPaidSpecModalSubmitted);\r\npaidManufacturedSpecModalSubmission$.subscribe(triggerPaidSpecModalSubmitted);\r\npaidAskAQuestionSpecModalSubmission$.subscribe(triggerPaidSpecModalSubmitted);\r\n\r\n// Recommended communities\r\n/**\r\n * Triggers a Google Analytics 4 event when the Skip button is clicked in the More Recommended Communities modal. \r\n */\r\nconst skipModalRecommendedCommunitiesClick$ = fromEvent(document.body, 'click').pipe(\r\n filter((event) => event.target.closest('[data-skip-recommendations]')),\r\n);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the close button is clicked in the More Recommended Communities modal. \r\n */\r\nconst closeModalRecommendedCommunitiesClick$ = fromEvent(document.body, 'click').pipe(\r\n filter((event) => event.target.closest('[data-close-recommended]')),\r\n);\r\n\r\n/**\r\n * getCustomPropertiesByType: Determines and returns custom properties based on\r\n * the product type (type) and whether it is basic (basic) or not.\r\n * @param {object} type Housing Product Type.\r\n * @param {object} data Information related to modal and the card.\r\n * @returns Card information according to its type.\r\n */\r\nfunction getCustomPropertiesByType(type, data) {\r\n const isBasic = data.isBasic === 'true';\r\n if (type === HousingProductType.Community().getName() && isBasic) {\r\n return getBasicCommunityCardProperties(data);\r\n }\r\n if (type === HousingProductType.Community().getName() && !isBasic) {\r\n return getPaidCommunityCardProperties(data);\r\n }\r\n if (type === HousingProductType.Spec().getName() && isBasic) {\r\n return getBasicSpecCardProperties(data);\r\n }\r\n if (type === HousingProductType.Spec().getName() && !isBasic) {\r\n return getPaidSpecCardProperties(data);\r\n }\r\n if (type === HousingProductType.Plan().getName() && isBasic) {\r\n return getBasicPlanCardProperties(data);\r\n }\r\n if (type === HousingProductType.Plan().getName() && !isBasic) {\r\n return getPaidPlanCardProperties(data);\r\n }\r\n if (type === HousingProductType.BasicListing().getName()) {\r\n return getBasicListingCardProperties(data);\r\n }\r\n return {}\r\n}\r\n/**\r\n * handleModalRecommendedCommunitiesFormSkip: Triggers the event when we press the Skip button in the \r\n * \"More recommended communities\" modal.\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction handleModalRecommendedCommunitiesFormSkip(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n const customPropertiesByType = getCustomPropertiesByType(modalInformation.type, listingInformation);\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...customPropertiesByType,\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'direc_form_skip', customProperties }));\r\n}\r\n\r\n/**\r\n * When the Skip button is clicked on the More Recommended Communities modal,\r\n * we subscribe to the 'recommendedCommunitiesShow$' observer to get the information from the modal.\r\n */\r\nskipModalRecommendedCommunitiesClick$.pipe(\r\n withLatestFrom(recommendedCommunitiesShow$),\r\n map(([, modalInfo]) => modalInfo),\r\n).subscribe(handleModalRecommendedCommunitiesFormSkip);\r\n\r\n/**\r\n * handleModalRecommendedCommunitiesShow: Triggers the event when we press the Skip button in the \r\n * \"More recommended communities\" modal.\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction handleModalRecommendedCommunitiesShow(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customPropertiesByType = getCustomPropertiesByType(modalInformation.type, listingInformation);\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...customPropertiesByType,\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'direc_section_view', customProperties }));\r\n}\r\n\r\n/**\r\n * When the More Recommended Communities modal is displayed,\r\n * we subscribe to the 'recommendedCommunitiesShow$' observer to get the information from the modal.\r\n */\r\nrecommendedCommunitiesShow$.subscribe(handleModalRecommendedCommunitiesShow);\r\n\r\n/**\r\n * handleModalRecommendedCommunitiesClose: Triggers the event when we press the close button in the \r\n * \"More recommended communities\" modal.\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction handleModalRecommendedCommunitiesClose(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: listingInformation?.clickTarget,\r\n });\r\n\r\n const customPropertiesByType = getCustomPropertiesByType(modalInformation.type, listingInformation);\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 30,\r\n button_name: modalInformation.buttonAction,\r\n is_zero_results: isNoResults,\r\n ...customPropertiesByType,\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'direc_form_close', customProperties }));\r\n}\r\n\r\n/**\r\n * When we click the close button on the recommended communities modal,\r\n * we subscribe to the `recommendedCommunitiesShow$` observer to get the modal information.\r\n */\r\ncloseModalRecommendedCommunitiesClick$.pipe(\r\n withLatestFrom(recommendedCommunitiesShow$),\r\n map(([, modalInfo]) => modalInfo),\r\n).subscribe(handleModalRecommendedCommunitiesClose);\r\n\r\n// ! Thank you modal more detail Button Click Event //\r\nconst triggerCommunityPaidDetailAnchorClickEvent = (id) => {\r\n const cardElement = document.querySelector(`[data-community-id=\"${id}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: 'Card clicked',\r\n is_zero_results: isNoResults,\r\n ...getPaidCommunityCardProperties(cardDataset), \r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\ndetailAnchorClicked$\r\n .pipe(\r\n filter((information) => information.listingType === 'community'),\r\n map((information) => information.listingId)\r\n )\r\n .subscribe(triggerCommunityPaidDetailAnchorClickEvent);\r\n\r\nconst triggerPlanPaidDetailAnchorClickEvent = (id) => {\r\n const cardElement = document.querySelector(`[data-plan-id=\"${id}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: 'Card clicked',\r\n is_zero_results: isNoResults,\r\n ...getPaidPlanCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\ndetailAnchorClicked$\r\n .pipe(\r\n filter((information) => information.listingType === 'plan'),\r\n map((information) => information.listingId)\r\n )\r\n .subscribe(triggerPlanPaidDetailAnchorClickEvent);\r\n\r\nconst triggerSpecPaidDetailAnchorClickEvent = (id) => {\r\n const cardElement = document.querySelector(`[data-spec-id=\"${id}\"]`);\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: cardDataset.clickTarget,\r\n });\r\n\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n click_target1: 'Card clicked',\r\n is_zero_results: isNoResults,\r\n ...getPaidSpecCardProperties(cardDataset),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'card_clicked', customProperties }));\r\n};\r\n\r\ndetailAnchorClicked$\r\n .pipe(\r\n filter((information) => information.listingType === 'spec'),\r\n map((information) => information.listingId)\r\n )\r\n .subscribe(triggerSpecPaidDetailAnchorClickEvent);\r\n\r\n// #endregion Brochure Modal\r\n\r\n// #region Layout\r\n\r\nconst footerLinks = document.querySelector('[data-footer-links]');\r\nconst footerLinksClicks$ = fromEvent(footerLinks, 'click');\r\n\r\n/** According to the clicked event with this dictionary,\r\n * we can obtain the name of the click target and the name of the event.\r\n * Example: I click footer_55_plus, its click_target: 'FT - New 55+ Communities' and eventName: 'buyingguide_events'.\r\n * */\r\nconst clickedLinkFooter = {\r\n footer_55_plus: { name: 'FT - New 55+ Communities', eventName: 'buyingguide_events' },\r\n footer_condos_townhouses: { name: 'FT - Search New Condos', eventName: 'site_links' },\r\n footer_custom_homes_center: { name: 'FT - Custom home buyers', eventName: 'buyingguide_events' },\r\n footer_first_time_homebuyers: { name: 'FT - New First Time Buyers Communities', eventName: 'buyingguide_events' },\r\n footer_luxury_homes: { name: 'FT - Search Luxury Homes', eventName: 'site_links' },\r\n footer_modular_homes: { name: 'FT - Search Modular Homes', eventName: 'site_links' },\r\n footer_learning_center: { name: 'FT - Learning Center', eventName: 'site_links' },\r\n footer_ratings_and_reviews: { name: 'FT - TrustBuilder Ratings Review', eventName: 'site_links' },\r\n footer_real_estate_professionals: { name: 'FT - New Home Source Professional', eventName: 'outbound_links' },\r\n footer_livabl: { name: 'FT - Livabl', eventName: 'outbound_links' },\r\n footer_houseplans: { name: 'FT - Houseplans', eventName: 'outbound_links' },\r\n footer_casas_nuevas: { name: 'FT - Casas Nuevas', eventName: 'outbound_links' },\r\n footer_start_fresh_buy_new: { name: 'FT-StartFreshBuyNew', eventName: 'outbound_links' },\r\n footer_about_us: { name: 'FT - About us', eventName: 'site_links' },\r\n footer_contact_us: { name: 'FT - Contact us', eventName: 'site_links' },\r\n footer_list_your_homes: { name: 'FT - List Your Homes', eventName: 'outbound_links' },\r\n footer_unsubscribe: { name: 'FT - Unsubscribe', eventName: 'site_links' },\r\n footer_accessibility: { name: 'FT - Accessibility statement', eventName: 'site_links' },\r\n footer_terms_of_use: { name: 'FT - Terms of use', eventName: 'site_links' },\r\n footer_privacy_policy: { name: 'FT - Privacy policy', eventName: 'site_links' },\r\n footer_site_help: { name: 'FT - Site Help', eventName: 'site_links' },\r\n footer_do_not_sell_my_info: { name: 'FT - Do Not Sell My Info', eventName: 'site_links' },\r\n footer_facebook_link: { name: 'Facebook', eventName: 'outbound_links' },\r\n footer_pinterest_link: { name: 'Pinterest', eventName: 'outbound_links' },\r\n footer_twitter_link: { name: 'Twitter', eventName: 'outbound_links' },\r\n footer_youtube_link: { name: 'YouTube', eventName: 'outbound_links' },\r\n footer_instagram_link: { name: 'Instagram', eventName: 'outbound_links' },\r\n}\r\n\r\nconst footerLinkClicked$ = footerLinksClicks$.pipe(\r\n filter((event) => event.target.closest('[data-footer-link]')),\r\n map((event) => event.target)\r\n);\r\n\r\nconst triggerFooterLinksClickEvent = (element) => {\r\n const elementName = element.dataset.footerLink ?? element?.closest('[data-footer-link]')?.dataset?.footerLink;\r\n const nameLinkClicked = clickedLinkFooter[elementName]?.name;\r\n const eventNameLinkClicked = clickedLinkFooter[elementName]?.eventName;\r\n\r\n const customProperties = {\r\n click_target: nameLinkClicked,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: eventNameLinkClicked, customProperties }));\r\n};\r\n\r\nfooterLinkClicked$.subscribe(triggerFooterLinksClickEvent);\r\n\r\nconst logoHeaderElement = document.querySelector('[data-header-logo]');\r\nconst logoHeaderClick$ = fromEvent(logoHeaderElement, 'click');\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the NewHomeSource header logo is clicked.\r\n */\r\nfunction triggerLogoHeaderClickEvent() {\r\n const customProperties = {\r\n click_target: 'NHS Logo'\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: siteLinksEventName, customProperties }));\r\n}\r\n\r\nlogoHeaderClick$.subscribe(triggerLogoHeaderClickEvent);\r\n\r\nconst metroAreaLinksContainerElement = document.querySelector('[data-find-a-home] [data-metro-links]');\r\nconst metroAreaLinkClick$ = fromEvent(metroAreaLinksContainerElement, 'click');\r\nconst homesByStateLinksContainerElement = document.querySelector('[data-find-a-home] [data-state-links]');\r\nconst homesByStateLinkClick$ = fromEvent(homesByStateLinksContainerElement, 'click');\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event related to a clicked element in Find a Home panel.\r\n * @param clickedElement - Element that was clicked by the user.\r\n * @param sectionName - Represents the name of the section in which the link was clicked.\r\n * It is inside of the Find a Home panel\r\n */\r\nfunction triggerFindAHomeLinkClickEvent(clickedElement, sectionName) {\r\n const customProperties = {\r\n click_target: `Global Header - ${sectionName}`,\r\n search_value: clickedElement.textContent,\r\n destination: clickedElement.href\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: siteLinksEventName, customProperties }));\r\n}\r\n\r\nmetroAreaLinkClick$.pipe(\r\n map((event) => event.target),\r\n filter((element) => element.href)\r\n).subscribe((element) => triggerFindAHomeLinkClickEvent(element, 'Metro Area'));\r\n\r\nhomesByStateLinkClick$.pipe(\r\n map((event) => event.target),\r\n filter((element) => element.href)\r\n).subscribe((element) => triggerFindAHomeLinkClickEvent(element, 'New Home States'));\r\n\r\nconst resourcesContainerElement = document.querySelector('[data-resources]');\r\nconst resourceLinkClick$ = fromEvent(resourcesContainerElement, 'click');\r\nconst advertisingLinkElement = document.querySelector('[data-nav-links] [data-nav-link=\"header_advertise\"]');\r\nconst advertisingLinkClick$ = fromEvent(advertisingLinkElement, 'click');\r\n\r\nconst navLinksEventNames = {\r\n 'header_advertise': outboundLinksEventName,\r\n 'header_reviews': siteLinksEventName,\r\n 'header_learn': siteLinksEventName,\r\n 'header_first_time_homebuyers': buyingGuideEventsName,\r\n 'header_custom_homes_center': buyingGuideEventsName,\r\n 'header_55_plus': buyingGuideEventsName,\r\n 'header_military_buyers': buyingGuideEventsName,\r\n 'header_affordability_calculator': siteLinksEventName,\r\n 'header_home_buying_tools': siteLinksEventName,\r\n 'header_credit_score': siteLinksEventName,\r\n 'header_mortgage_calculator': siteLinksEventName,\r\n 'header_get_preapproved': siteLinksEventName,\r\n 'header_prep_home_for_sale': siteLinksEventName,\r\n 'header_homeowners_insurance': siteLinksEventName,\r\n 'header_get_offers': siteLinksEventName,\r\n 'header_home_buying_tools_landing': siteLinksEventName\r\n};\r\n\r\nconst navLinksNames = {\r\n 'header_advertise': 'Builder Advertising',\r\n 'header_reviews': 'TB Rating',\r\n 'header_learn': 'HLC clicks',\r\n 'header_first_time_homebuyers': 'FTHB clicks',\r\n 'header_custom_homes_center': 'CHB clicks',\r\n 'header_55_plus': '55+ HB clicks',\r\n 'header_military_buyers': 'Military clicks',\r\n 'header_affordability_calculator': 'Af Calc clicks',\r\n 'header_home_buying_tools': 'HC Calc clicks',\r\n 'header_credit_score': 'Cdt Score clicks',\r\n 'header_mortgage_calculator': 'Mtg Calc clicks',\r\n 'header_get_preapproved': 'GP Approved clicks',\r\n 'header_prep_home_for_sale': 'PHF Sale clicks',\r\n 'header_homeowners_insurance': 'Hinsurance clicks',\r\n 'header_get_offers': 'Goffers clicks',\r\n 'header_home_buying_tools_landing': 'HB Tools clicks'\r\n};\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event based on the provided navigation link value.\r\n * @param navLinkValue - Represents the specific navigation link that was clicked in the global header.\r\n */\r\nfunction triggerHeaderLinkClickEvent(navLinkValue) {\r\n const customProperties = {\r\n click_target: `Global Header - ${navLinksNames[navLinkValue]}`\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: navLinksEventNames[navLinkValue], customProperties }));\r\n}\r\n\r\nresourceLinkClick$.pipe(\r\n map((event) => event.target),\r\n filter((element) => element.dataset.navLink && element.href),\r\n map((element) => element.dataset.navLink)\r\n).subscribe(triggerHeaderLinkClickEvent);\r\n\r\nadvertisingLinkClick$.pipe(\r\n map((event) => event.target.dataset.navLink)\r\n).subscribe(triggerHeaderLinkClickEvent);\r\n\r\n\r\nconst signInClickTargetValue = 'Global Header - Sign In';\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when a sign-in form is closed.\r\n */\r\nfunction triggerCloseSignInFormClickEvent() {\r\n const customProperties = {\r\n click_target: signInClickTargetValue\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'form_close', customProperties }));\r\n}\r\n\r\nconst signEventNames = {\r\n 'Sign In': 'login',\r\n 'Sign Up': 'sign-up'\r\n}\r\n\r\n/**\r\n * Triggers the event on sign-in buttons and dispatches a Google Analytics 4 event.\r\n * @param clickedElement - It is the element that was clicked by the user, typically a button or a link that\r\n * triggers the sign-in form submission.\r\n * This event is triggered by clicks and not when the sign transaction is done.\r\n */\r\nfunction triggerSignInFormClickEvent(clickedElement) {\r\n const formContainer = clickedElement.closest('.auth0-lock-widget-container')\r\n const signOptionSelected = formContainer.querySelector('.auth0-lock-tabs .auth0-lock-tabs-current').textContent;\r\n\r\n const customProperties = {\r\n click_target: signInClickTargetValue,\r\n method: clickedElement.dataset.provider || 'Auth0',\r\n button_name: clickedElement.textContent,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: signEventNames[signOptionSelected], customProperties }));\r\n}\r\n\r\npageWindowClick$.pipe(\r\n // We cannot add data attributes on the View as this form is external to NewHomeSource repository.\r\n map((event) => event.target.closest('.auth0-lock-close-button')),\r\n filter(Boolean)\r\n).subscribe(triggerCloseSignInFormClickEvent);\r\n\r\npageWindowClick$.pipe(\r\n // We cannot add data attributes on the View as this form is external to NewHomeSource repository.\r\n map((event) => event.target.closest('.auth0-lock-social-button') || event.target.closest('.auth0-lock-submit')),\r\n filter(Boolean)\r\n).subscribe(triggerSignInFormClickEvent)\r\n\r\n// #endregion Layout\r\n\r\n// #region Map\r\n\r\nconst mapContainerElement = document.querySelector('[data-map]');\r\nconst mapClick$ = fromEvent(mapContainerElement, 'click');\r\n\r\nconst mapToggleButtonElement = document.getElementById('btn-map-view');\r\nconst mapToggleButtonClick$ = fromEvent(mapToggleButtonElement, 'click');\r\n\r\n// As the state element value changes before we can trigger the event, so we have\r\n// to manage as it already changed. In other words, if we get a new click and the current state\r\n// is map, it means before the button were on list as state, so the click target value is Mobile Map View.\r\nconst toggleClickTargetValues = {\r\n list: 'Mobile Map View',\r\n map: 'Mobile List View'\r\n}\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event related to the map toggle button click.\r\n * @param elementState - Current state of the toggle button. It represents the new view on screen.\r\n */\r\nconst triggerMapToggleButtonClickEvent = (elementState) => {\r\n const customProperties = {\r\n click_target: toggleClickTargetValues[elementState],\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_events', customProperties }));\r\n}\r\n\r\nmapToggleButtonClick$.pipe(\r\n map((event) => event.target),\r\n map((element) => element.closest('#btn-map-view')),\r\n map((element) => element.dataset.state),\r\n filter(Boolean),\r\n).subscribe(triggerMapToggleButtonClickEvent);\r\n\r\n/**\r\n * Triggers the Google Analytics 4 event related to a map zoom button click.\r\n * @param zoomButton - Element that is used to trigger a zoom action by a click on the map.\r\n */\r\nconst triggerZoomClickEvent = (zoomButton) => {\r\n const customProperties = {\r\n click_target: `${zoomButton.title} map`,\r\n click_target1: 'On Click',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_events', customProperties }));\r\n}\r\n\r\nmapClick$.pipe(\r\n map((event) => event.target),\r\n filter((element) => element.closest('[data-control-width][data-control-height]')),\r\n filter((element) => element.title)\r\n).subscribe(triggerZoomClickEvent);\r\n\r\nconst mapContainerTouchstart$ = fromEvent(mapContainerElement, 'touchstart');\r\nconst mapContainerTouchend$ = fromEvent(mapContainerElement, 'touchend');\r\nconst mapZoomChange$ = fromEvent(mapContainerElement, 'zoomChanged');\r\n\r\nconst mapPinchStart$ = mapContainerTouchstart$.pipe(\r\n filter((touchstartEvent) => touchstartEvent.touches.length > 1)\r\n);\r\nconst mapPinchEnd$ = mapContainerTouchend$.pipe(\r\n filter((touchendEvent) => touchendEvent.touches.length > 1)\r\n);\r\n\r\nconst mapPinch$ = merge(mapPinchStart$, mapPinchEnd$);\r\n\r\nconst mapZoomPinch$ = mapZoomChange$.pipe(\r\n withLatestFrom(mapPinch$),\r\n\r\n // We have to validate if the last pinch was starting, otherwise it will mean\r\n // the zoom was caused by other reason.\r\n filter(([, lastPinchEvent]) => lastPinchEvent.type === 'touchstart'),\r\n map(([mapZoomChangeEvent]) => mapZoomChangeEvent.detail.isZoomIn),\r\n);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event based on whether the user is zooming in or out on a map using pinch gesture.\r\n * @param isZoomIn - Boolean value that indicates whether the map was zoom in or zoom out.\r\n */\r\nconst triggerMapZoomByPinch = (isZoomIn) => {\r\n const customProperties = {\r\n click_target: isZoomIn ? 'Zoom in map' : 'Zoom out map',\r\n click_target1: 'On Pinch',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_events', customProperties }));\r\n}\r\n\r\nmapZoomPinch$.subscribe(triggerMapZoomByPinch);\r\n\r\nconst mapWheel$ = fromEvent(mapContainerElement, 'wheel');\r\n\r\nconst mapZoomScroll$ = mapZoomChange$.pipe(\r\n // There's scenarios where the wheel event is triggered after the zoomChanged event.\r\n // So we have to wait a bit to get the latest wheel event.\r\n delay(50),\r\n withLatestFrom(mapWheel$),\r\n\r\n // The time when it is triggered could change. Sometimes the wheel event is triggered first, and sometimes\r\n // the zoomChanged event is triggered first. So we add a threshold time to validate if the wheel event\r\n // is related to the zoomChanged event.\r\n filter(([lastMapZoomEvent, lastMapWheelEvent]) => {\r\n const thresholdTime = 500;\r\n const maxTime = lastMapZoomEvent.timeStamp + thresholdTime;\r\n const minTime = lastMapZoomEvent.timeStamp - thresholdTime;\r\n\r\n return minTime < lastMapWheelEvent.timeStamp && lastMapWheelEvent.timeStamp < maxTime;\r\n }),\r\n map(([mapZoomChangeEvent]) => mapZoomChangeEvent.detail.isZoomIn),\r\n);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event based on whether the user is zooming in or out on a map using scrolling.\r\n * @param isZoomIn - Boolean value that indicates whether the map was zoom in or zoom out.\r\n */\r\nconst triggerMapZoomByScroll = (isZoomIn) => {\r\n const customProperties = {\r\n click_target: isZoomIn ? 'Zoom in map' : 'Zoom out map',\r\n click_target1: 'On Scroll',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_events', customProperties }));\r\n}\r\n\r\nmapZoomScroll$.subscribe(triggerMapZoomByScroll);\r\n\r\n// #endregion Map\r\n\r\n// #region Filter Menu\r\nconst facetPanel = document.querySelector('[data-facets-panel]');\r\nconst facetPanelClicks$ = fromEvent(facetPanel, 'click');\r\n\r\n/**\r\n * We assign the properties according to the clicked element.\r\n */\r\nconst getPropertiesFacets = {\r\n 'price-toggle': { filter_name: 'Price', click_target: 'Filter Clicked' },\r\n 'bedbath-toggle': { filter_name: 'Bed Bath', click_target: 'Filter Clicked' },\r\n 'movein-date': { filter_name: 'Move In', click_target: 'Filter Clicked' },\r\n 'allfilters-toggle': { filter_name: 'Advanced Search', click_target: 'Filter Clicked' },\r\n 'allfilters-clearAll': { filter_name: 'Advanced Search', click_target: 'Clear Filters' },\r\n 'allfilters-close': { filter_name: 'Advanced Search', click_target: 'Filter Closed' },\r\n};\r\n\r\nconst facetClicked$ = facetPanelClicks$.pipe(\r\n map((event) => event.target.closest('[data-panel-option]')),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when one of the filter panels,\r\n * clearAll, or close of the advanced panel is clicked.\r\n * @param element - Represents the DOM element clicked.\r\n */\r\nconst triggerFacetsClickEvent = (element) => {\r\n const option = element.dataset.panelOption;\r\n const customProperties = {\r\n ...getPropertiesFacets[option],\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\n\r\nfacetClicked$.subscribe(triggerFacetsClickEvent);\r\n\r\n// Typeahead\r\n/**\r\n * getSearchLocation: Gets the search location information based on what's on the search box\r\n * @param search All the location information: market, state, zip...\r\n * @returns The value with search location information.\r\n */\r\nconst getSearchLocation = (search) => {\r\n const { locationType, marketName, city, marketState, zip, syntheticGeographicName, county } = search;\r\n\r\n /* Search depending on the different search types */\r\n const searchLocationDictionary = {\r\n market: `${marketName} ${marketState}, Area`,\r\n city: `${city}, ${marketState}`,\r\n zip,\r\n syntheticGeo: `${syntheticGeographicName}, ${marketState}`,\r\n county: `${county} County, ${marketState}`,\r\n default: undefined,\r\n };\r\n\r\n const searchType = searchLocationDictionary[locationType];\r\n\r\n return searchType;\r\n}\r\n\r\n/**\r\n * Trigger a Google Analytics 4 event when the search is changed.\r\n * @param searchInformation - Represents the properties of the location.\r\n */\r\nconst triggerSearchEvent = (searchInformation) => {\r\n const search = getSearchLocation(searchInformation);\r\n if (!search) {\r\n return;\r\n }\r\n const customProperties = {\r\n filter_name: 'Location',\r\n search_value: search,\r\n current_location: search\r\n };\r\n setTimeout(() => store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties })), 0);\r\n};\r\nstore$.pipe(\r\n map(locationSearchParameters),\r\n distinctUntilChanged(),\r\n skip(1))\r\n .subscribe(triggerSearchEvent);\r\n\r\n// Price\r\nconst priceContainer = document.querySelector('[data-price-slider-container] [data-slider]');\r\n\r\nconst getPriceSliderChangeEvent = (handler) => priceContainer.noUiSlider.on('change', handler);\r\nconst priceChanged$ = fromEventPattern(getPriceSliderChangeEvent.bind(this)).pipe(\r\n map(([newValues]) => newValues)\r\n);\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the price filter is changed.\r\n * @param newValues - Represents the new values in the price.\r\n */\r\nconst triggerPriceChangeEvent = (newValues) => {\r\n const minPriceIndex = 0;\r\n const maxPriceIndex = 1;\r\n const customProperties = {\r\n filter_name: 'Price',\r\n click_target: 'Filter Applied',\r\n min_price: Math.trunc(newValues[minPriceIndex]),\r\n max_price: Math.trunc(newValues[maxPriceIndex]),\r\n };\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n}\r\npriceChanged$.subscribe(triggerPriceChangeEvent);\r\n\r\n// bedrooms and bathrooms\r\nconst bedFilter = document.querySelector('[data-bedrooms-group]');\r\nconst bathFilter = document.querySelector('[data-bathrooms-group]');\r\nconst panelBathChange$ = fromEvent(bathFilter, 'change').pipe(\r\n map((event) => event.target));\r\nconst panelBedChange$ = fromEvent(bedFilter, 'change').pipe(\r\n map((event) => event.target));\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when the bedrooms or bathrooms filter is clicked.\r\n * @param homeFacts Represents the list of home properties,\r\n * in this case extract bedrooms and bathrooms from it.\r\n */\r\nconst triggerbedBathFilterClickEvent = (homeFacts) => {\r\n const bedValue = homeFacts.bedrooms;\r\n const bathValue = homeFacts.bathrooms;\r\n const customProperties = {\r\n filter_name: 'Bed Bath',\r\n click_target: 'Filter Applied',\r\n bedrooms: bedValue,\r\n bathrooms: bathValue,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\n\r\nconst homeFacts$ = store$.pipe(\r\n map(homeFactsSelectors),\r\n distinctUntilChanged(),\r\n);\r\n\r\n/**\r\n * combine the observable of panelBathChange$ and panelChange$ so that when either is emitted, the event is triggered.\r\n * use homeFacts$ to get the most recent values of bedrooms and bathrooms\r\n */\r\nmerge(\r\n panelBathChange$,\r\n panelBedChange$\r\n).pipe(\r\n withLatestFrom(homeFacts$), map(([, homeFact]) => homeFact)\r\n).subscribe(triggerbedBathFilterClickEvent);\r\n\r\n// movein\r\nconst moveInDateFilter = document.querySelector('[data-move-in-date-filter]');\r\nconst moveInDatePanelChange$ = fromEvent(moveInDateFilter, 'change').pipe(\r\n filter((event) => event.target.closest('[data-move-in-date-filter]')),\r\n map((event) => event.target));\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any of the options in the moveInDate panel is clicked.\r\n * @param {*} element Represents the DOM element clicked on the panel.\r\n */\r\nconst triggermoveinDateFilterClickEvent = (element) => {\r\n const customProperties = {\r\n filter_name: 'Move In',\r\n click_target: 'Filter Applied',\r\n move_in_date: element.value,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\n\r\nmoveInDatePanelChange$.subscribe(triggermoveinDateFilterClickEvent);\r\n\r\n// Sort By\r\nconst sortChanged$ = store$.pipe(map(selectSorting), distinctUntilChanged(), skip(1));\r\nconst sortSelectElement = document.querySelector('[data-sort-select]');\r\n\r\n/**\r\n * getSortingLabel: Gets the label to be used on the sort value on GA4 events.\r\n * @param {object} sortingInformation Information related to sorting.\r\n * @returns The label to be used related to the sort value.\r\n */\r\nfunction getSortingLabel(sortingInformation) {\r\n const sortingValue = `${sortingInformation?.sortBy},${sortingInformation?.sortOrder}`;\r\n const sortingOption = sortSelectElement.querySelector(`[value=\"${sortingValue}\"]`);\r\n return sortingOption?.textContent;\r\n}\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any of the options in the sort by is clicked.\r\n * @param {*} element Represents the DOM element clicked on the sort by.\r\n */\r\nconst triggerSortByOptionClickEvent = (sorting) => {\r\n const customProperties = {\r\n search_value: getSortingLabel(sorting),\r\n click_target: 'Sort by',\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\n\r\nsortChanged$.subscribe(triggerSortByOptionClickEvent);\r\n\r\n// All filters\r\nconst allFiltersPanel = document.querySelector('[data-panel-allFilters]');\r\nconst allFiltersPanelChanges$ = fromEvent(allFiltersPanel, 'change').pipe(\r\n filter((event) => event.target.closest('[data-panel-allFilters]')),\r\n filter((event) => !event.target.closest('input#schools-dropdown')),\r\n filter((event) => !event.target.closest('input#community-status-dropdown')),\r\n map((event) => event.target));\r\n\r\n/**\r\n * Review the list of elements to get only those with true values.\r\n * @param elements\r\n * @returns A list with only the values that have true or undefined if no value was found.\r\n */\r\nconst getParametersActive = (elements) => {\r\n const activeFilters = Object.keys(elements)\r\n .filter(key => elements[key]);\r\n\r\n return activeFilters.length > 0 ? activeFilters : undefined;\r\n}\r\n\r\nconst getOthersproperties = (element) => {\r\n\r\n const otherProperties = {\r\n 'reviews': element.reviews || undefined,\r\n 'hotdeals': element.hotDeals || undefined,\r\n 'price_reduction': element.priceReduction || undefined,\r\n 'listings_hoa_info': element.hasHomeOwnersAssociationFee || undefined,\r\n '55plus-any': element.any || undefined,\r\n '55plus-only': element.only || undefined,\r\n '55plus-exclude': element.exclude || undefined,\r\n };\r\n\r\n return getParametersActive(otherProperties);\r\n\r\n}\r\n\r\n/**\r\n * Get the value for the properties,\r\n * and add undefined to those that do not have a significant value so that\r\n * when the event fires it skips the undefined values.\r\n * @param element - property list.\r\n * @returns A new list with the values assigned to each property for the event.\r\n */\r\nconst getFiltersAppliedProperties = (element) => ({\r\n home_type: getParametersActive(element.housingOptions),\r\n community_status: getParametersActive(element.communityStatus),\r\n min_price: element.price.minimumPrice || undefined,\r\n max_price: element.price.maximumPrice || undefined,\r\n move_in_date: element.moveInDate || undefined,\r\n school_districts: element.brandAndSchools.schools || undefined,\r\n brand_id: element.brandAndSchools.brandId || undefined,\r\n bedrooms: element.homeFacts.bedrooms || undefined,\r\n bathrooms: element.homeFacts.bathrooms || undefined,\r\n living_areas: element.homeFacts.livingAreas || undefined,\r\n primary_bedroom: element.homeFacts.primaryBedroom || undefined,\r\n stories: element.homeFacts.stories || undefined,\r\n garages: element.homeFacts.garages || undefined,\r\n other_features: element.homeFacts.rvGarage || undefined,\r\n other_filters: getOthersproperties(element.otherFilters),\r\n amenities: getParametersActive(element.amenities),\r\n});\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any of the filter options in the All filters panel is clicked.\r\n * @param elements Contains all updated filter values.\r\n */\r\nconst triggerAllFilterClickEvent = (elements) => {\r\n\r\n const customProperties = {\r\n filter_name: 'Advanced Search',\r\n click_target: 'Filter Applied',\r\n ...getFiltersAppliedProperties(elements),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\nconst facetsSelector$ = store$.pipe(\r\n map(facetsPanelSelector),\r\n distinctUntilChanged(),\r\n);\r\n\r\n/**\r\n * combine multiple observables into one using merge,\r\n * The 3 observables subscribe to triggerAllFilterClickEvent and use the same data source which is facetsSelector$,\r\n * all the observables are from different places in the allfilters panel,\r\n * priceChangedAdvance$ is from the price slider,\r\n * housingPanelClicks$ is from the housings option (luxury, custom, condos... .) and\r\n * allFiltersPanelChanges$ is everything else we have there and they react to the change event.\r\n * When you click on any of them, the entire list that comes in facetsSelector$ is read,\r\n * since the event emits all the active filters regardless of whether it is price,\r\n * bath/bed, schools, any active filter, so merge allows it.\r\n * for the priceChangedAdvance add a delay time using debounce so that\r\n * the price values are updated correctly in facetsPanelSelector.\r\n */\r\nmerge(\r\n allFiltersPanelChanges$,\r\n).pipe(\r\n withLatestFrom(facetsSelector$), map(([, facetsData]) => facetsData)\r\n).subscribe(triggerAllFilterClickEvent);\r\n// #endregion Filter Menu\r\n\r\n// #region Popular searches pill\r\n// Popular searches pill\r\nconst popularPillsFilters = document.querySelector('[data-popular-searches-pills-list]');\r\nconst popularPillsFiltersClicks$ = fromEvent(popularPillsFilters, 'click').pipe(\r\n map((event) => event.target));\r\n\r\n/**\r\n * Get the value for the properties,\r\n * and add undefined to those that do not have a significant value so that\r\n * when the event fires it skips the undefined values.\r\n * When the golf course pill is removed from the popular searches pills, please delete the amenities property from here.\r\n * Ticket where that pill will be removed: https://builderhomesite.atlassian.net/browse/NHS20-2391.\r\n * @param element - property list.\r\n * @returns A new list with the values assigned to each property for the event.\r\n */\r\nconst getPopularPillsAppliedProperties = (element) => {\r\n const otherFilters = getOthersproperties(element.otherFilters);\r\n const comingSoon = element.comingsoon ? ['comingsoon'] : [];\r\n return {\r\n amenities: getParametersActive(element.amenities),\r\n move_in_date: element.moveInDate || undefined,\r\n other_filters: [...otherFilters, ...comingSoon],\r\n home_type: getParametersActive(element.housingOptions),\r\n };\r\n};\r\n\r\n/**\r\n * Triggers a Google Analytics 4 event when any of the filter options in the popular search pills is clicked.\r\n * @param elements Contains all updated filter values.\r\n */\r\nconst triggerPopularPillsFilterClickEvent = (elements) => {\r\n\r\n const customProperties = {\r\n filter_name: 'Popular pills',\r\n click_target: 'Filter Applied',\r\n ...getPopularPillsAppliedProperties(elements),\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'search_filters', customProperties }));\r\n};\r\n\r\nconst popularPillsSelector$ = store$.pipe(\r\n map(selectLinkedPopularPillsFilters),\r\n distinctUntilChanged(),\r\n);\r\n\r\npopularPillsFiltersClicks$.pipe(\r\n debounceTime(500),\r\n withLatestFrom(popularPillsSelector$), map(([, filtersPopular]) => filtersPopular)\r\n).subscribe(triggerPopularPillsFilterClickEvent);\r\n// #endregion Popular searches pill\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Pins',\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 1,\r\n community_name: marker.metaData.communityName,\r\n type: MarkerType.HousingDevelopment.toString(),\r\n min_price: marker.metaData.priceLow,\r\n max_price: marker.metaData.priceHigh,\r\n is_paid: marker.metaData.isPaid,\r\n is_priced: isPriced(marker.metaData.priceLow) || isPriced(marker.metaData.priceHigh),\r\n is_zero_results: isNoResultsPage(),\r\n community_id: marker.id,\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n is_spotlight: marker.isFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pin_clicked', customProperties }));\r\n}\r\n\r\n// stream used to subscribe to community marker click events\r\nmarkerPinClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.HousingDevelopment.toString() || \r\n marker.type === MarkerType.BuildablePlan.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerCommunityMapMarkerClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for plan markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Pins',\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 1,\r\n type: marker.type,\r\n min_price: marker.metaData.priceLow,\r\n is_priced: isPriced(marker.metaData.priceLow),\r\n is_paid: marker.metaData.isPaid,\r\n is_zero_results: isNoResultsPage(),\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n plan_id: marker.id,\r\n is_plan: true,\r\n is_spec: false,\r\n is_spotlight: marker.isFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pin_clicked', customProperties }));\r\n}\r\n\r\n// stream used to subscribe to plan marker click events\r\nmarkerPinClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.PlanUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerPlanMapMarkerClickedEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapHoverEvent will dispatch the event of hovering in a community\r\n * static map. It will track properties as the identifier of the static map, and how many\r\n * time lasted the hovering gesture.\r\n */\r\nconst triggerCommunityStaticMapHoverEvent = ({ communityStaticMap, hoverDuration, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n hover_duration: hoverDuration,\r\n device_type: deviceType,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'map_hover', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapHovered$.subscribe(triggerCommunityStaticMapHoverEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapClickEvent will dispatch the event of clicking in a community.\r\n * static map.\r\n */\r\nconst triggerCommunityStaticMapClickEvent = ({ communityStaticMap, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'map_click', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapClicked$.subscribe(triggerCommunityStaticMapClickEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapDoubleClickEvent will dispatch the event of double clicking in a community.\r\n */\r\nconst triggerCommunityStaticMapDoubleClickEvent = ({ communityStaticMap, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n redirected_to: communityStaticMap.url,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'map_double_click', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapDoubleClicked$.subscribe(triggerCommunityStaticMapDoubleClickEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapZoomChangedEvent will dispatch an event with information like\r\n * identifier and name of the community static map that received the zoom change. Also, it\r\n * will track if the zoom change was a zoom in or out.\r\n */\r\nconst triggerCommunityStaticMapZoomChangedEvent = ({ communityStaticMap, zoomGesture, deviceType, zoomLevel }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n zoom_level: zoomLevel,\r\n };\r\n\r\n const eventName = zoomGesture === \"zoomIn\" ? \"map_zoom_in\" : \"map_zoom_out\";\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName, customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapZoomChanged$.subscribe(triggerCommunityStaticMapZoomChangedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for spec markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Pins',\r\n event_type: 'TDV Events',\r\n currency: 'USD',\r\n value: 1,\r\n type: marker.type,\r\n min_price: marker.metaData.priceLow,\r\n is_priced: isPriced(marker.metaData.priceLow),\r\n is_paid: marker.metaData.isPaid,\r\n is_zero_results: isNoResultsPage(),\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n spec_id: marker.id,\r\n is_plan: false,\r\n is_spec: true,\r\n is_spotlight: marker.isFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'pin_clicked', customProperties }));\r\n}\r\n\r\n// stream used to subscribe to spec marker click events\r\nmarkerPinClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.SpecUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerSpecMapMarkerClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunitySummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Card',\r\n click_target1: 'Community Link Clicked',\r\n market_id: marker.MarketId,\r\n community_name: marker.Name,\r\n type: marker.Type,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n min_price: marker.PriceLow,\r\n max_price: marker.PriceHigh,\r\n community_status: marker.MarketingStatus?.Name,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResultsPage(),\r\n community_id: marker.Id,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n destination: marker.Url,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_card_clicked', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for plan markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanSummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Card',\r\n click_target1: 'Home Link Clicked',\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResultsPage(),\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n plan_id: marker.Id,\r\n is_plan: true,\r\n is_spec: false,\r\n home_status: marker.StatusLabel,\r\n destination: marker.Url,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_card_clicked', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for spec markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecSummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n click_target: 'SRP Map Card',\r\n click_target1: 'Home Link Clicked',\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResultsPage(),\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n spec_id: marker.Id,\r\n is_plan: false,\r\n is_spec: true,\r\n home_status: marker.StatusLabel,\r\n destination: marker.Url,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: 'map_card_clicked', customProperties }));\r\n}\r\n\r\n/**\r\n * Stream used to check when a new community card link is clicked.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.HousingDevelopment.toString())\r\n).subscribe(triggerCommunitySummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Stream used to check when a new home card link is clicked.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.PlanUnit.toString())\r\n).subscribe(triggerPlanSummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Stream used to check when a new home card link is clicked.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.SpecUnit.toString())\r\n).subscribe(triggerSpecSummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunitySummaryCardCallToActionClickEvent(detail) {\r\n const { marker, callToAction, target } = detail;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: target,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: callToAction,\r\n market_id: marker.MarketId,\r\n community_name: marker.Name,\r\n type: marker.Type,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n min_price: marker.PriceLow,\r\n max_price: marker.PriceHigh,\r\n community_status: marker.MarketingStatus?.Name,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResults,\r\n community_id: marker.Id,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanSummaryCardCallToActionClickEvent(detail) {\r\n const { marker, callToAction, target } = detail;\r\n const isNoResults = isNoResultsPage();\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: target,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: callToAction,\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResults,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n plan_id: marker.Id,\r\n is_plan: true,\r\n is_spec: false,\r\n home_status: marker.StatusLabel,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecSummaryCardCallToActionClickEvent(detail) {\r\n const { marker, callToAction, target } = detail;\r\n const isNoResults = isNoResultsPage();\r\n\r\n const clickTarget = getClickTarget({\r\n isNoResultsPage: isNoResults,\r\n clickTarget: target,\r\n });\r\n\r\n const customProperties = {\r\n click_target: clickTarget,\r\n button_name: callToAction,\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResultsPage(),\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n spec_id: marker.Id,\r\n is_plan: false,\r\n is_spec: true,\r\n home_status: marker.StatusLabel,\r\n is_spotlight: marker.IsFeaturedListing,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'form_open', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the community map marker url opened event.\r\n *\r\n * @param {Object} event - The event object containing the marker and interaction type details.\r\n * @param {Object} event.detail.marker - The marker object.\r\n * @param {string} event.detail.interactionType - The type of interaction that triggered the event.\r\n */\r\nfunction triggerCommunityMarkerUrlOpenedEvent(data) {\r\n const { marker, interactionType } = data;\r\n\r\n const customProperties = {\r\n click_target: 'SRP Map Pins',\r\n click_target1: interactionType,\r\n community_name: marker.metaData.communityName,\r\n type: MarkerType.HousingDevelopment.toString(),\r\n min_price: marker.metaData.priceLow,\r\n max_price: marker.metaData.priceHigh,\r\n is_priced: isPriced(marker.metaData.priceLow) || isPriced(marker.metaData.priceHigh),\r\n is_paid: marker.metaData.isPaid,\r\n is_zero_results: isNoResultsPage(),\r\n community_id: marker.id,\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n destination: marker.url\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: \"mappin_double_clicked\", customProperties }));\r\n}\r\n\r\nmarkerUrlOpened$.pipe(\r\n filter(data => Boolean(data?.marker?.id)),\r\n filter(data => data?.marker?.type === MarkerType.HousingDevelopment.toString() || \r\n data?.marker?.type === MarkerType.BuildablePlan.toString() ),\r\n).subscribe(triggerCommunityMarkerUrlOpenedEvent);\r\n\r\n/**\r\n * Triggers the plan map marker url opened event.\r\n *\r\n * @param {Object} event - The event object containing the marker and interaction type details.\r\n * @param {Object} event.detail.marker - The marker object.\r\n * @param {string} event.detail.interactionType - The type of interaction that triggered the event.\r\n */\r\nfunction triggerPlanMarkerUrlOpenedEvent(data) {\r\n const { marker, interactionType } = data;\r\n\r\n const customProperties = {\r\n click_target: \"SRP Map Pins\",\r\n click_target1: interactionType,\r\n plan_id: marker.id,\r\n type: marker.type,\r\n min_price: marker.metaData.priceLow,\r\n is_priced: isPriced(marker.metaData.priceLow),\r\n is_paid: marker.metaData.isPaid,\r\n is_zero_results: isNoResultsPage(),\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n is_plan: true,\r\n is_spec: false,\r\n destination: marker.url,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: \"mappin_double_clicked\", customProperties }));\r\n}\r\n\r\nmarkerUrlOpened$.pipe(\r\n filter(data => Boolean(data?.marker?.id)),\r\n filter(data => data?.marker?.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanMarkerUrlOpenedEvent);\r\n\r\n/**\r\n * Triggers the spec map marker url opened event.\r\n *\r\n * @param {Object} event - The event object containing the marker and interaction type details.\r\n * @param {Object} event.detail.marker - The marker object.\r\n * @param {string} event.detail.interactionType - The type of interaction that triggered the event.\r\n */\r\nfunction triggerSpecMarkerUrlOpenedEvent(data) {\r\n const { marker, interactionType } = data;\r\n\r\n const customProperties = {\r\n click_target: \"SRP Map Pins\",\r\n click_target1: interactionType,\r\n spec_id: marker.id,\r\n type: marker.type,\r\n min_price: marker.metaData.priceLow,\r\n is_priced: isPriced(marker.metaData.priceLow),\r\n is_paid: marker.metaData.isPaid,\r\n is_zero_results: isNoResultsPage(),\r\n price_reduction: marker.metaData.priceReducedTrackingLabel,\r\n is_plan: false,\r\n is_spec: true,\r\n destination: marker.url,\r\n };\r\n\r\n store.dispatch(googleAnalytics4Event({ eventName: \"mappin_double_clicked\", customProperties }));\r\n}\r\n\r\nmarkerUrlOpened$.pipe(\r\n filter(data => Boolean(data?.marker?.id)),\r\n filter(data => data?.marker?.type === MarkerType.SpecUnit.toString()),\r\n).subscribe(triggerSpecMarkerUrlOpenedEvent);\r\n\r\n/**\r\n * Stream used to check when a community summary card call to action is clicked.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.HousingDevelopment.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerCommunitySummaryCardCallToActionClickEvent);\r\n\r\n/**\r\n * Stream used to check when a plan summary card call to action is clicked.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.PlanUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerPlanSummaryCardCallToActionClickEvent);\r\n\r\n/**\r\n * Stream used to check when a spec summary card call to action is clicked.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.SpecUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerSpecSummaryCardCallToActionClickEvent);\r\n\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const isNoResults = isNoResultsPage();\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_name: marker.Name,\r\n type: marker.Type,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n min_price: marker.PriceLow,\r\n max_price: marker.PriceHigh,\r\n community_status: marker.MarketingStatus?.Name,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResults,\r\n community_id: marker.Id,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n direction: data.direction,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_card_swiped', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for plan markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const isNoResults = isNoResultsPage();\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResults,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n plan_id: marker.Id,\r\n is_plan: true,\r\n is_spec: false,\r\n home_status: marker.StatusLabel,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_card_swiped', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for spec markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_zero_results: isNoResultsPage(),\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n spec_id: marker.Id,\r\n is_plan: false,\r\n is_spec: true,\r\n home_status: marker.StatusLabel,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_card_swiped', customProperties })));\r\n}\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanCarouselScrolledEvent);\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.SpecUnit.toString()),\r\n).subscribe(triggerSpecCarouselScrolledEvent);\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.HousingDevelopment.toString()),\r\n).subscribe(triggerCommunityCarouselScrolledEvent);\r\n\r\n\r\n/**\r\n * Triggers the carousel closed event for community markers.\r\n * @param {Object} data - The data object containing the active marker.\r\n */\r\nfunction triggerCommunityCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_name: marker.Name,\r\n type: marker.Type,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n min_price: marker.PriceLow,\r\n max_price: marker.PriceHigh,\r\n community_status: marker.MarketingStatus?.Name,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n community_id: marker.Id,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n listing_id: data.listingId,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_closed', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the carousel closed event for plan markers.\r\n * @param {Object} data - The data object containing the active marker.\r\n */\r\nfunction triggerPlanCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n plan_id: marker.Id,\r\n is_plan: true,\r\n is_spec: false,\r\n home_status: marker.StatusLabel,\r\n listing_id: data.listingId,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_closed', customProperties })));\r\n}\r\n\r\n/**\r\n * Triggers the carousel closed event for spec markers.\r\n * @param {Object} data - The data object containing the active marker.\r\n */\r\nfunction triggerSpecCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n type: marker.Type,\r\n min_price: marker.PriceLow,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n trustbuilder_reviews: marker.BuilderRating > 0,\r\n is_priced: Boolean(marker.PriceLow) && marker.PriceLow !== '0',\r\n is_paid: !marker.IsBasic,\r\n is_limited_availability: marker.IsLimited,\r\n zip_code: marker.Zip,\r\n price_reduction: marker.PriceReductionLabel,\r\n spec_id: marker.Id,\r\n is_plan: false,\r\n is_spec: true,\r\n home_status: marker.StatusLabel,\r\n listing_id: data.listingId,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(googleAnalytics4Event({ eventName: 'carousel_closed', customProperties })));\r\n}\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.HousingDevelopment.toString()),\r\n).subscribe(triggerCommunityCarouselClosedEvent);\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanCarouselClosedEvent);\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.SpecUnit.toString()),\r\n).subscribe(triggerSpecCarouselClosedEvent);","/**\r\n * ImpressionEventObserver: Class to be able to check when an element was viewed for impression event purposes.\r\n * As the impression events should be triggerred once, the element should be unobserve when it was\r\n * on the viewport according to IntersectionObserver API.\r\n */\r\nexport default class ImpressionEventObserver {\r\n constructor(callbackOnIntersection, options){\r\n const defaultOptions = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 1.0\r\n };\r\n \r\n const intersectionHandler = (entries, observer) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting) {\r\n const intersectedElement = entry.target;\r\n callbackOnIntersection(intersectedElement);\r\n observer.unobserve(intersectedElement)\r\n }\r\n });\r\n }\r\n \r\n this.intersectionObserver = new IntersectionObserver(intersectionHandler, options || defaultOptions);\r\n }\r\n \r\n /**\r\n * getIntersectionObserver: Gets the IntersectionObserver API object to be able to observe the elements.\r\n * @returns The IntersectionObserver API object.\r\n */\r\n getIntersectionObserver = () => this.intersectionObserver;\r\n}","import { store, store$ } from '@redux/store';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectCurrentUrl } from 'features/routing';\r\nimport { FavoriteType, selectNeustarStatus, selectPendingSaves } from 'features/userProfile';\r\nimport { ResultType, selectFetchCountsStatusAndsCounts, selectSorting } from 'features/searchResultsFacets';\r\nimport { segmentIdentify, segmentImpression, segmentPageView, segmentTrack } from 'features/segment';\r\nimport {\r\n newListingSaved$,\r\n paidCommunityModalSubmission$,\r\n basicCommunityModalSubmission$,\r\n paidHomeModalSubmission$,\r\n basicPlanModalSubmission$,\r\n basicSpecModalSubmission$,\r\n basicListingModalSubmission$,\r\n paidManufacturedLocationModalSubmission$,\r\n paidManufacturedPlanModalSubmission$,\r\n paidManufacturedSpecModalSubmission$,\r\n recommendedCommunitiesSubmitted$,\r\n recommendedCommunitiesSubmittedBasic$,\r\n summaryCardLinkClicked$,\r\n summaryCardCtaClicked$,\r\n markerUrlOpened$,\r\n markerSummaryCardClicked$,\r\n pendingListingSavesFavorites$,\r\n removedFavorites$,\r\n nearbyListingsCarouselScrolled$,\r\n carouselCloseButtonClicked$,\r\n communityStaticMapHovered$,\r\n communityStaticMapClicked$,\r\n communityStaticMapDoubleClicked$,\r\n communityStaticMapZoomChanged$,\r\n} from 'pages/searchResults/redux/observables';\r\nimport { \r\n combineLatest,\r\n distinctUntilChanged, \r\n distinctUntilKeyChanged, \r\n filter, \r\n fromEvent, \r\n map, \r\n pairwise, \r\n skip,\r\n tap} from 'rxjs';\r\nimport ImpressionEventObserver from 'utils/impressionEventObserver';\r\nimport { selectHousingProductLocationFetchStatus, selectRequestStatus } from 'features/locationContent';\r\nimport { MarkerType } from 'features/searchResultsMap';\r\nimport { selectSelectedMarker } from 'pages/searchResults/redux/selectors';\r\nimport PageType from 'enums/pageType';\r\n\r\n\r\n// #region List View Section\r\n/**\r\n * ! List View Section\r\n * All events related elements located in the list view should be placed in this region\r\n */\r\n\r\n/**\r\n * * This selector will work as an event delegator for all the click events\r\n * * that must be attached to elements inside the list view section\r\n */\r\nconst paidCommunityCardSelector = '[data-standard-card][data-paid-community]';\r\nconst paidBuildOnYourLotCommunityCardSelector = '[data-standard-card][data-paid-boyl-location]';\r\nconst paidCustomCommunityCardSelector = '[data-standard-card][data-paid-custom-location]';\r\nconst paidManufacturedCommunityCardSelector = '[data-standard-card][data-paid-manufactured-location]';\r\nconst basicCommunityCardSelector = '[data-standard-card][data-basic-community]';\r\nconst basicBuildOnYourLotCommunityCardSelector = '[data-standard-card][data-basic-boyl-location]';\r\nconst basicCustomCommunityCardSelector = '[data-standard-card][data-basic-custom-location]';\r\nconst basicManufacturedCommunityCardSelector = '[data-standard-card][data-basic-manufactured-location]';\r\nconst paidPlanCardSelector = '[data-standard-card][data-paid-plan]';\r\nconst paidSpecCardSelector = '[data-standard-card][data-paid-spec]';\r\nconst basicPlanCardSelector = '[data-standard-card][data-basic-plan]';\r\nconst basicSpecCardSelector = '[data-standard-card][data-basic-spec]';\r\nconst basicCustomPlanCardSelector = '[data-standard-card][data-basic-custom-plan]';\r\nconst basicCustomSpecCardSelector = '[data-standard-card][data-basic-custom-spec]';\r\nconst basicBuildOnYourLotPlanCardSelector = '[data-standard-card][data-basic-boyl-plan]';\r\nconst basicBuildOnYourLotSpecCardSelector = '[data-standard-card][data-basic-boyl-spec]';\r\nconst basicListingCardSelector = '[data-standard-card][data-basic-listing]'\r\nconst paidManufacturedPlanCardSelector = '[data-standard-card][data-paid-manufactured-plan]';\r\nconst paidManufacturedSpecCardSelector = '[data-standard-card][data-paid-manufactured-spec]';\r\nconst basicManufacturedPlanCardSelector = '[data-standard-card][data-basic-manufactured-plan]';\r\nconst basicManufacturedSpecCardSelector = '[data-standard-card][data-basic-manufactured-spec]';\r\nconst paidCustomPlanCardSelector = '[data-standard-card][data-paid-custom-plan]';\r\nconst paidCustomSpecCardSelector = '[data-standard-card][data-paid-custom-spec]';\r\nconst paidBuildOnYourLotPlanCardSelector = '[data-standard-card][data-paid-boyl-plan]';\r\nconst paidBuildOnYourLotSpecCardSelector = '[data-standard-card][data-paid-boyl-spec]';\r\nconst cardfavoriteButtonSelector = '[data-favorite-button]';\r\nconst listViewSection = document.querySelector('[data-list-view-element]');\r\nconst listViewSectionClicks$ = fromEvent(listViewSection, 'click');\r\nconst customAndBuildOnYourLotHomesSelectors = [\r\n basicCustomPlanCardSelector,\r\n basicCustomSpecCardSelector,\r\n basicBuildOnYourLotPlanCardSelector,\r\n basicBuildOnYourLotSpecCardSelector,\r\n paidCustomSpecCardSelector,\r\n paidBuildOnYourLotPlanCardSelector,\r\n paidBuildOnYourLotSpecCardSelector];\r\nconst customAndBuildOnYourLotCommunitiesSelectors = [\r\n paidBuildOnYourLotCommunityCardSelector,\r\n paidCustomCommunityCardSelector,\r\n basicBuildOnYourLotCommunityCardSelector,\r\n basicCustomCommunityCardSelector]; \r\n\r\n/**\r\n * Checks if a the page is showing the no result content.\r\n */\r\nconst isNotResultPage = () => !!listViewSection.querySelector('[data-no-result=\"true\"]');\r\n\r\n/**\r\n * Checks if it is a New Session.\r\n */\r\nfunction isUserNewSession() {\r\n return !!sessionStorage.getItem('isNewSession'); \r\n};\r\n\r\n/**\r\n* Set New Session.\r\n*/\r\nfunction setUserNewSession() {\r\n sessionStorage.setItem('isNewSession', 'true');\r\n}\r\n\r\nconst triggerIdentifyNewSession = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'New Session' }));\r\n};\r\n\r\n/**\r\n * Checks if the Neustar Segment Information is loaded.\r\n */\r\nconst isNeustarSegmentLoaded$ = store$.pipe(\r\n map(selectNeustarStatus),\r\n distinctUntilChanged(),\r\n filter((neustarStatus) => neustarStatus === LoadingStatus.Succeeded.toString()),\r\n filter(() => !isUserNewSession()),\r\n tap(setUserNewSession)\r\n)\r\n\r\nisNeustarSegmentLoaded$.subscribe(triggerIdentifyNewSession);\r\n\r\n/* \r\nObject that maps the names of the areas clicked on a card element to the corresponding segment event property. \r\n*/\r\nconst segmentAreaClickedPerCardElement = {\r\n price: 'Price Area',\r\n priceReduction: 'Price Area',\r\n communityName: 'Community Name Area',\r\n planName: 'Plan Name Area',\r\n specAddress: 'Spec Address Area',\r\n image: 'Image Area',\r\n brandName: 'Builder Name Area',\r\n ratingsScore: 'Ratings Score Area',\r\n default: 'Card',\r\n};\r\n\r\n/**\r\n * The getCardImageUrls function takes a cardElement as an argument and returns an object with the following properties:\r\n * primaryImage, secondaryImage, terciaryImage.\r\n * if there are no images in the cardElement then each property will be assigned to an empty string.\r\n * This can be used to other events in the list view section.\r\n * @param cardElement Get the image elements from the card element\r\n *\r\n * @return An object with primaryImage, secondaryImage, terciaryImage.\r\n */\r\nconst getCardImageUrls = (cardElement) => {\r\n const imageElements = cardElement.querySelectorAll('img');\r\n\r\n if (imageElements) {\r\n return {\r\n primaryImage: imageElements[0]?.src || '',\r\n secondaryImage: imageElements[1]?.src || '',\r\n terciaryImage: imageElements[2]?.src || '',\r\n };\r\n }\r\n\r\n return {};\r\n};\r\n\r\n// ! Community Lead Button Click Event //\r\n\r\n/**\r\n * The getLeadButtonClickedCommunityCustomProperties function is used to get the custom properties\r\n * for communities for the event LeadButtonClicked\r\n * @param cardDataset The card dataset\r\n * @param buttonDataset The button dataset\r\n * @param isPaid Bool that define if the community is paid or basic\r\n */\r\nconst getLeadButtonClickedCommunityCustomProperties = (cardDataset, buttonDataset, isPaid) => {\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n button_action: buttonDataset.buttonAction,\r\n is_paid: isPaid,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n return customProperties;\r\n};\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidCustomCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidCustomCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidBuildOnYourLotCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidBuildOnYourLotCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidManufacturedCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidManufacturedCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerPaidCustomCommunityLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerPaidCustomCommunityLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidCustomCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerPaidBuildOnYourLotCommunityLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerPaidBuildOnYourLotCommunityLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuildOnYourLotCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerPaidManufacturedCommunityLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerPaidManufacturedCommunityLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\npaidCommunityLeadButtonClicked$.subscribe(triggerLeadButtonClickEvent);\r\npaidCustomCommunityLeadButtonClicked$.subscribe(triggerPaidCustomCommunityLeadButtonClickEvent);\r\npaidBuildOnYourLotCommunityLeadButtonClicked$.subscribe(triggerPaidBuildOnYourLotCommunityLeadButtonClickEvent);\r\npaidManufacturedCommunityLeadButtonClicked$.subscribe(triggerPaidManufacturedCommunityLeadButtonClickEvent);\r\n\r\n// ! Basic Community Lead Button Click Event //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicBuildOnYourLotCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicBuildOnYourLotCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicCustomCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicCustomCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicManufacturedCommunityLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicManufacturedCommunityCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerBasicLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerBasicLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, false);\r\n \r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicBuildOnYourLotLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerBasicBuildOnYourLotLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicBuildOnYourLotCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, false);\r\n \r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicCustomLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerBasicCustomLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicCustomCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, false);\r\n \r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicManufacturedLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n */\r\nconst triggerBasicManufacturedLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicManufacturedCommunityCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n const customProperties = getLeadButtonClickedCommunityCustomProperties(cardDataset, buttonDataset, false);\r\n \r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\nbasicCommunityLeadButtonClicked$.subscribe(triggerBasicLeadButtonClickEvent);\r\nbasicBuildOnYourLotCommunityLeadButtonClicked$.subscribe(triggerBasicBuildOnYourLotLeadButtonClickEvent);\r\nbasicCustomCommunityLeadButtonClicked$.subscribe(triggerBasicCustomLeadButtonClickEvent);\r\nbasicManufacturedCommunityLeadButtonClicked$.subscribe(triggerBasicManufacturedLeadButtonClickEvent);\r\n\r\n// ! Community Result Selected Event //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst paidcommunityCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidCommunityCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerCommunityCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerCommunityCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidCommunityCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n image_2_url: cardImages.secondaryImage,\r\n image_3_url: cardImages.terciaryImage,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Selected', customProperties }));\r\n};\r\n\r\npaidcommunityCardClicked$.subscribe(triggerCommunityCardClickEvent);\r\n\r\n// ! Community Result Selected Event: Basic Communities //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst basicCommunityCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(basicCommunityCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerBasicCommunityCardClickEvent function is used to track the card click for Basic Communities.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicCommunityCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicCommunityCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n is_paid: false,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n image_2_url: cardImages.secondaryImage,\r\n image_3_url: cardImages.terciaryImage,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Selected', customProperties }));\r\n};\r\n\r\nbasicCommunityCardClicked$.subscribe(triggerBasicCommunityCardClickEvent);\r\n\r\n// ! Community Favorited Event //\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPendingFavoritesChanged$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise()\r\n);\r\n\r\n/**\r\n * The triggerCommunityFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerCommunityFavoritedEvent = (payload) => {\r\n const [lastValue, newValue] = payload;\r\n\r\n // this filter, validates if it was an item addition to the existing array, and works with the addedd item\r\n const newFavoritedItems = newValue.filter((item) => !lastValue.includes(item));\r\n if (!newFavoritedItems || newFavoritedItems.length === 0) {\r\n return;\r\n }\r\n\r\n const itemId = newFavoritedItems[0].listingInformation.id;\r\n const typeCard = newFavoritedItems[0].listingInformation.isBasic === 'true'\r\n ? 'basic' : 'paid';\r\n const cardElement = document.querySelector(`[data-${typeCard}-community][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n\r\n const cardDataset = cardElement.dataset;\r\n const isPaid = cardElement.dataset.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n is_paid: isPaid,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nonPendingFavoritesChanged$.subscribe(triggerCommunityFavoritedEvent);\r\n\r\n// ! Home (Spec/Plan) Lead Button Click Event //\r\n/**\r\n * The getLeadButtonClickedPlanCustomProperties function is used to get the custom properties\r\n * for plans for the event LeadButtonClicked\r\n * @param cardElement The card element\r\n * @param buttonDataset The button dataset\r\n * @param isPaid Bool that define if the community is paid or basic\r\n */\r\nconst getLeadButtonClickedHomesCustomProperties = (cardElement, buttonDataset, isPaid) => {\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n button_action: buttonDataset.buttonAction,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_paid: isPaid,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n return customProperties;\r\n};\r\n\r\n\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidManufacturedPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidManufacturedPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidManufacturedSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidManufacturedSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidCustomPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidCustomPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidCustomSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidCustomSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidBuildOnYourLotPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidBuildOnYourLotPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst paidBuildOnYourLotSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(paidBuildOnYourLotSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerManufacturedPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerManufacturedPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerManufacturedSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerManufacturedSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerCustomPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerCustomPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidCustomPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerCustomSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerCustomSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidCustomSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBuildOnYourLotPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBuildOnYourLotPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuildOnYourLotPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBuildOnYourLotSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBuildOnYourLotSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(paidBuildOnYourLotSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, true);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\npaidPlanLeadButtonClicked$.subscribe(triggerPlanLeadButtonClickEvent);\r\npaidSpecLeadButtonClicked$.subscribe(triggerSpecLeadButtonClickEvent);\r\npaidManufacturedPlanLeadButtonClicked$.subscribe(triggerManufacturedPlanLeadButtonClickEvent);\r\npaidManufacturedSpecLeadButtonClicked$.subscribe(triggerManufacturedSpecLeadButtonClickEvent);\r\npaidCustomPlanLeadButtonClicked$.subscribe(triggerCustomPlanLeadButtonClickEvent);\r\npaidCustomSpecLeadButtonClicked$.subscribe(triggerCustomSpecLeadButtonClickEvent);\r\npaidBuildOnYourLotPlanLeadButtonClicked$.subscribe(triggerBuildOnYourLotPlanLeadButtonClickEvent);\r\npaidBuildOnYourLotSpecLeadButtonClicked$.subscribe(triggerBuildOnYourLotSpecLeadButtonClickEvent);\r\n\r\n// ! Basic Home (Spec/Plan/Listing) Lead Button Click Event //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicManufacturedPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicManufacturedPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicManufacturedSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicManufacturedSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicCustomPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicCustomPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicCustomSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicCustomSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicBuildOnYourLotPlanLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicBuildOnYourLotPlanCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicBuildOnYourLotSpecLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicBuildOnYourLotSpecCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the CTA button.\r\nconst basicListingLeadButtonClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.dataset.leadGeneratorOpener),\r\n filter((event) => event.target.closest(basicListingCardSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerBasicPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicManufacturedPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicManufacturedPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicManufacturedPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicManufacturedSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicManufacturedSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicManufacturedSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicCustomPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicCustomPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicCustomPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicCustomSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicCustomSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicCustomSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicBuildOnYourLotPlanLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicBuildOnYourLotPlanLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicBuildOnYourLotPlanCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\n/**\r\n * The triggerBasicBuildOnYourLotSpecLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicBuildOnYourLotSpecLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicBuildOnYourLotSpecCardSelector);\r\n const buttonDataset = element.dataset;\r\n const customProperties = getLeadButtonClickedHomesCustomProperties(cardElement, buttonDataset, false);\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n/**\r\n * The triggerBasicListingLeadButtonClickEvent function is used to track the Lead Button Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param element Get the target element of the event\r\n */\r\nconst triggerBasicListingLeadButtonClickEvent = (element) => {\r\n const cardElement = element.closest(basicListingCardSelector);\r\n const buttonDataset = element.dataset;\r\n const cardDataset = cardElement.dataset;\r\n\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n primary_image_url: primaryImageUrl,\r\n button_action: buttonDataset.buttonAction,\r\n listing_id: cardDataset.id,\r\n home_price: cardDataset.price,\r\n is_paid: false,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n};\r\n\r\nbasicPlanLeadButtonClicked$.subscribe(triggerBasicPlanLeadButtonClickEvent);\r\nbasicSpecLeadButtonClicked$.subscribe(triggerBasicSpecLeadButtonClickEvent);\r\nbasicManufacturedPlanLeadButtonClicked$.subscribe(triggerBasicManufacturedPlanLeadButtonClickEvent);\r\nbasicManufacturedSpecLeadButtonClicked$.subscribe(triggerBasicManufacturedSpecLeadButtonClickEvent);\r\nbasicCustomPlanLeadButtonClicked$.subscribe(triggerBasicCustomPlanLeadButtonClickEvent);\r\nbasicCustomSpecLeadButtonClicked$.subscribe(triggerBasicCustomSpecLeadButtonClickEvent);\r\nbasicBuildOnYourLotPlanLeadButtonClicked$.subscribe(triggerBasicBuildOnYourLotPlanLeadButtonClickEvent);\r\nbasicBuildOnYourLotSpecLeadButtonClicked$.subscribe(triggerBasicBuildOnYourLotSpecLeadButtonClickEvent);\r\nbasicListingLeadButtonClicked$.subscribe(triggerBasicListingLeadButtonClickEvent);\r\n\r\n// ! Home Result Selected Event (spec / plan) //\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst paidPlanCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidPlanCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst paidSpecCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidSpecCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst manufacturedPlanCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidManufacturedPlanCardSelector) ||\r\n event.target.closest(basicManufacturedPlanCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst manufacturedSpecCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidManufacturedSpecCardSelector) ||\r\n event.target.closest(basicManufacturedSpecCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst paidCustomPlanCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidCustomPlanCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst basicListingCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(basicListingCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst basicPlanCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(basicPlanCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst basicSpecCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(basicSpecCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerPlanCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerSpecCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerSpecCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidSpecCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerManufacturedPlanCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerManufacturedPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedPlanCardSelector) ||\r\n element.closest(basicManufacturedPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerManufacturedPlanCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerManufacturedSpecCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedSpecCardSelector) ||\r\n element.closest(basicManufacturedSpecCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n/**\r\n * The triggerCustomPlanCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerCustomPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidCustomPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerBasicListingCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicListingCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicListingCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n is_paid: false,\r\n id: cardDataset.id,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Basic Detail Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerBasicPlanCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicPlanCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicPlanCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n plan_id: cardDataset.planId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\n/**\r\n * The triggerBasicSpecCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicSpecCardClickEvent = (element) => {\r\n const cardElement = element.closest(basicSpecCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n spec_id: cardDataset.specId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\npaidPlanCardClicked$.subscribe(triggerPlanCardClickEvent);\r\npaidSpecCardClicked$.subscribe(triggerSpecCardClickEvent);\r\nmanufacturedPlanCardClicked$.subscribe(triggerManufacturedPlanCardClickEvent);\r\nmanufacturedSpecCardClicked$.subscribe(triggerManufacturedSpecCardClickEvent);\r\npaidCustomPlanCardClicked$.subscribe(triggerCustomPlanCardClickEvent);\r\nbasicListingCardClicked$.subscribe(triggerBasicListingCardClickEvent);\r\nbasicPlanCardClicked$.subscribe(triggerBasicPlanCardClickEvent);\r\nbasicSpecCardClicked$.subscribe(triggerBasicSpecCardClickEvent);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst customAndBuildOnYourLotHomeCardClicked$ = listViewSectionClicks$.pipe(\r\n map((event) => {\r\n const foundSelector = customAndBuildOnYourLotHomesSelectors.find((selector) => event.target.closest(selector));\r\nreturn { event, foundSelector };\r\n }),\r\n filter(({ foundSelector }) => !!foundSelector),\r\n filter(({ event }) => !event.target.dataset?.leadGeneratorOpener),\r\n filter(({ event }) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map(({ event, foundSelector }) => ({ event, foundSelector }))\r\n);\r\n\r\n/**\r\n * The triggerCommunityCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerCustomAndBuildOnYourLotHomeCardClickEvent = ({ event, foundSelector }) => {\r\n const cardElement = event.target.closest(foundSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = event.target.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardImages.primaryImage,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Selected', customProperties }));\r\n};\r\n\r\ncustomAndBuildOnYourLotHomeCardClicked$.subscribe(triggerCustomAndBuildOnYourLotHomeCardClickEvent);\r\n\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst customAndBuildOnYourLotCommunityCardClicked$ = listViewSectionClicks$.pipe(\r\n map((event) => {\r\n const foundSelector = customAndBuildOnYourLotCommunitiesSelectors\r\n .find((selector) => event.target.closest(selector));\r\n return { event, foundSelector };\r\n }),\r\n filter(({ foundSelector }) => !!foundSelector),\r\n filter(({ event }) => !event.target.dataset?.leadGeneratorOpener),\r\n filter(({ event }) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map(({ event, foundSelector }) => ({ event, foundSelector }))\r\n);\r\n\r\n/**\r\n * The triggerCommunityCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerCustomAndBuildOnYourLotCommunityCardClickEvent = ({ event, foundSelector }) => {\r\n const cardElement = event.target.closest(foundSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = event.target.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n image_2_url: cardImages.secondaryImage,\r\n image_3_url: cardImages.terciaryImage,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Selected', customProperties }));\r\n};\r\n\r\ncustomAndBuildOnYourLotCommunityCardClicked$.subscribe(triggerCustomAndBuildOnYourLotCommunityCardClickEvent);\r\n\r\n// observable created when there is a click in the list view.\r\n// It will filter the actions to identify the ones performed in the card which takes the user to detail page.\r\n// filters the clicks on lead cta and fav button.\r\nconst manufacturedCommunityCardClicked$ = listViewSectionClicks$.pipe(\r\n filter((event) => event.target.closest(paidManufacturedCommunityCardSelector) ||\r\n event.target.closest(basicManufacturedCommunityCardSelector)),\r\n filter((event) => !event.target.dataset?.leadGeneratorOpener),\r\n filter((event) => !event.target.closest(cardfavoriteButtonSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\n/**\r\n * The triggerCommunityCardClickEvent function is used to track the card Click.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerManufacturedCommunityCardClickEvent = (element) => {\r\n const cardElement = element.closest(paidManufacturedCommunityCardSelector) ||\r\n element.closest(basicManufacturedCommunityCardSelector);\r\n const cardDataset = cardElement.dataset;\r\n const elementName = element.dataset.cardElement;\r\n const cardAreaClicked = segmentAreaClickedPerCardElement[elementName] || segmentAreaClickedPerCardElement.default;\r\n const cardImages = getCardImageUrls(cardElement);\r\n const position = parseInt(cardDataset.index, 10) + 1;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n area_clicked: cardAreaClicked,\r\n image_1_url: cardImages.primaryImage,\r\n image_2_url: cardImages.secondaryImage,\r\n image_3_url: cardImages.terciaryImage,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Selected', customProperties }));\r\n};\r\n\r\nmanufacturedCommunityCardClicked$.subscribe(triggerManufacturedCommunityCardClickEvent);\r\n// ! Home Favorited Event /\r\n\r\n// Identifies if there is a new saved object of a given type and maps it.\r\nconst filterFavoritedByType = (payload, type) => {\r\n const [lastValue, newValue] = payload;\r\n\r\n // this filter, validates if it was an item addition to the existing array, and works with the addedd item\r\n const newFavoritedItems = newValue.filter((item) => !lastValue.includes(item));\r\n if (!newFavoritedItems || newFavoritedItems.length === 0) {\r\n return null;\r\n }\r\n\r\n if (newFavoritedItems[0].type !== type) {\r\n return null;\r\n }\r\n\r\n return newFavoritedItems[0];\r\n};\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPlanPendingFavoritesChanged$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map((payload) => filterFavoritedByType(payload, 'HomePlan')),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonPlanPendingFavoritesChanged$.subscribe(triggerPlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onSpecPendingFavoritesChanged$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map((payload) => filterFavoritedByType(payload, 'HomeSpec')),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonSpecPendingFavoritesChanged$.subscribe(triggerSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicPlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicPlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_paid: false,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicPlanPendingFavoritesChanged$.subscribe(triggerBasicPlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n spec_id: cardDataset.specId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_paid: false,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicSpecPendingFavoritesChanged$.subscribe(triggerBasicSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidBuildOnYourLotPlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidBOYLPlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidBuildOnYourLotPlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-boyl-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n is_paid: true,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonPaidBuildOnYourLotPlanPendingFavoritesChanged$.subscribe(triggerPaidBuildOnYourLotPlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidBuildOnYourLotSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidBOYLSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidBuildOnYourLotSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-boyl-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n is_paid: true,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonPaidBuildOnYourLotSpecPendingFavoritesChanged$.subscribe(triggerPaidBuildOnYourLotSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidCustomHomePlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomHomePlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidCustomHomePlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-custom-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n is_paid: true,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonPaidCustomHomePlanPendingFavoritesChanged$.subscribe(triggerPaidCustomHomePlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidCustomHomeSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomHomeSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidCustomHomeSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-custom-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n is_paid: true,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonPaidCustomHomeSpecPendingFavoritesChanged$.subscribe(triggerPaidCustomHomeSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicBuildOnYourLotPlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidBOYLPlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicBuildOnYourLotPlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-boyl-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicBuildOnYourLotPlanPendingFavoritesChanged$.subscribe(triggerBasicBuildOnYourLotPlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicBuildOnYourLotSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidBOYLSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicBuildOnYourLotSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-boyl-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicBuildOnYourLotSpecPendingFavoritesChanged$.subscribe(triggerBasicBuildOnYourLotSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicCustomHomePlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomHomePlanFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicCustomHomePlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-custom-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicCustomHomePlanPendingFavoritesChanged$.subscribe(triggerBasicCustomHomePlanFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicCustomHomeSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomHomeSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicCustomHomeSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-custom-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n is_paid: false,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nonBasicCustomHomeSpecPendingFavoritesChanged$.subscribe(triggerBasicCustomHomeSpecFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst manufacturedHomeSpecPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Spec.toString())),\r\n filter(Boolean)\r\n);\r\nconst manufacturedHomePlanPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Plan.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomHomeSpecFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerManufacturedHomePlanFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const itemType = payload.listingInformation.isBasic !== 'true'\r\n ? 'paid' : 'basic';\r\n\r\n const cardElement = document.querySelector(`[data-${itemType}-manufactured-plan][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n plan_id: cardDataset.planId,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nconst triggerManufacturedHomeSpecFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const itemType = payload.listingInformation.isBasic !== 'true'\r\n ? 'paid' : 'basic';\r\n\r\n const cardElement = document.querySelector(`[data-${itemType}-manufactured-spec][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n spec_id: cardDataset.specId,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Favorited', customProperties }));\r\n};\r\n\r\nmanufacturedHomeSpecPendingFavoritesChanged$.subscribe(triggerManufacturedHomeSpecFavoritedEvent);\r\nmanufacturedHomePlanPendingFavoritesChanged$.subscribe(triggerManufacturedHomePlanFavoritedEvent);\r\n\r\n// ! Community Favorited Event.\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidCustomLocationPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Community.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidCustomLocationFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidCustomLocationFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-custom-location][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n is_paid: true,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nonPaidCustomLocationPendingFavoritesChanged$.subscribe(triggerPaidCustomLocationFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onPaidBuildOnYourLotLocationPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Community.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerPaidBOYLLocationFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerPaidBuildOnYourLotLocationFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-paid-boyl-location][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n is_paid: true,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nonPaidBuildOnYourLotLocationPendingFavoritesChanged$.subscribe(triggerPaidBuildOnYourLotLocationFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicCustomLocationPendingFavoritesChanged$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Community.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerBasicCustomLocationFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicCustomLocationFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-custom-location][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n is_paid: false,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nonBasicCustomLocationPendingFavoritesChanged$.subscribe(triggerBasicCustomLocationFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst onBasicBuildOnYourLotLocationPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Community.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerBasicBOYLLocationFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerBasicBuildOnYourLotLocationFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const cardElement = document.querySelector(`[data-basic-boyl-location][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n is_paid: false,\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nonBasicBuildOnYourLotLocationPendingFavoritesChanged$.subscribe(triggerBasicBuildOnYourLotLocationFavoritedEvent);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved.\r\n// It will filter the actions to now when it changes.\r\nconst manufacturedCommunityPendingFavoritesChanged$ = pendingListingSavesFavorites$.pipe(\r\n map((payload) => filterFavoritedByType(payload, FavoriteType.Community.toString())),\r\n filter(Boolean)\r\n);\r\n\r\n/**\r\n * The triggerBasicBOYLLocationFavoritedEvent function is used to track the favorited event.\r\n * which happens when the user clicks in the fav button to save it.\r\n * This will gather the custom properties and dispatch the segment event\r\n * @param action Get the target element of the event\r\n *\r\n */\r\nconst triggerManufacturedCommunityFavoritedEvent = (payload) => {\r\n const itemId = payload.listingInformation.id;\r\n const itemType = payload.listingInformation.isBasic !== 'true'\r\n ? 'paid' : 'basic';\r\n const cardElement = document.querySelector(`[data-${itemType}-manufactured-location][data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n is_paid: cardDataset.isBasic !== 'true',\r\n plan_id: cardDataset.planId,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Favorited', customProperties }));\r\n};\r\n\r\nmanufacturedCommunityPendingFavoritesChanged$.subscribe(triggerManufacturedCommunityFavoritedEvent);\r\n\r\n/**\r\n * triggerCommunitySavedEvent: Triggers the event related when the favorite listing was already saved.\r\n * IMPORTANT: This event is not when the user clicks on the Favorite button, but when the listing was succesfully saved\r\n * on the server.\r\n * @param {Object} favoriteInformation Information related to the favorite.\r\n */\r\nfunction triggerPaidCommunitySavedEvent(favoriteInformation) {\r\n const { listingInformation } = favoriteInformation;\r\n const isPaid = listingInformation.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n community_id: listingInformation.id,\r\n community_name: listingInformation.name,\r\n community_status: listingInformation.marketingStatusLabel,\r\n primary_image_url: listingInformation.imageUrl,\r\n community_low_price: listingInformation.priceLow,\r\n community_high_price: listingInformation.priceHigh,\r\n city: listingInformation.city,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n is_paid: isPaid,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Saved', customProperties }));\r\n}\r\n\r\nconst newCommunityListingSaved$ = newListingSaved$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === FavoriteType.Community.toString())\r\n);\r\n\r\nnewCommunityListingSaved$.subscribe(triggerPaidCommunitySavedEvent);\r\n\r\n/**\r\n * triggerPaidSpecSavedEvent: Triggers the event related when the favorite paid spec listing was already saved.\r\n * IMPORTANT: This event is not when the user clicks on the Favorite button, but when the listing was succesfully saved\r\n * on the server.\r\n * @param {Object} favoriteInformation Information related to the favorite.\r\n */\r\nfunction triggerPaidSpecSavedEvent(favoriteInformation) {\r\n const { listingInformation } = favoriteInformation;\r\n const isPaid = listingInformation.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n community_id: listingInformation.communityId,\r\n community_name: listingInformation.communityName,\r\n primary_image_url: listingInformation.imageUrl,\r\n home_type: listingInformation.homeStatus,\r\n home_price: listingInformation.price,\r\n spec_id: listingInformation.id,\r\n city: listingInformation.city,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n is_paid: isPaid,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Saved', customProperties }));\r\n}\r\n\r\nconst newPaidSpecListingSaved$ = newListingSaved$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === FavoriteType.Spec.toString())\r\n);\r\n\r\nnewPaidSpecListingSaved$.subscribe(triggerPaidSpecSavedEvent);\r\n\r\n/**\r\n * triggerPaidPlanSavedEvent: Triggers the event related when the favorite paid plan listing was already saved.\r\n * IMPORTANT: This event is not when the user clicks on the Favorite button, but when the listing was succesfully saved\r\n * on the server.\r\n * @param {Object} favoriteInformation Information related to the favorite.\r\n */\r\nfunction triggerPaidPlanSavedEvent(favoriteInformation) {\r\n const { listingInformation } = favoriteInformation;\r\n const isPaid = listingInformation.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n community_id: listingInformation.communityId,\r\n community_name: listingInformation.communityName,\r\n primary_image_url: listingInformation.imageUrl,\r\n home_type: listingInformation.homeStatus,\r\n home_price: listingInformation.price,\r\n plan_id: listingInformation.id,\r\n city: listingInformation.city,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n is_paid: isPaid,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Saved', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the related event when a community has already been removed from the list of favorite communities.\r\n * @param {any} favoriteInformation Information about the removed card.\r\n */\r\nfunction triggerCommunityRemovedEvent(favoriteInformation) {\r\n const itemId = favoriteInformation.listingId;\r\n const cardElement = document.querySelector(`[data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n const isPaid = cardDataset.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.name,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: primaryImageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n is_paid: isPaid,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Removed', customProperties }));\r\n}\r\n\r\nconst removedCommunity$ = removedFavorites$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === FavoriteType.Community.toString())\r\n);\r\n\r\nremovedCommunity$.subscribe(triggerCommunityRemovedEvent);\r\n\r\n/**\r\n * Triggers the related event when a home has already been removed from the list of favorite communities.\r\n * @param {any} favoriteInformation Information about the removed card.\r\n */\r\nfunction triggerHomeRemovedEvent(favoriteInformation) {\r\n const itemId = favoriteInformation.listingId;\r\n const cardElement = document.querySelector(`[data-id=\"${itemId}\"]`);\r\n\r\n if (!cardElement) {\r\n return;\r\n }\r\n const cardDataset = cardElement.dataset;\r\n const primaryImageUrl =\r\n cardDataset.imageUrl !== '' ? cardDataset.imageUrl : getCardImageUrls(cardElement).primaryImage;\r\n const isPaid = cardDataset.isBasic !== 'true';\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: primaryImageUrl,\r\n home_type: cardDataset.homeStatus,\r\n home_price: cardDataset.price,\r\n plan_id: cardDataset.planId,\r\n spec_id: cardDataset.specId,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n is_paid: isPaid,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Removed', customProperties }));\r\n}\r\n\r\nconst removedSpecHome$ = removedFavorites$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === 'Spec')\r\n);\r\nconst removedPlanHome$ = removedFavorites$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === 'Plan')\r\n);\r\n\r\nremovedSpecHome$.subscribe(triggerHomeRemovedEvent);\r\nremovedPlanHome$.subscribe(triggerHomeRemovedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_high_price: marker.PriceHigh,\r\n community_low_price: marker.PriceLow,\r\n community_id: marker.Id,\r\n community_name: marker.Name,\r\n community_status: marker.MarketingStatus.Name,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n page_type: 'Community_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Map Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n *\r\n * @param {Object} marker - The marker object.\r\n */\r\nmarkerSummaryCardClicked$\r\n .pipe(\r\n filter((nearbyListings) => Boolean(nearbyListings?.length)),\r\n map(nearbyListings => nearbyListings[0]),\r\n filter(\r\n (marker) => marker.Type === MarkerType.HousingDevelopment.toString()\r\n ),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(triggerCommunityMapMarkerClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for home markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n market_name: `${marker.MarketName},${marker.StateAbbreviation}`,\r\n page_type: 'Homes_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n plan_id: marker.Id,\r\n home_price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Map Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for plan unit markers.\r\n *\r\n * @param {Object} marker - The marker object.\r\n */\r\nmarkerSummaryCardClicked$\r\n .pipe(\r\n filter((nearbyListings) => Boolean(nearbyListings?.length)),\r\n map(nearbyListings => nearbyListings[0]),\r\n filter((marker) => marker.Type === MarkerType.PlanUnit.toString()),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(triggerPlanMapMarkerClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for home markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecMapMarkerClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n market_name: `${marker.MarketName},${marker.StateAbbreviation}`,\r\n page_type: 'Homes_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n spec_id: marker.Id,\r\n home_price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Map Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for spec unit markers.\r\n *\r\n * @param {Object} marker - The marker object.\r\n */\r\nmarkerSummaryCardClicked$\r\n .pipe(\r\n filter((nearbyListings) => Boolean(nearbyListings?.length)),\r\n map(nearbyListings => nearbyListings[0]),\r\n filter((marker) => marker.Type === MarkerType.SpecUnit.toString()),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(triggerSpecMapMarkerClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunitySummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_high_price: marker.PriceHigh,\r\n community_low_price: marker.PriceLow,\r\n community_id: marker.Id,\r\n community_name: marker.Name,\r\n community_status: marker.MarketingStatus.Name,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n page_type: 'Community_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Map Selected', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map marker clicked event for community summary cards.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.HousingDevelopment.toString())\r\n).subscribe(triggerCommunitySummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for home markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanSummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n market_name: `${marker.MarketName},${marker.StateAbbreviation}`,\r\n page_type: 'Homes_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n plan_id: marker.Id,\r\n home_price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Map Selected', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map card link event for plan summary cards.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.PlanUnit.toString())\r\n).subscribe(triggerPlanSummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Triggers the map card link clicked event for spec markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecSummaryCardLinkClickedEvent(marker) {\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_id: marker.CommunityId,\r\n community_name: marker.CommunityName,\r\n image_1_url: marker.Images[0]?.Srcset,\r\n is_zero_results: isNotResultPage(),\r\n market_name: `${marker.MarketName},${marker.StateAbbreviation}`,\r\n page_type: 'Homes_Results',\r\n primary_image_url: marker.Images[0]?.Srcset,\r\n spec_id: marker.Id,\r\n home_price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Map Selected', customProperties }));\r\n}\r\n\r\n/**\r\n * Triggers the map card link clicked event for spec summary cards.\r\n */\r\nsummaryCardLinkClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.Type === MarkerType.SpecUnit.toString())\r\n).subscribe(triggerSpecSummaryCardLinkClickedEvent);\r\n\r\n/**\r\n * Triggers the community map card CTA clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunitySummaryCardCallToActionClickEvent(detail) {\r\n const { marker } = detail;\r\n \r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n brand_name: marker.brandName,\r\n id: marker.Id,\r\n name: marker.Name,\r\n type: 'community',\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n}\r\n\r\n/**\r\n * Triggers the map card CTA clicked event for community summary cards.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.HousingDevelopment.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerCommunitySummaryCardCallToActionClickEvent);\r\n\r\n/**\r\n * Triggers the community map card CTA clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanSummaryCardCallToActionClickEvent(detail) {\r\n const { marker } = detail;\r\n \r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n brand_name: marker.brandName,\r\n id: marker.Id,\r\n name: marker.Name,\r\n type: 'plan',\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n}\r\n/**\r\n * Triggers the plan map card CTA clicked event.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.PlanUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerPlanSummaryCardCallToActionClickEvent);\r\n\r\n/**\r\n * Triggers the community map card CTA clicked event.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecSummaryCardCallToActionClickEvent(detail) {\r\n const { marker } = detail;\r\n \r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n brand_name: marker.brandName,\r\n id: marker.Id,\r\n name: marker.Name,\r\n type: 'spec',\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n is_spotlight: !!marker.IsFeaturedListing,\r\n community_type: marker.CommunityProjectType.Key,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'Lead Button Clicked', customProperties })), 0);\r\n}\r\n\r\n/**\r\n * Triggers the spec map card CTA clicked event.\r\n */\r\nsummaryCardCtaClicked$.pipe(\r\n filter((detail) => Boolean(detail.marker)),\r\n filter((detail) => detail.marker.Type === MarkerType.SpecUnit.toString()),\r\n distinctUntilChanged(),\r\n).subscribe(triggerSpecSummaryCardCallToActionClickEvent);\r\n\r\nconst newPaidPlanListingSaved$ = newListingSaved$.pipe(\r\n filter((favoritedInformation) => favoritedInformation.type === FavoriteType.Plan.toString())\r\n);\r\n\r\nnewPaidPlanListingSaved$.subscribe(triggerPaidPlanSavedEvent);\r\n\r\nconst sortChanged$ = store$.pipe(map(selectSorting), distinctUntilChanged(), skip(1));\r\n\r\nconst sortSelectElement = document.querySelector('[data-sort-select]');\r\n\r\n/**\r\n * getSortingLabel: Gets the label to be used on the sort value on Segment events.\r\n * @param {object} sortingInformation Information related to sorting.\r\n * @returns The label to be used related to the sort value.\r\n */\r\nfunction getSortingLabel(sortingInformation) {\r\n const sortingValue = `${sortingInformation?.sortBy},${sortingInformation?.sortOrder}`;\r\n const sortingOption = sortSelectElement.querySelector(`[value=\"${sortingValue}\"]`);\r\n return sortingOption?.textContent;\r\n}\r\n\r\n/**\r\n * trackResultsSortedEvent: Tracks the sorted event for the searches.\r\n * @param {object} sorting Information related to the sort parameters.\r\n */\r\nfunction trackResultsSortedEvent(sorting) {\r\n const customProperties = {\r\n sort_value: getSortingLabel(sorting),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Results Sorted', customProperties }));\r\n}\r\n\r\nsortChanged$.subscribe(trackResultsSortedEvent);\r\n\r\n// #endregion List View Section\r\n\r\n// #region TabSelect\r\nconst homesSelector = '[data-product-type=\"homes\"]';\r\nconst communitiesSelector = '[data-product-type=\"communities\"]';\r\n\r\nconst tabsContainer = document.querySelector('[data-result-type-bar]');\r\nconst tabsContainerClicks$ = fromEvent(tabsContainer, 'click');\r\n\r\nconst homesButtonClicks$ = tabsContainerClicks$.pipe(\r\n filter((event) => event.target.closest(homesSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nconst communitiesButtonClicks$ = tabsContainerClicks$.pipe(\r\n filter((event) => event.target.closest(communitiesSelector)),\r\n map((event) => event.target)\r\n);\r\n\r\nconst triggerHomesTabClickEvent = () => {\r\n const customProperties = {\r\n page_type: PageType.Homes.toString(),\r\n};\r\n store.dispatch(segmentTrack({ eventName: 'View Homes Clicked', customProperties }));\r\n};\r\n\r\nhomesButtonClicks$.subscribe(triggerHomesTabClickEvent);\r\n\r\nconst triggerCommunitiesTabClickEvent = () => {\r\n const customProperties = {\r\n page_type: PageType.Communities.toString(),\r\n};\r\n store.dispatch(segmentTrack({ eventName: 'View Communities Clicked', customProperties }));\r\n};\r\n\r\ncommunitiesButtonClicks$.subscribe(triggerCommunitiesTabClickEvent);\r\n\r\n// #end region TabSelect\r\n\r\n// #region Pageview\r\n/**\r\n * ! When URL change, dispatch a pageview\r\n */\r\nconst triggerPageViewEvent = () => store.dispatch(segmentPageView({}));\r\nconst onUrlChange$ = store$.pipe(map(selectCurrentUrl), filter(Boolean), distinctUntilChanged());\r\n\r\n/**\r\n * Observable checking the changes in the Hounsing content.\r\n */\r\nconst onHousingProductLocationFetchStatus$ = store$.pipe(\r\n map(selectHousingProductLocationFetchStatus),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * Observable checking the changes in the listing counts selector, \r\n * checks if the ajax request is succes and the gets the counts value.\r\n */\r\nconst countsChange$ = store$.pipe(\r\n map(selectFetchCountsStatusAndsCounts),\r\n distinctUntilKeyChanged('resultCountsStatus'));\r\n\r\n/**\r\n * Observable checking the URL changes, the Housing product content change and the counts change\r\n * in order to trigger the segment page view is the counts are greater than 0.\r\n */\r\ncombineLatest([onUrlChange$, onHousingProductLocationFetchStatus$, countsChange$])\r\n .pipe(\r\n map(([currentUrl, housingProductFetchStatus, counts]) => ({currentUrl, housingProductFetchStatus, counts})),\r\n filter(({counts}) => counts.resultCountsStatus !== LoadingStatus.Loading),\r\n filter(({housingProductFetchStatus}) => housingProductFetchStatus !== LoadingStatus.Loading),\r\n filter(({counts}) => counts.listingCounts > 0))\r\n .subscribe(triggerPageViewEvent);\r\n\r\nconst triggerPageViewNoResultEvent = () => store.dispatch(segmentPageView(\r\n { customProperties: { is_zero_results: true } }));\r\n\r\n/**\r\n* Observable checking the counts and the Housing product content change\r\n* in order to trigger the No results page view.\r\n*/\r\ncombineLatest([countsChange$, onHousingProductLocationFetchStatus$])\r\n .pipe(filter(([, housingProductStatus ]) => housingProductStatus !== LoadingStatus.Loading),\r\n filter(([counts]) => counts.resultCountsStatus !== LoadingStatus.Loading),\r\n filter(([counts]) => counts.listingCounts === 0))\r\n .subscribe(triggerPageViewNoResultEvent);\r\n\r\n/**\r\n* trackRealtorQuestionAnswerEvent: Tracks the sorted event for the realtor dropdown.\r\n*/\r\nfunction getRealtorQuestionAnswerText() {\r\n const realtorSelect = document.querySelector('[name=\"realtorQuestion\"]');\r\n let realtorQuestionAnswer = '';\r\n if (realtorSelect && realtorSelect.selectedIndex > 0) {\r\n realtorQuestionAnswer = realtorSelect.options[realtorSelect.selectedIndex].text;\r\n }\r\n return realtorQuestionAnswer;\r\n}\r\n\r\n// #region\r\n\r\n// #region Brochure Modal\r\n/**\r\n * ! Brochure Modal Section\r\n * All events related elements located in brochure modal should be placed in this region\r\n */\r\n\r\n/**\r\n * triggerPaidCommunityModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Free Brochure\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerPaidCommunityModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n\r\n const customProperties = {\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n community_id: listingInformation.id,\r\n community_name: listingInformation.communityName,\r\n community_status: listingInformation.marketingStatusLabel,\r\n primary_image_url: listingInformation.imageUrl,\r\n community_low_price: listingInformation.priceLow,\r\n community_high_price: listingInformation.priceHigh,\r\n city: listingInformation.city,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n button_action: modalInformation.buttonAction,\r\n is_paid: true,\r\n is_spotlight: !!listingInformation.isFeaturedListing,\r\n community_type: listingInformation.communityType,\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Lead Modal Form Submitted', customProperties }));\r\n}\r\n\r\npaidCommunityModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\npaidManufacturedLocationModalSubmission$.subscribe(triggerPaidCommunityModalSubmitted);\r\n/**\r\n * triggerBasicCommunityModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicCommunityModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const customProperties = {\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n community_id: listingInformation.id,\r\n community_name: listingInformation.communityName,\r\n community_status: listingInformation.marketingStatusLabel,\r\n primary_image_url: listingInformation.imageUrl,\r\n community_low_price: listingInformation.priceLow,\r\n community_high_price: listingInformation.priceHigh,\r\n city: listingInformation.city,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n button_action: modalInformation.buttonAction,\r\n is_paid: false,\r\n is_spotlight: !!listingInformation.isFeaturedListing,\r\n community_type: listingInformation.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Lead Modal Form Submitted', customProperties }));\r\n}\r\n\r\nbasicCommunityModalSubmission$.subscribe(triggerBasicCommunityModalSubmitted);\r\n\r\n\r\n/**\r\n * Triggers the events for the recommended communities that were selected.\r\n * @param {Object} modalInformation Information related to the modal.\r\n */\r\nfunction triggerRecommendedCommunitySubmittedEvents(modalInformation) {\r\n const { selectedRecommendedCommunities, buttonAction } = modalInformation;\r\n selectedRecommendedCommunities.forEach((community) => {\r\n const customProperties = {\r\n market_id: community.MarketId,\r\n market_name: `${community.MarketName}, ${community.StateAbbreviation}`,\r\n builder_id: community.BuilderId,\r\n builder_name: community.BrandName,\r\n community_id: community.CommunityId,\r\n community_name: community.CommunityName,\r\n community_status: community.MarketingStatusLabel,\r\n primary_image_url: community.ImageUrl,\r\n community_low_price: community.PriceLow,\r\n community_high_price: community.PriceHigh,\r\n city: community.City,\r\n state: community.StateAbbreviation,\r\n zip: community.Zip,\r\n button_action: buttonAction,\r\n is_paid: !community.isBasic,\r\n is_spotlight: !!community.isFeaturedListing,\r\n community_type: community.CommunityProjectType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Rec Community Lead Modal Submitted', customProperties }));\r\n });\r\n}\r\n\r\nrecommendedCommunitiesSubmitted$.subscribe(triggerRecommendedCommunitySubmittedEvents);\r\nrecommendedCommunitiesSubmittedBasic$.subscribe(triggerRecommendedCommunitySubmittedEvents);\r\n\r\n/**\r\n * triggerPaidHomeModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Free Brochure\r\n * - Get More Information\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerPaidHomeModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const customProperties = {\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n button_action: modalInformation.buttonAction,\r\n city: listingInformation.city,\r\n community_id: listingInformation.communityId,\r\n community_name: listingInformation.communityName,\r\n home_price: listingInformation.price,\r\n home_type: listingInformation.homeStatus,\r\n is_paid: true,\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n plan_id: listingInformation.planId,\r\n primary_image_url: listingInformation.imageUrl,\r\n state: listingInformation.stateAbbreviation,\r\n spec_id: listingInformation.specId,\r\n zip: listingInformation.zip,\r\n is_spotlight: !!listingInformation.isFeaturedListing,\r\n community_type: listingInformation.communityType,\r\n realtor_question: getRealtorQuestionAnswerText(),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Lead Modal Form Submitted', customProperties }));\r\n}\r\n\r\npaidHomeModalSubmission$.subscribe(triggerPaidHomeModalSubmitted);\r\npaidManufacturedPlanModalSubmission$.subscribe(triggerPaidHomeModalSubmitted);\r\npaidManufacturedSpecModalSubmission$.subscribe(triggerPaidHomeModalSubmitted);\r\n\r\n/**\r\n * triggerBasicHomeModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicHomeModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const customProperties = {\r\n builder_id: listingInformation.builderId,\r\n builder_name: listingInformation.brandName,\r\n button_action: modalInformation.buttonAction,\r\n city: listingInformation.city,\r\n community_id: listingInformation.communityId,\r\n community_name: listingInformation.communityName,\r\n home_price: listingInformation.price,\r\n home_type: listingInformation.homeStatus,\r\n is_paid: false,\r\n listing_id: listingInformation.listingId,\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n plan_id: listingInformation.planId,\r\n primary_image_url: listingInformation.imageUrl,\r\n state: listingInformation.stateAbbreviation,\r\n spec_id: listingInformation.specId,\r\n zip: listingInformation.zip,\r\n is_spotlight: !!listingInformation.isFeaturedListing,\r\n community_type: listingInformation.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Lead Modal Form Submitted', customProperties }));\r\n}\r\n\r\nbasicPlanModalSubmission$.subscribe(triggerBasicHomeModalSubmitted);\r\nbasicSpecModalSubmission$.subscribe(triggerBasicHomeModalSubmitted);\r\n\r\n/**\r\n * triggerBasicListingModalSubmitted: Triggers the event when the modal form is submitted.\r\n * This event only applies for the following forms:\r\n * - Learn More\r\n * @param {object} modalInformation The information related to the modal opened.\r\n */\r\nfunction triggerBasicListingModalSubmitted(modalInformation) {\r\n const { listingInformation } = modalInformation;\r\n const customProperties = {\r\n button_action: modalInformation.buttonAction,\r\n city: listingInformation.city,\r\n community_id: listingInformation.communityId,\r\n community_name: listingInformation.communityName,\r\n home_price: listingInformation.price,\r\n is_paid: false,\r\n listing_id: listingInformation.id,\r\n market_id: listingInformation.marketId,\r\n market_name: `${listingInformation.marketName}, ${listingInformation.stateAbbreviation}`,\r\n primary_image_url: listingInformation.imageUrl,\r\n state: listingInformation.stateAbbreviation,\r\n zip: listingInformation.zip,\r\n is_spotlight: !!listingInformation.isFeaturedListing,\r\n community_type: listingInformation.communityType,\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Lead Modal Form Submitted', customProperties }));\r\n}\r\n\r\nbasicListingModalSubmission$.subscribe(triggerBasicListingModalSubmitted);\r\n\r\n// #endregion Brochure Modal\r\n\r\n// #region\r\n\r\n/**\r\n * ! IDENTIFY EVENTS\r\n */\r\n\r\nconst triggerIdentifySavedCommunity = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Community Saved' }));\r\n};\r\n\r\nnewCommunityListingSaved$.subscribe(triggerIdentifySavedCommunity);\r\n\r\nconst triggerIdentifyCommunityModalSubmission = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Lead Modal Form Submitted' }));\r\n};\r\n\r\npaidCommunityModalSubmission$.subscribe(triggerIdentifyCommunityModalSubmission);\r\npaidManufacturedLocationModalSubmission$.subscribe(triggerIdentifyCommunityModalSubmission);\r\nbasicCommunityModalSubmission$.subscribe(triggerIdentifyCommunityModalSubmission);\r\n\r\nconst triggerIdentifySavedSpec = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Home Saved' }));\r\n};\r\n\r\nnewPaidSpecListingSaved$.subscribe(triggerIdentifySavedSpec);\r\n\r\nconst triggerIdentifySavedPlan = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Home Saved' }));\r\n};\r\n\r\nnewPaidPlanListingSaved$.subscribe(triggerIdentifySavedPlan);\r\n\r\nconst triggerIdentifyHomeModalSubmission = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Lead Modal Form Submitted' }));\r\n};\r\n\r\npaidHomeModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\npaidManufacturedPlanModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\npaidManufacturedSpecModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\nbasicPlanModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\nbasicSpecModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\nbasicListingModalSubmission$.subscribe(triggerIdentifyHomeModalSubmission);\r\n\r\nconst triggerIdentifyRemovedCommunityFavorite = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Community Removed' }));\r\n};\r\n\r\nremovedCommunity$.subscribe(triggerIdentifyRemovedCommunityFavorite);\r\n\r\nconst triggerIdentifyRemovedHomeFavorite = () => {\r\n store.dispatch(segmentIdentify({ eventName: 'Home Removed' }));\r\n};\r\n\r\nremovedSpecHome$.subscribe(triggerIdentifyRemovedHomeFavorite);\r\nremovedPlanHome$.subscribe(triggerIdentifyRemovedHomeFavorite);\r\n\r\n/**\r\n * Returns if the listing is price reduction or not.\r\n * \r\n * @param {string} priceReductionLabel - The price reduction label.\r\n */\r\nconst isPriceReduction = (priceReductionLabel) => priceReductionLabel === \"Y\";\r\n\r\n/**\r\n * Triggers the map marker clicked event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityMapMarkerUrlOpenedEvent(data) {\r\n const { marker } = data;\r\n\r\n const customProperties = {\r\n id: marker.id,\r\n name: marker.metaData.communityName,\r\n type: 'community',\r\n price: marker.metaData.priceLow,\r\n is_paid: marker.metaData.isPaid,\r\n price_reduction: isPriceReduction(marker.metaData.priceReducedTrackingLabel),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Community Result Pin Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `markerUrlOpened$` observable and fires a segment event when triggered.\r\n */\r\nmarkerUrlOpened$.pipe(\r\n filter(data => Boolean(data?.marker?.id)),\r\n filter(data => data?.marker?.type === MarkerType.HousingDevelopment.toString()),\r\n).subscribe(triggerCommunityMapMarkerUrlOpenedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for home markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanMapMarkerUrlOpenedEvent(data) {\r\n const { marker } = data;\r\n\r\n const customProperties = {\r\n id: marker.id,\r\n type: 'plan',\r\n price: marker.metaData.priceLow,\r\n is_paid: marker.metaData.isPaid,\r\n price_reduction: isPriceReduction(marker.metaData.priceReducedTrackingLabel),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Pin Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `markerUrlOpened$` observable and fires a segment event when triggered.\r\n */\r\nmarkerUrlOpened$.pipe(\r\n filter(data => Boolean(data?.marker?.id)),\r\n filter(data => data?.marker?.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanMapMarkerUrlOpenedEvent);\r\n\r\n/**\r\n * Triggers the map marker clicked event for home markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecMapMarkerUrlOpenedEvent(data) {\r\n const { marker } = data;\r\n\r\n const customProperties = {\r\n id: marker.id,\r\n type: 'spec',\r\n price: marker.metaData.priceLow,\r\n is_paid: marker.metaData.isPaid,\r\n price_reduction: isPriceReduction(marker.metaData.priceReducedTrackingLabel),\r\n };\r\n\r\n store.dispatch(segmentTrack({ eventName: 'Home Result Pin Displayed', customProperties }));\r\n}\r\n\r\n/**\r\n * Subscribes to the `markerUrlOpened$` observable and fires a segment event when triggered.\r\n */\r\nmarkerUrlOpened$\r\n .pipe(\r\n filter((data) => Boolean(data?.marker?.id)),\r\n filter((data) => data?.marker?.type === MarkerType.SpecUnit.toString()),\r\n )\r\n .subscribe(triggerSpecMapMarkerUrlOpenedEvent);\r\n\r\n// #endregion\r\n\r\n// #region\r\n/**\r\n * ! IMPRESSION EVENTS\r\n */\r\n/**\r\n * getPaidCommunityListingCards: Gets the list of current paid community listing cards.\r\n * @returns A HTML Node list of current paid community cards.\r\n */\r\nconst getPaidCommunityListingCards = () => listViewSection.querySelectorAll(paidCommunityCardSelector);\r\n/**\r\n * getPaidManufacturedCommunityListingCards: Gets the list of current paid community listing cards.\r\n * @returns A HTML Node list of current paid community cards.\r\n */\r\nconst getPaidManufacturedCommunityListingCards = () =>\r\n listViewSection.querySelectorAll(paidManufacturedCommunityCardSelector);\r\n\r\n/**\r\n* getBasicCustomCommunityListingCards: Gets the list of current basic community listing cards.\r\n* @returns A HTML Node list of current basic community cards.\r\n*/\r\nconst getPaidCustomCommunityListingCards = () =>\r\n listViewSection.querySelectorAll(`${paidCustomCommunityCardSelector}, ${paidBuildOnYourLotCommunityCardSelector}`);\r\n/**\r\n * isAutoScroll: Gets the selector for the map marker to know if the Auto Scroll functionality is available.\r\n * @returns A bool to determine if it is auto scroll or not.\r\n */\r\nconst isAutoScroll = () => {\r\n const state = store.getState();\r\n\r\n const selectedMarkerInformation = selectSelectedMarker(state);\r\n\r\n if (!selectedMarkerInformation) {\r\n return false;\r\n }\r\n\r\n const {marker, resultType } = selectedMarkerInformation;\r\n\r\n return marker && resultType === ResultType.Communities.toString();\r\n};\r\n\r\n/**\r\n * triggerPaidCommunityResultsDisplayedEvent: Triggers the Community Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerPaidCommunityResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n image_1_url: cardDataset.imageUrl,\r\n image_2_url: cardDataset.secondaryImageUrl,\r\n image_3_url: cardDataset.tertiaryImageUrl,\r\n is_zero_results: isNotResultPage(),\r\n is_auto_scroll: isAutoScroll(),\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType\r\n };\r\n store.dispatch(segmentImpression({ eventName: 'Community Result Displayed', customProperties }));\r\n};\r\nconst paidCommunityResultsDisplayedEventObserver = new ImpressionEventObserver(\r\n triggerPaidCommunityResultsDisplayedEvent\r\n);\r\n\r\n/**\r\n * getBasicCommunityListingCards: Gets the list of current basic community listing cards.\r\n * @returns A HTML Node list of current basic community cards.\r\n */\r\nconst getBasicCommunityListingCards = () => listViewSection.querySelectorAll(basicCommunityCardSelector);\r\n/**\r\n * getBasicManufacturedCommunityListingCards: Gets the list of current basic community listing cards.\r\n * @returns A HTML Node list of current basic community cards.\r\n */\r\nconst getBasicManufacturedCommunityListingCards = () =>\r\n listViewSection.querySelectorAll(basicManufacturedCommunityCardSelector);\r\n/**\r\n* getBasicCustomCommunityListingCards: Gets the list of current basic community listing cards.\r\n* @returns A HTML Node list of current basic community cards.\r\n*/\r\nconst getBasicCustomCommunityListingCards = () =>\r\n listViewSection.querySelectorAll(`${basicCustomCommunityCardSelector}, ${basicBuildOnYourLotCommunityCardSelector}`);\r\n/**\r\n * triggerBasicCommunityResultsDisplayedEvent: Triggers the Community Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerBasicCommunityResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n is_paid: false,\r\n image_1_url: cardDataset.imageUrl,\r\n image_2_url: cardDataset.secondaryImageUrl,\r\n image_3_url: cardDataset.tertiaryImageUrl,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n is_zero_results: isNotResultPage(),\r\n is_auto_scroll: isAutoScroll(),\r\n };\r\n store.dispatch(segmentImpression({ eventName: 'Community Result Displayed', customProperties }));\r\n};\r\n\r\nconst basicCommunityResultsDisplayedEventObserver = new ImpressionEventObserver(\r\n triggerBasicCommunityResultsDisplayedEvent\r\n);\r\n\r\n/**\r\n * bindBasicCommunityResultsDisplayedEvents: Observe each card to check when some card is viewed.\r\n */\r\nconst bindBasicCommunityResultsDisplayedEvents = () => {\r\n const basicCommunityListingCards = getBasicCommunityListingCards();\r\n const basicManufacturedCommunityListingCards = getBasicManufacturedCommunityListingCards();\r\n const basicCustomCommunityListingCards = getBasicCustomCommunityListingCards();\r\n const basicCommunitiesListings = [\r\n ...basicCommunityListingCards,\r\n ...basicManufacturedCommunityListingCards,\r\n ...basicCustomCommunityListingCards\r\n ];\r\n const basicCommunityContainerObserver = basicCommunityResultsDisplayedEventObserver.getIntersectionObserver();\r\n basicCommunitiesListings.forEach((card) => basicCommunityContainerObserver.observe(card));\r\n};\r\n\r\n/**\r\n * getBasicSpecListingCards: Gets the list of current basic spec cards.\r\n * @returns A HTML Node list of current basic spec cards.\r\n */\r\nconst getBasicSpecListingCards = () => listViewSection.querySelectorAll(basicSpecCardSelector);\r\n/**\r\n * getBasicManufacturedSpecListingCards: Gets the list of current basic manufactured spec cards.\r\n * @returns A HTML Node list of current basic manufactured spec cards.\r\n */\r\nconst getBasicManufacturedSpecListingCards = () => listViewSection.querySelectorAll(basicManufacturedSpecCardSelector);\r\n/**\r\n * getBasicCustomSpecListingCards: Gets the list of current basic custom spec cards.\r\n * @returns A HTML Node list of current basic custom spec cards.\r\n */\r\nconst getBasicCustomSpecListingCards = () => listViewSection.querySelectorAll(`${basicCustomSpecCardSelector}, ${basicBuildOnYourLotSpecCardSelector}`);\r\n/**\r\n * triggerBasicSpecResultsDisplayedEvent: Triggers the Basic Spec Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerBasicSpecResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n spec_id: cardDataset.specId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardDataset.imageUrl,\r\n position,\r\n is_paid: false,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n image_1_url: cardDataset.imageUrl,\r\n is_zero_results: isNotResultPage(),\r\n }\r\n store.dispatch(segmentImpression({ eventName: 'Home Result Displayed', customProperties }));\r\n};\r\nconst basicSpecListingResultsDisplayedEventObserver = new ImpressionEventObserver(\r\n triggerBasicSpecResultsDisplayedEvent\r\n);\r\n/**\r\n * bindBasicSpecResultsDisplayedEvents: Observe each card to check when some card is viewed.\r\n */\r\nconst bindBasicSpecResultsDisplayedEvents = () => {\r\n const basicSpecListingCards = getBasicSpecListingCards();\r\n const basicManufacturedSpecListingCards = getBasicManufacturedSpecListingCards();\r\n const basicCustomSpecListingCards = getBasicCustomSpecListingCards();\r\n const basicHomesListingCards = [\r\n ...basicSpecListingCards,\r\n ...basicManufacturedSpecListingCards,\r\n ...basicCustomSpecListingCards];\r\n const basicSpecListingContainerObserver = basicSpecListingResultsDisplayedEventObserver.getIntersectionObserver();\r\n basicHomesListingCards.forEach((card) => basicSpecListingContainerObserver.observe(card));\r\n};\r\n/**\r\n * getBasicPlanListingCards: Gets the list of current basic plan cards.\r\n * @returns A HTML Node list of current basic plan cards.\r\n */\r\nconst getBasicPlanListingCards = () => listViewSection.querySelectorAll(basicPlanCardSelector);\r\n/**\r\n * getBasicManufacturedPlanListingCards: Gets the list of current basic manufactured plan cards.\r\n * @returns A HTML Node list of current basic manufactured plan cards.\r\n */\r\nconst getBasicManufacturedPlanListingCards = () => listViewSection.querySelectorAll(basicManufacturedPlanCardSelector);\r\n\r\n/**\r\n * getBasicCustomPlanListingCards: Gets the list of current basic custom plan cards.\r\n * @returns A HTML Node list of current basic custom plan cards.\r\n */\r\nconst getBasicCustomPlanListingCards = () => listViewSection.querySelectorAll(`${basicCustomPlanCardSelector}, ${basicBuildOnYourLotPlanCardSelector}`);\r\n\r\n/**\r\n * triggerBasicPlanResultsDisplayedEvent: Triggers the Basic Plan Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerBasicPlanResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n plan_id: cardDataset.planId,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardDataset.imageUrl,\r\n position,\r\n is_paid: false,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n image_1_url: cardDataset.imageUrl,\r\n is_zero_results: isNotResultPage(),\r\n }\r\n store.dispatch(segmentImpression({ eventName: 'Home Result Displayed', customProperties }));\r\n};\r\nconst basicPlanListingResultsDisplayedEventObserver = new ImpressionEventObserver(\r\n triggerBasicPlanResultsDisplayedEvent\r\n);\r\n/**\r\n * bindBasicPlanResultsDisplayedEvents: Observe each card to check when some card is viewed.\r\n */\r\nconst bindBasicPlanResultsDisplayedEvents = () => {\r\n const basicPlanListingCards = getBasicPlanListingCards();\r\n const basicManufacturedPlanListingCards = getBasicManufacturedPlanListingCards();\r\n const basicCustomPlanListingCards = getBasicCustomPlanListingCards();\r\n const basicPlanHomesListingCards = [\r\n ...basicPlanListingCards,\r\n ...basicManufacturedPlanListingCards,\r\n ...basicCustomPlanListingCards];\r\n const basicPlanListingContainerObserver = basicPlanListingResultsDisplayedEventObserver.getIntersectionObserver();\r\n basicPlanHomesListingCards.forEach((card) => basicPlanListingContainerObserver.observe(card));\r\n};\r\n/**\r\n * getBasicListingCards: Gets the list of current basic listing cards.\r\n * @returns A HTML Node list of current basic listing cards.\r\n */\r\nconst getBasicListingCards = () => listViewSection.querySelectorAll(basicListingCardSelector);\r\n/**\r\n * triggerBasicListingResultsDisplayedEvent: Triggers the Basic Listing Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerBasicListingResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n community_id: cardDataset.communityId,\r\n id: cardDataset.id,\r\n community_name: cardDataset.communityName,\r\n primary_image_url: cardDataset.imageUrl,\r\n position,\r\n is_paid: false,\r\n is_zero_results: isNotResultPage(),\r\n };\r\n store.dispatch(segmentImpression({ eventName: 'Basic Detail Result Displayed', customProperties }));\r\n};\r\nconst basicListingResultsDisplayedEventObserver = new ImpressionEventObserver(\r\n triggerBasicListingResultsDisplayedEvent\r\n);\r\n/**\r\n * bindBasicListingResultsDisplayedEvents: Observe each card to check when some card is viewed.\r\n */\r\nconst bindBasicListingResultsDisplayedEvents = () => {\r\n const basicListingCards = getBasicListingCards();\r\n const basicListingContainerObserver = basicListingResultsDisplayedEventObserver.getIntersectionObserver();\r\n basicListingCards.forEach((card) => basicListingContainerObserver.observe(card));\r\n};\r\n\r\nconst isNewResultsInformationLoaded = ({\r\n fetchResultListingsStatus,\r\n fetchResultCountsStatus,\r\n housingProductLocationFetchStatus,\r\n}) =>\r\n fetchResultListingsStatus !== LoadingStatus.Loading &&\r\n fetchResultCountsStatus !== LoadingStatus.Loading &&\r\n housingProductLocationFetchStatus !== LoadingStatus.Loading;\r\n\r\n/**\r\n * bindPaidCommunityResultsDisplayedEvents: Observe each card to check when some card is viewed.\r\n */\r\nconst bindPaidCommunityResultsDisplayedEvents = () => {\r\n const communityListingCards = getPaidCommunityListingCards();\r\n const manufacturedCommunityListingCards = getPaidManufacturedCommunityListingCards();\r\n const customCommunityListingCards = getPaidCustomCommunityListingCards();\r\n const paidCommunityListings = [\r\n ...communityListingCards,\r\n ...manufacturedCommunityListingCards,\r\n ...customCommunityListingCards,\r\n ];\r\n const communityContainerObserver = paidCommunityResultsDisplayedEventObserver.getIntersectionObserver();\r\n paidCommunityListings.forEach((card) => communityContainerObserver.observe(card));\r\n};\r\nconst resultsChanged$ = store$.pipe(\r\n map(selectRequestStatus),\r\n distinctUntilChanged(),\r\n filter(isNewResultsInformationLoaded)\r\n);\r\n\r\n/**\r\n * triggerCommunityStaticMapHoverEvent will dispatch the event of hovering in a community\r\n * static map. It will track properties as the identifier of the static map, and how many\r\n * time lasted the hovering gesture.\r\n */\r\nconst triggerCommunityStaticMapHoverEvent = ({ communityStaticMap, hoverDuration, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n hover_duration: hoverDuration,\r\n device_type: deviceType,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'map_hover', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapHovered$.subscribe(triggerCommunityStaticMapHoverEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapClickEvent will dispatch the event of clicking in a community.\r\n * static map.\r\n */\r\nconst triggerCommunityStaticMapClickEvent = ({ communityStaticMap, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'map_click', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapClicked$.subscribe(triggerCommunityStaticMapClickEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapDoubleClickEvent will dispatch the event of double clicking in a community.\r\n */\r\nconst triggerCommunityStaticMapDoubleClickEvent = ({ communityStaticMap, deviceType }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n redirected_to: communityStaticMap.url,\r\n };\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName: 'map_double_click', customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapDoubleClicked$.subscribe(triggerCommunityStaticMapDoubleClickEvent);\r\n\r\n/**\r\n * triggerCommunityStaticMapZoomChangedEvent will dispatch an event with information like\r\n * identifier and name of the community static map that received the zoom change. Also, it\r\n * will track if the zoom change was a zoom in or out.\r\n */\r\nconst triggerCommunityStaticMapZoomChangedEvent = ({ communityStaticMap, zoomGesture, deviceType, zoomLevel }) => {\r\n const customProperties = {\r\n community_id: communityStaticMap.id,\r\n community_name: communityStaticMap.name,\r\n device_type: deviceType,\r\n zoom_level: zoomLevel,\r\n };\r\n\r\n const eventName = zoomGesture === \"zoomIn\" ? \"map_zoom_in\" : \"map_zoom_out\";\r\n\r\n setTimeout(()=> store.dispatch(segmentTrack({ eventName, customProperties })), 0);\r\n}\r\n\r\ncommunityStaticMapZoomChanged$.subscribe(triggerCommunityStaticMapZoomChangedEvent);\r\n\r\nresultsChanged$.subscribe(bindPaidCommunityResultsDisplayedEvents);\r\nresultsChanged$.subscribe(bindBasicCommunityResultsDisplayedEvents);\r\nresultsChanged$.subscribe(bindBasicPlanResultsDisplayedEvents);\r\nresultsChanged$.subscribe(bindBasicSpecResultsDisplayedEvents);\r\nresultsChanged$.subscribe(bindBasicListingResultsDisplayedEvents);\r\n\r\nbindPaidCommunityResultsDisplayedEvents();\r\nbindBasicCommunityResultsDisplayedEvents();\r\nbindBasicListingResultsDisplayedEvents();\r\nbindBasicPlanResultsDisplayedEvents();\r\nbindBasicSpecResultsDisplayedEvents();\r\n\r\n/**\r\n * getPaidPlanListingCards: Gets the list of current paid plan listing cards.\r\n * @returns A HTML Node list of current paid plan cards.\r\n */\r\nconst getPaidPlanListingCards = () => listViewSection.querySelectorAll(paidPlanCardSelector);\r\n/**\r\n * getPaidSpecListingCards: Gets the list of current spec community listing cards.\r\n * @returns A HTML Node list of current paid spec cards.\r\n */\r\nconst getPaidSpecListingCards = () => listViewSection.querySelectorAll(paidSpecCardSelector);\r\n/**\r\n * getPaidManufacturedListingCards: Gets the list of current paid manufactured listing cards.\r\n * @returns A HTML Node list of current paid manufactured home cards.\r\n */\r\nconst getPaidManufacturedListingCards = () => listViewSection.querySelectorAll(`${paidManufacturedPlanCardSelector},\r\n${paidManufacturedSpecCardSelector}`);\r\n\r\n/**\r\n * getPaidCustomListingCards: Gets the list of current paid custom listing cards.\r\n * @returns A HTML Node list of current paid manufactured home cards.\r\n */\r\nconst getPaidCustomListingCards = () => listViewSection.querySelectorAll(`${paidCustomPlanCardSelector}, \r\n${paidCustomSpecCardSelector}, ${paidBuildOnYourLotPlanCardSelector}, ${paidBuildOnYourLotSpecCardSelector}`);\r\n/**\r\n * triggerPaidHomeResultsDisplayedEvent: Triggers the Home Results Displayed impression event.\r\n * @param {HTMLElement} viewedCard Shown card.\r\n */\r\nconst triggerPaidHomeResultsDisplayedEvent = (viewedCard) => {\r\n const cardDataset = viewedCard.dataset;\r\n const position = Number(cardDataset.index) + 1;\r\n\r\n const homeType = cardDataset.type;\r\n if (homeType === 'plan') {\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n plan_id: cardDataset.planId,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n image_1_url: cardDataset.imageUrl,\r\n image_2_url: cardDataset.secondaryImageUrl,\r\n image_3_url: cardDataset.tertiaryImageUrl,\r\n is_zero_results: isNotResultPage(),\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n }\r\n store.dispatch(segmentImpression({ eventName: 'Home Result Displayed', customProperties }));\r\n }\r\n\r\n if (homeType === 'spec') {\r\n const customProperties = {\r\n market_id: cardDataset.marketId,\r\n market_name: `${cardDataset.marketName}, ${cardDataset.stateAbbreviation}`,\r\n city: cardDataset.city,\r\n state: cardDataset.stateAbbreviation,\r\n zip: cardDataset.zip,\r\n builder_id: cardDataset.builderId,\r\n builder_name: cardDataset.brandName,\r\n community_id: cardDataset.communityId,\r\n spec_id: cardDataset.specId,\r\n community_name: cardDataset.communityName,\r\n community_status: cardDataset.marketingStatusLabel,\r\n primary_image_url: cardDataset.imageUrl,\r\n community_low_price: cardDataset.priceLow,\r\n community_high_price: cardDataset.priceHigh,\r\n position,\r\n image_1_url: cardDataset.imageUrl,\r\n image_2_url: cardDataset.secondaryImageUrl,\r\n image_3_url: cardDataset.tertiaryImageUrl,\r\n is_zero_results: isNotResultPage(),\r\n is_paid: true,\r\n is_spotlight: !!cardDataset.isFeaturedListing,\r\n community_type: cardDataset.communityType,\r\n }\r\n\r\n store.dispatch(segmentImpression({ eventName: 'Home Result Displayed', customProperties }));\r\n }\r\n};\r\nconst paidHomeResultsDisplayedEventObserver = new ImpressionEventObserver(triggerPaidHomeResultsDisplayedEvent);\r\n\r\n/**\r\n * bindPaidHomeResultsDisplayedEvents: Observe each home card to check when some card is viewed.\r\n */\r\nconst bindPaidHomeResultsDisplayedEvents = () => {\r\n const paidPlanListingCards = getPaidPlanListingCards();\r\n const paidSpecListingCards = getPaidSpecListingCards();\r\n const paidManufacturedListingCards = getPaidManufacturedListingCards();\r\n const paidCustomListingCards = getPaidCustomListingCards();\r\n const paidHomeListingCards = [\r\n ...paidPlanListingCards,\r\n ...paidSpecListingCards,\r\n ...paidManufacturedListingCards,\r\n ...paidCustomListingCards,\r\n ];\r\n const homeContainerObserver = paidHomeResultsDisplayedEventObserver.getIntersectionObserver();\r\n paidHomeListingCards.forEach((card) => homeContainerObserver.observe(card));\r\n};\r\n\r\nresultsChanged$.subscribe(bindPaidHomeResultsDisplayedEvents);\r\nbindPaidHomeResultsDisplayedEvents();\r\n\r\n// #endregion\r\n\r\n/**\r\n * Triggers the carousel closed event for plan markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerPlanCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n plan_id: marker.Id,\r\n community_id: marker.CommunityId,\r\n plan_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.CommunityStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_closed', customProperties }));\r\n });\r\n}\r\n\r\n/**\r\n * Triggers the carousel closed event for spec markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerSpecCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n spec_id: marker.Id,\r\n community_id: marker.CommunityId,\r\n spec_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.CommunityStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_closed', customProperties }));\r\n });\r\n}\r\n\r\n/**\r\n * Triggers the carousel scrolled event for plan markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityCarouselClosedEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n community_id: marker.Id,\r\n community_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.MarketingStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_closed', customProperties }));\r\n });\r\n}\r\n\r\n/**\r\n * Triggers the carousel scrolled event for plan markers.\r\n * @param {Object} - The marker object.\r\n */\r\nfunction triggerPlanCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n market_id: marker.MarketId,\r\n plan_id: marker.Id,\r\n community_id: marker.CommunityId,\r\n plan_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.CommunityStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_card_swiped', customProperties }));\r\n });\r\n}\r\n\r\n/**\r\n * Triggers the carousel scrolled event for spec markers.\r\n * @param {Object} spec - The marker object.\r\n */\r\nfunction triggerSpecCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n spec_id: marker.Id,\r\n community_id: marker.CommunityId,\r\n spec_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.CommunityStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_card_swiped', customProperties }));\r\n });\r\n}\r\n\r\n/**\r\n * Triggers the carousel scrolled event for community markers.\r\n * \r\n * @param {Object} marker - The marker object.\r\n */\r\nfunction triggerCommunityCarouselScrolledEvent(data) {\r\n const marker = data.activeItem;\r\n\r\n const customProperties = {\r\n market_id: marker.MarketId,\r\n brand_name: marker.brandName,\r\n community_id: marker.Id,\r\n community_name: marker.Name,\r\n price: marker.Price,\r\n city: marker.City,\r\n state: marker.StateAbbreviation,\r\n zip: marker.Zip,\r\n is_paid: !marker.IsBasic,\r\n current_card_position: data.currentCardPosition,\r\n next_card_position: data.nextCardPosition,\r\n listing_id: data.listingId,\r\n direction: data.direction,\r\n builder_id: marker.BuilderId,\r\n builder_name: marker.BrandName,\r\n community_status: marker.MarketingStatus.Name, \r\n primary_image_url: marker.Thumbnail,\r\n community_low_price: marker.PriceLow,\r\n community_high_price: marker.PriceHigh,\r\n };\r\n\r\n setTimeout(() => {\r\n store.dispatch(segmentTrack({ eventName: 'carousel_card_swiped', customProperties }));\r\n });\r\n}\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanCarouselClosedEvent);\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.SpecUnit.toString()),\r\n).subscribe(triggerSpecCarouselClosedEvent);\r\n\r\ncarouselCloseButtonClicked$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.HousingDevelopment.toString()),\r\n).subscribe(triggerCommunityCarouselClosedEvent);\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.PlanUnit.toString()),\r\n).subscribe(triggerPlanCarouselScrolledEvent);\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.SpecUnit.toString()),\r\n).subscribe(triggerSpecCarouselScrolledEvent);\r\n\r\nnearbyListingsCarouselScrolled$.pipe(\r\n filter(marker => Boolean(marker)),\r\n filter(marker => marker.type === MarkerType.HousingDevelopment.toString()),\r\n).subscribe(triggerCommunityCarouselScrolledEvent);\r\n","import { isMapResultsFetching, selectMapLibraryStatus } from 'features/searchResultsMap';\r\nimport { selectUiState } from 'layout/redux/selectors';\r\nimport { store, store$ } from '@redux/store';\r\nimport {\r\n combineLatest,\r\n debounceTime,\r\n distinctUntilChanged,\r\n distinctUntilKeyChanged,\r\n filter,\r\n fromEvent,\r\n map,\r\n merge,\r\n pairwise,\r\n skip,\r\n switchMap,\r\n take,\r\n tap,\r\n withLatestFrom,\r\n} from 'rxjs';\r\nimport LeadFormType from 'features/leadGenerators';\r\nimport {\r\n selectIsInProgress,\r\n speedCurveMarkEnd,\r\n speedCurveMarkStart,\r\n speedCurveTrackConversion,\r\n speedcurveStateActions,\r\n speedcurveTimingMetric,\r\n} from 'features/speedcurve';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport {\r\n UrlSubdirectoryTypes,\r\n selectFacts,\r\n selectFeatures,\r\n selectFetchResultListingsStatus,\r\n selectLocation,\r\n selectResultsModifiers,\r\n} from 'features/searchResultsFacets';\r\nimport { selectRoutingState } from 'features/routing';\r\n\r\nconst isLuxDefined = () => !!window.LUX;\r\n\r\nconst startSpeedcurveTracking = () => {\r\n const state = store.getState();\r\n const isInProgress = selectIsInProgress(state);\r\n // Speedcurve is in progress and make interaction in the DOM fast, we need to end and start again the tracking.\r\n if (isInProgress) {\r\n const routing = selectRoutingState(state);\r\n window.LUX.label = UrlSubdirectoryTypes.fromKey(routing.urlSubdirectory).luxLabel;\r\n window.LUX.send();\r\n window.LUX.init();\r\n return;\r\n }\r\n store.dispatch(speedcurveStateActions.start());\r\n};\r\nconst endSpeedcurveTracking = () => store.dispatch(speedcurveStateActions.end());\r\n\r\nconst paidModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => LeadFormType.InformationFormBasic.toString() !== modalInformation.leadGeneratorOpener)\r\n);\r\n\r\nconst trackPaidFormSend = () => store.dispatch(speedCurveTrackConversion([{ name: 'lead_sent', value: 1 }]));\r\n\r\npaidModalSubmission$.subscribe(trackPaidFormSend);\r\n\r\nconst onMapLibraryStatusChange$ = store$.pipe(map(selectMapLibraryStatus), distinctUntilChanged());\r\n\r\nconst trackMapLibraryStart = () => store.dispatch(speedCurveMarkStart([{ name: 'map_script_start' }]));\r\n\r\nconst trackMapLibraryLoaded = () =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: 'map_downloaded',\r\n markNameStart: 'map_script_start',\r\n markNameEnd: 'map_script_end',\r\n },\r\n ])\r\n );\r\n\r\nonMapLibraryStatusChange$\r\n .pipe(filter((status) => status === LoadingStatus.Loading.toString()))\r\n .subscribe(trackMapLibraryStart);\r\n\r\nonMapLibraryStatusChange$\r\n .pipe(filter((status) => status === LoadingStatus.Succeeded.toString()))\r\n .subscribe(trackMapLibraryLoaded);\r\n\r\nconst onMapResultsChange$ = store$.pipe(map(isMapResultsFetching), distinctUntilChanged());\r\n\r\nconst trackMapResultsStart = () => store.dispatch(speedCurveMarkStart([{ name: 'map_points_start' }]));\r\n\r\nconst trackMapResultsLoaded = () =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: 'map_points_request',\r\n markNameStart: 'map_points_start',\r\n markNameEnd: 'map_points_end',\r\n },\r\n ])\r\n );\r\n\r\nonMapResultsChange$.pipe(filter(Boolean)).subscribe(trackMapResultsStart);\r\n\r\nonMapResultsChange$\r\n .pipe(\r\n filter((isFetching) => !isFetching),\r\n skip(1)\r\n )\r\n .subscribe(trackMapResultsLoaded);\r\n\r\n/**\r\n * The `mapResources` function maps script, link, and font resources on a web page to their\r\n * corresponding URLs.\r\n * @returns The function `mapResources` returns an object that contains the resources mapped by their\r\n * respective URLs or values. The object includes three properties: `scripts`, `links`, and `fonts`.\r\n * Each property is an object that maps the URL or value of the resource to its corresponding\r\n * `data-resource` attribute value.\r\n */\r\nconst mapResources = () => {\r\n const scriptResources = document.querySelectorAll('script[data-resource]');\r\n const linkResources = document.querySelectorAll('link[data-resource]');\r\n const fontResources = document.querySelectorAll('[data-resource=\"font\"]');\r\n const scripts = {};\r\n const links = {};\r\n const fonts = {};\r\n\r\n scriptResources.forEach((resource) => {\r\n scripts[resource.src] = resource.dataset.resource;\r\n });\r\n\r\n linkResources.forEach((resource) => {\r\n links[resource.href] = resource.dataset.resource;\r\n });\r\n\r\n fontResources.forEach((resource) => {\r\n fonts[resource.value] = resource.dataset.resource;\r\n });\r\n\r\n return { ...scripts, ...links, ...fonts };\r\n};\r\n\r\n/**\r\n * The function `trackResourceTiming` retrieves performance timing data for specified resources and\r\n * dispatches an action with the data.\r\n * @param resources - The `resources` parameter is an object that maps resource URLs to their\r\n * corresponding keys. The keys are used to identify the resources in the `speedcurveResources` array.\r\n */\r\nconst trackResourceTiming = (resources) => {\r\n const entries = performance?.getEntriesByType('resource') || [];\r\n const speedcurveResources = [];\r\n entries.forEach((entry) => {\r\n const key = resources[entry.name];\r\n if (key) {\r\n speedcurveResources.push({\r\n name: key,\r\n value: entry.duration,\r\n });\r\n }\r\n });\r\n\r\n if (speedcurveResources.length) {\r\n store.dispatch(speedcurveTimingMetric(speedcurveResources));\r\n }\r\n};\r\n\r\nfromEvent(window, 'load').pipe(map(mapResources)).subscribe(trackResourceTiming);\r\n\r\nconst getKeyAd = (elementId) => {\r\n const key = elementId.split('--');\r\n return key[key.length - 1];\r\n};\r\n\r\nconst trackAdRequestStart = () => store.dispatch(speedCurveMarkStart([{ name: `ad_request_start` }]));\r\n\r\nfromEvent(window, 'adRequestStart').subscribe(trackAdRequestStart);\r\n\r\nconst trackAdRequestEnd = (key) =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: `ad_${key}_measure`,\r\n markNameStart: `ad_request_start`,\r\n markNameEnd: `ad_${key}_end`,\r\n },\r\n ])\r\n );\r\n\r\nfromEvent(window, 'adRequestEnd')\r\n .pipe(map((event) => getKeyAd(event.detail.elementId)))\r\n .subscribe(trackAdRequestEnd);\r\n\r\nconst trackAdScriptStart = () => store.dispatch(speedCurveMarkStart([{ name: `ads_script_start` }]));\r\n\r\nfromEvent(window, 'adScriptStart').subscribe(trackAdScriptStart);\r\n\r\nconst trackAdScriptEnd = () =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: `ads_script_measure`,\r\n markNameStart: `ads_script_start`,\r\n markNameEnd: `ads_script_end`,\r\n },\r\n ])\r\n );\r\n\r\nfromEvent(window, 'adScriptEnd').subscribe(trackAdScriptEnd);\r\n\r\nconst trackAdParametersStart = () => store.dispatch(speedCurveMarkStart([{ name: `ads_parameters_definition_start` }]));\r\n\r\nfromEvent(window, 'adParametersStart').subscribe(trackAdParametersStart);\r\n\r\nconst trackAdParametersEnd = () =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName: `ads_parameters_definition_measure`,\r\n markNameStart: `ads_parameters_definition_start`,\r\n markNameEnd: `ads_parameters_definition_end`,\r\n },\r\n ])\r\n );\r\n\r\nfromEvent(window, 'adParametersEnd').subscribe(trackAdParametersEnd);\r\n\r\n/* Measure list view interactions */\r\n\r\n/**\r\n * Dispatches a `speedCurveMarkStart` action to mark when the interaction start.\r\n */\r\nconst markStartEvent = ({ markNameStart }) => store.dispatch(speedCurveMarkStart([{ name: markNameStart }]));\r\n\r\n/**\r\n * Dispatches an action to mark the end of a performance measurement for the list view being loaded.\r\n */\r\nconst trackListViewLoaded = ({ markNameStart, measureName }) =>\r\n store.dispatch(\r\n speedCurveMarkEnd([\r\n {\r\n measureName,\r\n markNameStart,\r\n markNameEnd: `list_view_loaded`,\r\n },\r\n ])\r\n );\r\n\r\nconst tabContainer = document.querySelectorAll('[data-result-type-bar]');\r\n\r\n/** Listen click events on elements tab results.\r\n */\r\nconst tabsClicks$ = fromEvent(tabContainer, 'click').pipe(tap(startSpeedcurveTracking));\r\n\r\n/**\r\n * Creates an observable that emit a value when results are succeded.\r\n * We add the pairwise because after the fetchResultListingsStatus is set to @LoadingStatus.Succeeded,\r\n * in the next iteraction the fetchResultListingsStatus is Succeded and it doesn't change to Loading.\r\n * For this reason we need to check if the last value was Loading and the current value is Succeded.\r\n */\r\nconst listViewLoaded$ = store$.pipe(\r\n map(selectFetchResultListingsStatus),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n filter(([previous, current]) => previous === LoadingStatus.Loading && current === LoadingStatus.Succeeded)\r\n);\r\n\r\n/** Observable to track the interaction when a user clicks on\r\n * tabs and measure how much time takes the list view to be ready.\r\n */\r\nconst measureListViewOnTabsInteraction$ = tabsClicks$.pipe(\r\n map(() => ({\r\n markNameStart: 'tabs_click',\r\n })),\r\n tap(markStartEvent),\r\n switchMap(({ markNameStart }) =>\r\n listViewLoaded$.pipe(\r\n tap(() =>\r\n trackListViewLoaded({\r\n markNameStart,\r\n measureName: `tabs_interaction_list_view`,\r\n })\r\n ),\r\n take(1)\r\n )\r\n )\r\n);\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in facts leaf change.\r\n */\r\nconst facts$ = store$.pipe(map(selectFacts), filter(Boolean), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in features leaf change.\r\n */\r\nconst features$ = store$.pipe(map(selectFeatures), filter(Boolean), distinctUntilChanged());\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in results modifiers leaf change.\r\n */\r\nconst resultsModifiers$ = store$.pipe(map(selectResultsModifiers), filter(Boolean), distinctUntilChanged());\r\n\r\nconst onFilterChange$ = combineLatest([facts$, features$, resultsModifiers$]).pipe(\r\n debounceTime(100),\r\n skip(1),\r\n tap(startSpeedcurveTracking)\r\n);\r\n\r\n/** Observable to track the interaction when a filter is applied\r\n * and measure how much time takes the list view to be ready.\r\n */\r\nconst measureListViewOnFiltersIteraction$ = onFilterChange$.pipe(\r\n map(() => ({\r\n markNameStart: 'filter_applied',\r\n })),\r\n tap(markStartEvent),\r\n switchMap(({ markNameStart }) =>\r\n listViewLoaded$.pipe(\r\n tap(() =>\r\n trackListViewLoaded({\r\n markNameStart,\r\n measureName: `filter_interaction_list_view`,\r\n })\r\n ),\r\n take(1)\r\n )\r\n )\r\n);\r\n\r\n/** Subscribe to the store$ observable to listen for changes\r\n * When search parameters in location leaf change, fetch the new results for map.\r\n */\r\nconst locationChange$ = store$.pipe(\r\n map(selectLocation),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n skip(1),\r\n tap(startSpeedcurveTracking)\r\n);\r\n\r\n/** Observable to track the interaction when a user change the location\r\n * and measure how much time takes the list view to be ready.\r\n */\r\nconst measureListViewOnLocationIteraction$ = locationChange$.pipe(\r\n map(() => ({\r\n markNameStart: 'location_change',\r\n measureName: `location_interaction_list_view`,\r\n })),\r\n tap(markStartEvent),\r\n switchMap((measureNames) =>\r\n listViewLoaded$.pipe(\r\n tap(() => trackListViewLoaded(measureNames)),\r\n take(1)\r\n )\r\n )\r\n);\r\n\r\nmerge(\r\n measureListViewOnTabsInteraction$,\r\n measureListViewOnFiltersIteraction$,\r\n measureListViewOnLocationIteraction$\r\n).subscribe();\r\n\r\n/** Init LUX */\r\nconst pathname$ = store$.pipe(map(selectRoutingState), filter(Boolean), distinctUntilKeyChanged('currentUrl'));\r\n/**\r\n * The function `markLuxLoadTime` calls the `markLoadTime` method of the `LUX` object in the\r\n * `window` scope.\r\n */\r\nconst markLuxLoadTime = () => window.LUX.markLoadTime();\r\n\r\nconst onSpeedcurveIsInProgress$ = store$.pipe(\r\n filter(isLuxDefined),\r\n map(selectIsInProgress),\r\n distinctUntilChanged(),\r\n filter(Boolean)\r\n);\r\n\r\nonSpeedcurveIsInProgress$.subscribe(() => window.LUX.init());\r\n\r\nconst onPageLoadedOnAjax$ = store$.pipe(\r\n map((state) => {\r\n const fetchResultListingStatus = selectFetchResultListingsStatus(state);\r\n return fetchResultListingStatus === LoadingStatus.Succeeded && state?.mapState?.isFetchingResults === false;\r\n }),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst onResultsLoaded$ = store$.pipe(\r\n filter(isLuxDefined),\r\n map((state) => {\r\n const fetchResultListingStatus = selectFetchResultListingsStatus(state);\r\n return fetchResultListingStatus === LoadingStatus.Loading || state?.mapState?.isFetchingResults;\r\n }),\r\n distinctUntilChanged(),\r\n map((isFetching) => isFetching === false),\r\n filter(Boolean),\r\n skip(1),\r\n tap(markLuxLoadTime),\r\n switchMap(() => onPageLoadedOnAjax$.pipe(filter(Boolean), take(1))),\r\n withLatestFrom(pathname$),\r\n map(([, routing]) => routing)\r\n);\r\n\r\nonResultsLoaded$\r\n .pipe(\r\n // Speedcurve recommendation, Force SpeedCurve RUM to capture data for a minimum amount\r\n // of time before sending the beacon. Equivalent to minMeasureTime.\r\n debounceTime(5000)\r\n )\r\n .subscribe((routing) => {\r\n window.LUX.label = UrlSubdirectoryTypes.fromKey(routing.urlSubdirectory).luxLabel;\r\n window.LUX.send();\r\n endSpeedcurveTracking();\r\n });\r\n","require('./panels');\r\nrequire('./sort');\r\nrequire('./pageSize');\r\nrequire('./searchWithinMap');\r\n","import { store } from '@redux/store';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { fromEvent } from \"rxjs\";\r\n\r\nconst pageSizeElement = document.querySelector('[data-page-size]');\r\nconst pageSizeChange$ = fromEvent(pageSizeElement, 'change');\r\n\r\n/**\r\n * pageSizeChangeHandler: Handles the page size changes.\r\n * @param {Event} event Change event object\r\n */\r\nfunction pageSizeChangeHandler(event) {\r\n const newPageSize = parseInt(event.target.value, 10);\r\n store.dispatch(searchParametersActions.fetchPageSize(newPageSize));\r\n}\r\n\r\npageSizeChange$.subscribe(pageSizeChangeHandler);\r\n\r\n","import Panel from \"@components/panel\";\r\n\r\nconst facetContainers = document.querySelectorAll('[data-panel]');\r\nfacetContainers.forEach(container => {\r\n const configuration = {\r\n container\r\n }; \r\n // Disabling no-new because it is not required to save this object\r\n // on a variable.\r\n // eslint-disable-next-line no-new\r\n new Panel(configuration);\r\n});","import { distinctUntilChanged, filter, map, pairwise, withLatestFrom } from 'rxjs/operators';\r\nimport { store, store$ } from '@redux/store';\r\nimport { \r\n getGeoCoordinates,\r\n mapStateActions,\r\n isMapLibraryLoaded,\r\n isSearchWithinMapEnabled\r\n} from 'features/searchResultsMap';\r\nimport { LocationType, searchParametersActions } from 'features/searchResultsFacets';\r\nimport { fromEvent } from 'rxjs';\r\n\r\nconst searchWithinMapCheckbox = document.getElementById('btnSearchWithinMap');\r\n\r\n/**\r\n * When the user clicks the button, the mapStateActions.enableSearchWithinMap() function is called,\r\n * which updates the state of the map setting the isSearchWithinMap flag in true\r\n * to enable the search within map functionality.\r\n */\r\nconst enableMapSearch = () => {\r\n store.dispatch(mapStateActions.enableSearchWithinMap({}));\r\n};\r\n\r\n/**\r\n * When the user search for new location, the mapStateActions.disableSearchWithinMap() function is called,\r\n * which updates the state of the map setting the isSearchWithinMap flag in false\r\n * to disable the search within map functionality.\r\n */\r\nconst disableMapSearch = () => {\r\n store.dispatch(mapStateActions.disableSearchWithinMap({}));\r\n};\r\n\r\n/**\r\n * It takes the coordinates of the map's current viewport and uses them to update the location parameters\r\n * from the state which will force an update on the page results.\r\n */\r\nconst fetchSearchWithinMapResults = () => {\r\n const geoCoordinates = getGeoCoordinates();\r\n store.dispatch(\r\n searchParametersActions.fetchLocations({\r\n locationType: 'rectangularArea',\r\n minimumLatitude: geoCoordinates.south,\r\n maximumLatitude: geoCoordinates.north,\r\n minimumLongitude: geoCoordinates.west,\r\n maximumLongitude: geoCoordinates.east,\r\n })\r\n );\r\n};\r\n\r\n/** Unchecks the checkbox as needed.\r\n * Usualy used when the search whithin map is disabled via other mean other that the checkbox itself.\r\n */\r\nconst uncheckSearchWithinMapCheckbox = () => {\r\n searchWithinMapCheckbox.checked = false;\r\n};\r\n\r\n/** Method to be called once search within map is disabled by other mean other that the checkbox itself.\r\n * example, once the location is updated via typeahed, then searchwithin map is disabled,\r\n * so we need to ensure that the checkbox is unchecked as well\r\n */\r\nconst disableSearchWithinMap = () => {\r\n disableMapSearch();\r\n uncheckSearchWithinMapCheckbox();\r\n};\r\n\r\n/**\r\n * checkSearchWithinMapCheckbox: checks the search within map check box.\r\n */\r\nconst checkSearchWithinMapCheckbox = () => {\r\n searchWithinMapCheckbox.checked = true;\r\n}\r\n\r\n/** Determines the toggle state\r\n * When the toggle checkbox is clicked, it will determine the checked attribute\r\n * and incoke the eneable or disable map search methods. \r\n */\r\nconst searchWithinMapToggleAction = (event) => {\r\n const checkboxElement = event.target;\r\n if (checkboxElement.checked) {\r\n enableMapSearch();\r\n } else {\r\n disableMapSearch();\r\n }\r\n}\r\n\r\nconst searchWithinMapCheckboxClicks$ = fromEvent(searchWithinMapCheckbox, 'click');\r\nsearchWithinMapCheckboxClicks$.subscribe(searchWithinMapToggleAction);\r\n\r\n\r\n/** Subscribing to the store.\r\n * When the location change and it is not RectangularArea, it will call disableMapSearch.\r\n */\r\nstore$\r\n .pipe(\r\n map((state) => state.searchParameters.location?.locationType),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n filter(([previousLocationType]) => previousLocationType === LocationType.RectangularArea.toString())\r\n )\r\n .subscribe(disableSearchWithinMap);\r\n\r\n/**\r\n * This observable emits a flag indicating when the map library script loaded correctly.\r\n */\r\nconst isMapLibraryLoaded$ = store$.pipe(\r\n filter(isMapLibraryLoaded),\r\n filter((state) => state.mapState.isSearchWithinMapReady),\r\n map(isMapLibraryLoaded),\r\n distinctUntilChanged());\r\n\r\n/**\r\n * This observable emits new geo coordinates retrieved after the map positioned to a new place.\r\n */\r\nconst onNewCoordinates$ = store$.pipe(\r\n filter(isMapLibraryLoaded),\r\n filter((state) => state.mapState.isSearchWithinMapReady),\r\n map((state) => state.mapState.geoCoordinates),\r\n distinctUntilChanged());\r\n\r\n/** Subscribing to the store.\r\n * When the map state geo coordinatnes changes it will call the fetchSearchWithinMapResults function.\r\n */\r\nstore$\r\n .pipe(\r\n filter(isMapLibraryLoaded),\r\n filter((state) => state.mapState.isSearchWithinMapReady),\r\n map((state) => state.mapState.geoCoordinates),\r\n /**\r\n * the explanation behind the pairwise is: we have map coordinates until the time the GM library is loaded and\r\n * an action stores those geo-coordinates. Before that time, our geo-coordinates are undefined.\r\n * By using a pairwise operator, we make sure to trigger the search within map functionality only when the\r\n * user drags the map around from a given location to a new one (so the geo-coordinates in the store changed\r\n * from valid ones, to a new ones also valid, not undefined).\r\n * This means: if the geo-coordinates changes from undefined to an actual latitude or longitude value, we are'nt\r\n * triggering the fetch functionality, because that change means the GM map has loaded and stored the first set\r\n * of valid geo-coordinates, but not because of an actual drag on the map. The only time that search within map\r\n * is ON by the time we move from undefined geo-coordinates to valid ones is in initial load for rectangular\r\n * area searches, and in those scenarios we already have both the map markers and the cards calculated from\r\n * server side, no need to fetch them again.\r\n */\r\n pairwise(),\r\n filter(([prevCoordinates, currentCoordinates]) => prevCoordinates && currentCoordinates),\r\n filter(([prevCoordinates, currentCoordinates]) =>\r\n prevCoordinates.east !== currentCoordinates.east ||\r\n prevCoordinates.north !== currentCoordinates.north ||\r\n prevCoordinates.south !== currentCoordinates.south ||\r\n prevCoordinates.west !== currentCoordinates.west),\r\n map(([, currentCoordinates]) => currentCoordinates),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(fetchSearchWithinMapResults);\r\n\r\n/**\r\n * Subscribing to the observable for 'Search Within Map' checkbox clicks, we fetch results when new clicks are received,\r\n * provided that signals from the observables for map library loaded and new geo-coordinates have already been emitted.\r\n */\r\nsearchWithinMapCheckboxClicks$.pipe(\r\n withLatestFrom(isMapLibraryLoaded$, onNewCoordinates$),\r\n map(([clickEvent]) => ({\r\n clickEvent\r\n })),\r\n filter(({ clickEvent }) => clickEvent.target.checked)\r\n)\r\n.subscribe(fetchSearchWithinMapResults);\r\n\r\n /** Subscribing to the store.\r\n * When seach within map is enabled, but the checkbox switch on screen for search within map doesn't reflects that,\r\n * then we manually check that switch so it is clear for the user that she/he is search within map.\r\n * The scenario where this could happen is when an outside module dispatches the enableSearchWithinMap action from\r\n * the map slice, for example: the geoProximityHandler.js module when an user selects current location from the\r\n * typeahead, this option triggers a search within map search without the need of clicking the search within\r\n * map checkbox.\r\n */\r\n store$\r\n .pipe(\r\n filter(() => !searchWithinMapCheckbox.checked),\r\n filter(isSearchWithinMapEnabled),\r\n )\r\n .subscribe(checkSearchWithinMapCheckbox);","import {\r\n searchParametersActions,\r\n selectResultTypeAndSorting,\r\n selectSorting,\r\n} from 'features/searchResultsFacets';\r\nimport Select from '@components/select';\r\nimport { store, store$ } from '@redux/store';\r\nimport {\r\n map,\r\n distinctUntilKeyChanged,\r\n skip,\r\n filter,\r\n distinctUntilChanged,\r\n} from 'rxjs';\r\n\r\nconst sortElement = document.querySelector('[data-sort-element]');\r\n\r\nconst select$ = new Select(sortElement).getObservable();\r\n\r\nselect$.subscribe((value) => {\r\n const sortBy = value.split(',')[0];\r\n const sortOrder = value.split(',')[1] === 'true';\r\n store.dispatch(\r\n searchParametersActions.fetchSort({\r\n sortBy,\r\n sortOrder,\r\n })\r\n );\r\n});\r\n\r\n/**\r\n * This observable will emit values every time there is a change in the result type.\r\n */\r\nconst onResultsTypeChanged$ = store$.pipe(\r\n map(selectResultTypeAndSorting),\r\n distinctUntilKeyChanged('resultType'),\r\n map(({sorting, resultType}) => ({\r\n value: `${sorting.sortBy},${sorting.sortOrder}`,\r\n resultType,\r\n })),\r\n skip(1),\r\n);\r\n\r\n/**\r\n * updateOptionsVisibility: based on the current result type, this function updates the visibility\r\n * of some options that are unique for a given result type and should not appear in all scenarios.\r\n * @param {string} resultType is the result type name. \r\n */\r\nconst updateOptionsVisibility = ({resultType}) => {\r\n const uniqueOptions = sortElement.querySelectorAll(`[data-only-result-types]`);\r\n uniqueOptions.forEach((option) => {\r\n const validResultTypes = option.dataset.onlyResultTypes.split(',');\r\n if (validResultTypes.includes(resultType)) {\r\n option.removeAttribute('hidden');\r\n } else {\r\n option.setAttribute('hidden', '');\r\n }\r\n });\r\n}\r\n\r\nonResultsTypeChanged$.subscribe(updateOptionsVisibility);\r\n\r\n/**\r\n * synchronizeSortElement: there are scenarios where users might sort results using\r\n * a sorting criteria that is unique for the result type they are currently viewing.\r\n * For example: the sorting criteria \"bed\" is only available for \"homes\" result type,\r\n * so if the user selects it and then navigates to another result type, the select HTML\r\n * element has to be congruent with the user selection and the results shown.\r\n * In the specified example described, the sorting will change to \"default\" as \"bed\" only exists\r\n * for \"homes\" result type, so this function is in charge of reflecting that change in the\r\n * select HTML element the user is seeing in the newly selected result type.\r\n * @param {HTML} sortElement is the HTML control the user is currently seeing. \r\n * @param {string} value represents the value to be selected in the HTML control. \r\n */\r\nconst synchronizeSortElement = ({value}) => {\r\n if (sortElement.querySelector(`option[value=\"${value}\"]`)) {\r\n sortElement.value = value;\r\n return;\r\n }\r\n\r\n sortElement.selectedIndex = 0;\r\n}\r\n\r\nonResultsTypeChanged$.subscribe(synchronizeSortElement);\r\n\r\n/**\r\n * onSortStateChange$: is an observable of the store. The streams will occur whenever the\r\n * state value for the sorting is different than what the sorting HTML is showing.\r\n * This could happen when you have applied a sorting option, and then you clean up the filters,\r\n */\r\nconst onSortStateChange$ = store$.pipe(\r\n map(selectSorting),\r\n distinctUntilChanged(),\r\n map((sorting) => ({\r\n value: `${sorting?.sortBy},${sorting?.sortOrder}`,\r\n sortElementValue: sortElement.value,\r\n })),\r\n filter(({value, sortElementValue}) => value !== sortElementValue),\r\n);\r\n\r\nonSortStateChange$.subscribe(synchronizeSortElement);","import { store$ } from '@redux/store';\r\nimport { ResultType, selectResultsType } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\n\r\nconst panelsElements = [\r\n document.querySelector('[data-typeahead-container]'),\r\n document.querySelector('[data-facets-panel]'),\r\n];\r\n\r\n/**\r\n * Hides all elements in the `panelsElements` array.\r\n * Adds the `hidden` attribute to make the elements invisible.\r\n */\r\nconst hidePanels = () => panelsElements.forEach((element) => element?.setAttribute('hidden', ''));\r\n\r\n/**\r\n * Shows all elements in the `panelsElements` array.\r\n * Removes the `hidden` attribute to make the elements visible.\r\n */\r\nconst showPanels = () => panelsElements.forEach((element) => element?.removeAttribute('hidden'));\r\n\r\n/**\r\n * Checks if the result type is `Builders`.\r\n *\r\n * @param {string} resultType - The current result type from the store.\r\n * @returns {boolean} - True if `resultType` equals `ResultType.Builders`.\r\n */\r\nconst isBuildersResultType = (resultType) => resultType === ResultType.Builders.toString();\r\n\r\n/**\r\n * Checks if the result type is not `Builders`.\r\n *\r\n * @param {string} resultType - The current result type from the store.\r\n * @returns {boolean} - True if `resultType` does not equal `ResultType.Builders`.\r\n */\r\nconst isNotBuildersResultType = (resultType) => !isBuildersResultType(resultType);\r\n\r\n/**\r\n * Observable stream that emits the current `ResultType` from the store whenever it changes.\r\n *\r\n * - `map(selectResultsType)`: Extracts the `ResultType` from the Redux store's state.\r\n * - `distinctUntilChanged()`: Emits only when the `ResultType` changes to a new value.\r\n */\r\nconst onResultTypeChange$ = store$.pipe(map(selectResultsType), distinctUntilChanged());\r\n\r\n// Subscribes to the `onResultTypeChange$` stream and hides panels if the result type is `Builders`.\r\nonResultTypeChange$.pipe(filter(isBuildersResultType)).subscribe(hidePanels);\r\n\r\n// Subscribes to the `onResultTypeChange$` stream and shows panels if the result type is not `Builders`.\r\nonResultTypeChange$.pipe(filter(isNotBuildersResultType)).subscribe(showPanels);\r\n","/*\r\n * This module will call the form certifier 3rd party\r\n * called ActiveProspect. For details:\r\n * https://developers.activeprospect.com/docs/trustedform/overview/.\r\n * When executed, a set of inputs will be submitted in every\r\n * lead, so we can post a secret token that confirms the\r\n * authenticity of the lead in terms of the 3rd party.\r\n * These inputs will contain Ids that are used to give\r\n * traceability to the leads requested from NHS and make sure\r\n * they come from a real user.\r\n */\r\n(function handlerTrustedForm(global) {\r\n \r\n\r\n global.NewHomeSource = global.NewHomeSource || {};\r\n const queryScript = 'nhs_scriptTrustedForm';\r\n const eventToAttach = Object.prototype.hasOwnProperty.call(global, 'ontouchstart') ? 'touchend' : 'mousedown';\r\n\r\n /**\r\n * @constructs NewHomeSource.TrustedForm\r\n */\r\n function TrustedForm() {\r\n }\r\n\r\n /**\r\n * @private\r\n * attachEvent: attach event to load script.\r\n *\r\n * @param {Event} event with the information of current target.\r\n */\r\n function attachEvent(event) {\r\n if (event.target.dataset.trustedForm) {\r\n TrustedForm.load();\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * executeMethod: observe when input on form is already in the DOM to make the request.\r\n *\r\n * @param {Function} callback to be executed when trusted form is ready.\r\n */\r\n function executeMethod(callback) {\r\n const xxTrustedFormCertUrl = document.querySelector(\"[name='xxTrustedFormCertUrl']\");\r\n if (xxTrustedFormCertUrl) {\r\n callback();\r\n } else {\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (!mutation.addedNodes) { return; }\r\n\r\n for (let i = 0; i < mutation.addedNodes.length; i += 1) {\r\n if (mutation.addedNodes[i].id === 'xxTrustedFormCertUrl_0') {\r\n observer.disconnect();\r\n callback();\r\n break;\r\n }\r\n }\r\n });\r\n });\r\n observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n attributes: false,\r\n characterData: false\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * load: download the script of trusted form\r\n *\r\n * @param {Function} callback to be executed after all is ready.\r\n */\r\n TrustedForm.load = function (callback) {\r\n if (document.querySelector('#' + queryScript)) {\r\n if (typeof callback === 'function') {\r\n callback();\r\n }\r\n return;\r\n }\r\n const field = 'xxTrustedFormCertUrl';\r\n const provideReferrer = false;\r\n const invertFieldSensitivity = false;\r\n const tf = document.createElement('script');\r\n tf.type = 'text/javascript';\r\n tf.async = true;\r\n tf.id = queryScript;\r\n tf.src = document.location.protocol + '//api.trustedform.com/trustedform.js?provide_referrer=' +\r\n escape(provideReferrer) + '&field=' + escape(field) + '&l=' + new Date().getTime() + Math.random() +\r\n '&invert_field_sensitivity=' + invertFieldSensitivity;\r\n document.head.appendChild(tf);\r\n\r\n if (typeof callback === 'function') {\r\n tf.addEventListener('load', executeMethod.bind(this, callback));\r\n }\r\n };\r\n\r\n global.NewHomeSource.TrustedForm = TrustedForm;\r\n document.addEventListener(eventToAttach, attachEvent);\r\n\r\n return TrustedForm;\r\n}(window));\r\n","/*\r\n * This module is in charge of presenting users with results in close proximity to their current location.\r\n * When users select this option, they are prompted to provide permission for access to their current location.\r\n * Upon receiving permission, NewHomeSource then displays results near to the user's exact location.\r\n*/\r\nimport { store, store$ } from '@redux/store';\r\nimport { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators';\r\nimport { updateMapCenter, updateMinimumZoomLevel } from 'libraries/mapLibrary';\r\nimport { mapStateActions } from 'features/searchResultsMap';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { selectCurrentLocationSearchInformation } from '../redux/selectors';\r\n\r\n/*\r\n Settings to consider for aproximity searches to optimize the site's performance.\r\n For instance, we tune the map's zoom level in advance of initiating a rectangular area search\r\n to prevent overloading the database with a large area from which to retrieve results.\r\n*/\r\nconst currentLocationSearchSettings = {\r\n maxZoom: 9,\r\n latitude: null,\r\n longitude: null,\r\n};\r\n\r\nconst mapViewButton = document.querySelector(\"#btn-map-view\");\r\n\r\n/**\r\n * fetchCurrentLocationResults: takes the coordinates of the map's current viewport and uses them to\r\n * update the location parameters from the state which will trigger an update on the page results.\r\n */\r\nconst fetchCurrentLocationResults = () => {\r\n store.dispatch(mapStateActions.enableSearchWithinMap({}));\r\n};\r\n\r\n/**\r\n * toggleCurrentLocationSearchFlag: dispatches an action to the search parameters state indicating wether the user\r\n * is driving a current location search.\r\n * @param currentSearchParameters - object representing the search parameters from the store.\r\n */\r\nconst toggleCurrentLocationSearchFlag = (isCurrentLocationSearch) => {\r\n store.dispatch(searchParametersActions.toggleCurrentLocationSearch(isCurrentLocationSearch));\r\n};\r\n\r\n/**\r\n * displayMapView: in small devices, we don't show the map untill we click the toggle map view button.\r\n * When doing a proximity search, we need to show the map instead of list view by design, so we toggle\r\n * views in this function.\r\n */\r\nconst displayMapView = () => {\r\n if (mapViewButton?.dataset.state === 'map') {\r\n mapViewButton?.click();\r\n }\r\n}\r\n\r\n/**\r\n * handleLocationPermissionGranted: when the user grants NewHomeSource access to their current location,\r\n * this function receives the location information. If the user's location is within the United States of America,\r\n * the map center will adjust to the user's current location.\"\r\n * @param geolocation - object representing the user's current position in terms of navigator.geolocation API.\r\n */\r\nconst handleLocationPermissionGranted = async (geolocation) => {\r\n currentLocationSearchSettings.latitude = geolocation.coords.latitude;\r\n currentLocationSearchSettings.longitude = geolocation.coords.longitude;\r\n displayMapView();\r\n sessionStorage.setItem('geolocationPermission', true);\r\n toggleCurrentLocationSearchFlag(true);\r\n}\r\n\r\n/**\r\n * handleLocationPermissionDenied: when the user dennies NewHomeSource access to their current location,\r\n * this function handles the next steps to follow like showing an information message indicating that\r\n * permissions where not granted.\r\n */\r\nconst handleLocationPermissionDenied = () => {\r\n sessionStorage.setItem('geolocationPermission', false);\r\n const errorContainer = document.querySelector('[data-current-location-permission-denied-error]');\r\n const searchInput = errorContainer.closest('form');\r\n\r\n searchInput.classList.add('error');\r\n errorContainer.style.display = 'block';\r\n}\r\n\r\n/**\r\n * getCurrentLocation: Requests permission from the user to access their current location and executes\r\n * a callback for both granted and denied permission scenarios.\r\n */\r\nconst getCurrentLocation = (event) => {\r\n if (event?.target?.matches('[data-current-location-search]')) {\r\n navigator.geolocation.getCurrentPosition(handleLocationPermissionGranted, handleLocationPermissionDenied);\r\n }\r\n}\r\n\r\n/**\r\n * onCurrentLocationSearch: triggers a rectangular area search so listings near by the\r\n * user's current location gets fetched.\r\n */\r\nconst onCurrentLocationSearch = () => {\r\n updateMapCenter({\r\n latitude: currentLocationSearchSettings.latitude,\r\n longitude: currentLocationSearchSettings.longitude\r\n });\r\n updateMinimumZoomLevel(currentLocationSearchSettings.maxZoom);\r\n toggleCurrentLocationSearchFlag(false);\r\n fetchCurrentLocationResults();\r\n}\r\n\r\n/**\r\n * Subscribing to the store$ observable to listen for changes.\r\n * When the map coordinates have changed, checks if the user is searching by current location.\r\n * If that is the case run the onCurrentLocationSearch function.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectCurrentLocationSearchInformation),\r\n filter((information) => information.isCurrentLocationSearch),\r\n filter((information) => information.isMapReady),\r\n filter((information) => information.geographicCoordinates),\r\n distinctUntilChanged(),\r\n debounceTime(100)\r\n )\r\n .subscribe(onCurrentLocationSearch);\r\n\r\n// Event delegation for current location searches. Right now only typeahead has the option to search by\r\n// current location but we are ready in case they ask for it in another place like a search pill or similar.\r\n document.body.addEventListener('click', getCurrentLocation);\r\n","class HamburgerMenu {\r\n constructor(configuration) {\r\n const { toggleButton, content} = configuration;\r\n this.content = content;\r\n toggleButton.addEventListener('change', this.toggleButtonHandler.bind(this));\r\n }\r\n\r\n /**\r\n * toggleButtonHandler: Handles when the toggle button checked changes.\r\n * @param {Event} event Change event related to the hamburger menu toggle button.\r\n */\r\n toggleButtonHandler(event) {\r\n if (!event.target.checked) {\r\n const accordionMenuToggles = this.content.querySelectorAll('[data-menu-accordion-toggle]');\r\n accordionMenuToggles.forEach(menuToggle => {\r\n menuToggle.checked = false;\r\n });\r\n }\r\n\r\n // emit a custom event when the menu is opened\r\n const customEvent = new CustomEvent('hamburgerMenuClicked', {\r\n detail: { data: {\r\n isOpen: event.target.checked\r\n } }\r\n });\r\n document.body.dispatchEvent(customEvent);\r\n }\r\n}\r\n\r\nexport default HamburgerMenu;","import HamburgerMenu from \"@components/hamburgerMenu/\";\r\n\r\nconst content = document.querySelector('[data-hamburger-menu-content]');\r\nconst toggleButton = document.querySelector('[data-hamburger-menu-toggle]');\r\n\r\nconst configuration = {\r\n toggleButton,\r\n content,\r\n}\r\n\r\n// eslint-disable-next-line no-new\r\nnew HamburgerMenu(configuration);\r\n\r\nconst findAHomeSubmenu = document.querySelector('[data-find-a-home]');\r\nconst resourcesSubmenu = document.querySelector('[data-resources]');\r\n\r\n/**\r\n * accordionToggleHandle: Handles when some accordion menu opens or closes.\r\n * @param {Event} event Change event related to the opening or closing accordion menu.\r\n */\r\nfunction accordionToggleHandle(event, container) {\r\n const accordionMenus = container.querySelectorAll('[data-menu-accordion-toggle]');\r\n accordionMenus.forEach(menu => {\r\n if (!event.target.isSameNode(menu)) {\r\n menu.checked = false;\r\n }\r\n });\r\n}\r\n\r\nfindAHomeSubmenu.addEventListener('change', (event) => accordionToggleHandle(event, findAHomeSubmenu));\r\nresourcesSubmenu.addEventListener('change', (event) => accordionToggleHandle(event, resourcesSubmenu));\r\n","import { store$ } from '@redux/store';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectFetchResultListingsStatus } from 'features/searchResultsFacets';\r\nimport { selectLoading, selectResourcesHostNames } from 'layout/redux/selectors';\r\nimport { distinctUntilChanged, filter, first, fromEvent, map } from 'rxjs';\r\nimport generateRandomNumber from 'utils/randomNumber';\r\n\r\n/** An observable that emits the resourcesHostNames value from the Redux store whenever\r\n * the loading status is succeeded.\r\n */\r\nconst resourcesHostNames$ = store$.pipe(\r\n filter((state) => selectLoading(state) === LoadingStatus.Succeeded.toString()),\r\n map(selectResourcesHostNames),\r\n distinctUntilChanged()\r\n);\r\n\r\n/**\r\n * Generates a random number and returns a URL string for a lifestyle image based on that number.\r\n * @param imageResizeService - is a string representing the domain Image Resize Service.\r\n * @returns a string that represents the URL of a randomly selected lifestyle image.\r\n */\r\nconst getLifeStyleImage = (imageResizeService) => {\r\n const randomNumber = generateRandomNumber(1, 20);\r\n return `${imageResizeService}/images/Lifestyle/lifestyle_${randomNumber}.jpg`;\r\n};\r\n\r\n/**\r\n * Returns the URL of a placeholder image for a brand logo.\r\n * @param staticImagesHostName - is a string that represents the domain or URL where the resource files are located.\r\n */\r\nconst getBrandLogoPlaceholderImage = (staticImagesHostName) =>\r\n `${staticImagesHostName}/GlobalResources23/images/icons/builderLogo.png`;\r\n\r\n/**\r\n * Removes all `` elements within the closest `` element of a given image.\r\n * @param image - is a reference to an HTML `img` element.\r\n */\r\nconst removeSource = (image) => {\r\n const picture = image.closest('picture');\r\n if (picture) {\r\n picture.querySelectorAll('source').forEach((element) => element.remove());\r\n }\r\n};\r\n\r\n/**\r\n * Replaces the source of an image element with a placeholder image if the original image fails to load.\r\n * @param image - is the HTML `img` element that needs to be replaced with a new image source in case of an error.\r\n * @param resourcesHostNames - is an object that contains the IRS and resource domain URLs.\r\n */\r\nconst onErrorImage = (image, resourcesHostNames) => {\r\n const { staticImagesHostName, imageResizeService } = resourcesHostNames;\r\n removeSource(image);\r\n const imageSrc =\r\n 'brandLogo' in image.dataset\r\n ? getBrandLogoPlaceholderImage(staticImagesHostName)\r\n : getLifeStyleImage(imageResizeService);\r\n image.src = imageSrc;\r\n image.onerror = null;\r\n};\r\n\r\n/**\r\n * Returns an observable that emits the first error event from a given element.\r\n * @param element - is the DOM element on which the `error` event is being listened to.\r\n */\r\nconst getErrorEvent = (element) =>\r\n fromEvent(element, 'error').pipe(\r\n map((event) => event.target),\r\n first()\r\n );\r\n\r\n/**\r\n * Attaches an error event listener to lazy-loaded images and calls the `onErrorImage` function when an error occurs.\r\n * @param resourcesHostNames - is an object that contains onfiguration settings for handling errors in\r\n * lazy-loaded images.\r\n */\r\nconst handlerErrorInLazyImages = (resourcesHostNames) => {\r\n const imagesToAttachErrorEvent = document.querySelectorAll('[data-list-view-element] img:not([data-error=\"true\"])');\r\n imagesToAttachErrorEvent.forEach((image) => {\r\n const onError$ = getErrorEvent(image);\r\n onError$.subscribe((imageWithError) => onErrorImage(imageWithError, resourcesHostNames));\r\n });\r\n};\r\n\r\n/**\r\n * Handles errors in eager-loaded images.\r\n * @param resourcesHostNames - is an object that contains configuration settings for handling resources,\r\n * such as images.\r\n */\r\nconst handlerErrorInEagerImages = (resourcesHostNames) => {\r\n const imagesWithError = document.querySelectorAll('[data-list-view-element] [data-error=\"true\"]');\r\n imagesWithError.forEach((image) => onErrorImage(image, resourcesHostNames));\r\n};\r\n\r\n/**\r\n * Handles errors in both eager and lazy images.\r\n */\r\nconst handlerError = () => {\r\n resourcesHostNames$.subscribe(handlerErrorInEagerImages);\r\n resourcesHostNames$.subscribe(handlerErrorInLazyImages);\r\n};\r\n\r\n/**\r\n * Subscribing to the store$ observable to listen for changes.\r\n * When the selectFetchResultListingsStatus changes, we need to validate if the status is Succeeded\r\n * to handler the error of the images.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectFetchResultListingsStatus),\r\n distinctUntilChanged(),\r\n filter((status) => status === LoadingStatus.Succeeded)\r\n )\r\n .subscribe(handlerError);\r\n\r\n// Handler the error of the images in initial load.\r\nhandlerError();\r\n","/**\r\n * The function generates a random number between a given minimum and maximum value.\r\n * @param min - The minimum value that the random number can be.\r\n * @param max - The maximum value that the random number can be.\r\n * @returns a random integer between the minimum and maximum values provided as arguments.\r\n */\r\nexport default function generateRandomNumber(min, max) {\r\n const random = Math.random();\r\n return Math.floor(random * (max - min + 1)) + min;\r\n}\r\n","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getCommunitiesResults } from 'constants/routes'\r\n\r\nfunction getResults(payload) {\r\n const url = `${getCommunitiesResults}`;\r\n\r\n return fromFetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n searchCommand: {\r\n ...payload.searchParameters\r\n },\r\n selectedMarkerId: payload.selectedMarkerId\r\n }),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'image/webp'\r\n }\r\n }).pipe(\r\n switchMap((response) => response.text())\r\n );\r\n}\r\n\r\nexport default getResults;\r\n","import { fromEvent } from \"rxjs\";\r\nimport { store } from \"@redux/store\";\r\nimport { totalDeliveryValueActions } from \"features/totalDeliveryValue\";\r\n\r\nconst getDataset = (element) => element.dataset;\r\n\r\nconst firedCommunitiesResultsEvents = () => {\r\n const elements = document.querySelectorAll('[data-tdv-label=\"COMR\"]');\r\n if (elements.length === 0) {\r\n return;\r\n }\r\n\r\n store.dispatch(totalDeliveryValueActions.fireTdvEvent({\r\n event: 'COMR',\r\n datasets: Array.from(elements).map(getDataset)\r\n }));\r\n};\r\n\r\nconst firedHomesResultsEvents = () => {\r\n const elements = document.querySelectorAll('[data-tdv-label=\"HOMEHR\"]');\r\n if (elements.length === 0) {\r\n return;\r\n }\r\n\r\n store.dispatch(totalDeliveryValueActions.fireTdvEvent({\r\n event: 'HOMEHR',\r\n datasets: Array.from(elements).map(getDataset)\r\n }));\r\n};\r\n\r\nconst firedMasterPlanEvents = () => {\r\n const elements = document.querySelectorAll('[data-tdv-label=\"MPC_Result\"]');\r\n if (elements.length === 0) {\r\n return;\r\n }\r\n\r\n store.dispatch(totalDeliveryValueActions.fireTdvEvent({\r\n event: 'MPC_Result',\r\n datasets: Array.from(elements).map(getDataset)\r\n }));\r\n};\r\n\r\nconst trackEvents = () => {\r\n firedCommunitiesResultsEvents();\r\n firedHomesResultsEvents();\r\n firedMasterPlanEvents();\r\n}\r\n\r\nfromEvent(window, 'load').subscribe(trackEvents);\r\n\r\nexport default trackEvents;","const hiddeHeaderSection = () => {\r\n const resultsContainer = document.querySelector('[data-search-results-content]');\r\n const isNoResultSectionVisible = !!document.querySelector('[data-no-result=\"true\"]');\r\n const hiddenSections = document.querySelectorAll('[data-hidden-section]');\r\n\r\n if (!isNoResultSectionVisible) {\r\n hiddenSections.forEach(element => element.removeAttribute('hidden'));\r\n resultsContainer.classList.remove('nhs-c-wrapper--no-results', 'nhs-mq-wrapper--no-results-medium');\r\n return;\r\n }\r\n\r\n hiddenSections.forEach(element => element.setAttribute('hidden', ''));\r\n resultsContainer.classList.add('nhs-c-wrapper--no-results', 'nhs-mq-wrapper--no-results-medium');\r\n};\r\n\r\nexport default hiddeHeaderSection;","/**\r\n * ListViewHandler is a module in charge of rendering results in the grid where cards are shown to the user.\r\n */\r\nimport { store, store$ } from '@redux/store';\r\nimport { selectResultsPresentationType } from 'layout/redux/selectors';\r\nimport {\r\n searchParametersActions,\r\n selectSearchModifiers,\r\n getResults$,\r\n selectSearchParameters,\r\n selectResultType,\r\n ResultType,\r\n} from 'features/searchResultsFacets';\r\nimport { catchError, distinctUntilChanged, filter, map, of, shareReplay, switchMap } from 'rxjs';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport fastdom from 'fastdom';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport trackEvents from './eventTracking/totalDeliveryValue';\r\nimport onListViewPaint from '../redux/actions';\r\nimport hiddeHeaderSection from './noResults/handlerNoResultsSection';\r\nimport { selectResultsLoadedAndResultsPresentationType, selectSelectedMarker } from '../redux/selectors';\r\n\r\n/**\r\n * loadResults: inserts the more recent loaded results in the grid view.\r\n */\r\nconst loadResults = ({ presentationType, results }) => {\r\n const element = document.querySelector('[data-list-view-element]');\r\n\r\n if (presentationType === ResultPresentationType.InfiniteScrolling.toString()) {\r\n const result = document.createRange().createContextualFragment(results);\r\n element.appendChild(result);\r\n } else {\r\n element.innerHTML = results;\r\n }\r\n\r\n store.dispatch(onListViewPaint());\r\n};\r\n\r\n/**\r\n * loadingResult$ observes and emits a value every time we are loading results.\r\n */\r\nconst loadingResult$ = store$.pipe(\r\n filter(\r\n (state) =>\r\n selectResultType(state) !== ResultType.Communities.toString() ||\r\n selectSelectedMarker(state)?.marker === null ||\r\n selectSelectedMarker(state)?.marker === undefined\r\n ),\r\n map(selectResultsLoadedAndResultsPresentationType),\r\n distinctUntilChanged(),\r\n filter((information) => information.fetchListingStatus?.name === LoadingStatus.Loading.toString()),\r\n filter((information) => information.presentationType !== ResultPresentationType.InfiniteScrolling.toString())\r\n);\r\n\r\nloadingResult$.subscribe(() =>\r\n fastdom.mutate(() => {\r\n window.scrollTo({\r\n top: 0,\r\n behavior: 'smooth',\r\n });\r\n })\r\n);\r\n\r\n/**\r\n * onLoadingResults$ observes and emits a value to determine when we have to trigger the ajax request in charge of\r\n * bringing new results based in the users' search criteria.\r\n */\r\nconst onLoadingResults$ = store$.pipe(\r\n map(selectSearchModifiers),\r\n distinctUntilChanged(),\r\n filter(({ fetchResultsListingStatus }) => fetchResultsListingStatus?.name === LoadingStatus.Loading.toString())\r\n);\r\n\r\n/**\r\n * onResultLoad$ observes and emits a value when new results are ready from server side.\r\n */\r\nconst onResultLoad$ = onLoadingResults$.pipe(\r\n switchMap(() => {\r\n const state = store.getState();\r\n const payload = {\r\n searchParameters: selectSearchParameters(state),\r\n selectedMarkerId: selectSelectedMarker(state)?.marker?.id,\r\n };\r\n const presentationType = selectResultsPresentationType(state);\r\n const response = {\r\n presentationType,\r\n };\r\n\r\n return getResults$(payload).pipe(\r\n switchMap((data) => {\r\n response.results = data;\r\n\r\n loadResults(response);\r\n store.dispatch(searchParametersActions.fetchResultsListingFulfilled());\r\n\r\n return of(response);\r\n }),\r\n catchError((error) => {\r\n response.results = error;\r\n store.dispatch(searchParametersActions.fetchResultsListingError());\r\n\r\n return of(error);\r\n })\r\n );\r\n }),\r\n shareReplay(1)\r\n);\r\n\r\nonResultLoad$.subscribe(hiddeHeaderSection);\r\nonResultLoad$.subscribe(trackEvents);\r\n","import { store$, store } from '@redux/store';\r\nimport { map, filter, distinctUntilChanged, distinctUntilKeyChanged, withLatestFrom, fromEvent, take } from 'rxjs';\r\nimport objectEquals from 'utils/equals';\r\nimport { selectLocation, selectPaging, selectResultType } from 'features/searchResultsFacets';\r\nimport { isLoading } from 'features/utm';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport { selectNativeAdInformation } from '../redux/selectors';\r\n\r\nconst footerAds = document.querySelectorAll('[data-footer-ad]');\r\n\r\n/**\r\n * handleFooterAds: configures the footer ads's styles and data attributes.\r\n */\r\nconst handleFooterAds = () => {\r\n footerAds.forEach((element) => {\r\n element.dataset.native = 'true';\r\n element.classList.add('nhs-c-card--native-ad-fixed');\r\n element.setAttribute('hidden', '');\r\n });\r\n};\r\n\r\n/**\r\n * A one-time stream will happen in the load window event.\r\n * This is taken into consideration for the handleFooterAds subscriber.\r\n */\r\nfromEvent(window, 'load').pipe(take(1)).subscribe(handleFooterAds);\r\n\r\n/**\r\n * Sets the inner HTML of elements in the `footerAds` array to a specified template and\r\n * adds classes and attributes to them.\r\n * @param ads - object which is used to retrieve the template for the footer ads.\r\n *\r\n * Hides footer ads with a `data-native` attribute set to 'true'.\r\n */\r\nconst hideFooterAds = () =>\r\n footerAds.forEach((element) => {\r\n if (element.dataset.native === 'true') {\r\n element.setAttribute('hidden', '');\r\n delete element.dataset.loaded;\r\n }\r\n });\r\n\r\nlet previousLocation;\r\nlet previousResultType;\r\nlet previousPaging;\r\nconst refreshOrRegenerateNativeAds = () => {\r\n const state = store.getState();\r\n const currentLocation = selectLocation(state);\r\n const currentResultType = selectResultType(state);\r\n const currentPaging = selectPaging(state);\r\n if (window.AppNexus) {\r\n const locationChanged = previousLocation && !objectEquals(currentLocation, previousLocation);\r\n const resultTypeChanged = previousResultType && !objectEquals(currentResultType, previousResultType);\r\n const pagingChanged = previousPaging && !objectEquals(currentPaging, previousPaging);\r\n\r\n if (locationChanged || resultTypeChanged || pagingChanged) {\r\n window.AppNexus.refreshAdsAndUpdateParams();\r\n } else {\r\n window.AppNexus.regenerateAds(true);\r\n }\r\n }\r\n\r\n if (!window.AppNexus) {\r\n require('libraries/appNexus');\r\n }\r\n\r\n previousLocation = currentLocation;\r\n previousResultType = currentResultType;\r\n previousPaging = currentPaging;\r\n};\r\n\r\n/*\r\n * Observable to know when the listing is loaded\r\n */\r\nconst onResultLoad$ = store$.pipe(map(selectNativeAdInformation), distinctUntilKeyChanged('fetchResultListingsStatus'));\r\n\r\n/**\r\n * Observale to check that the Results are ready.\r\n * Triggers the Native Ads insertion on the the SRP with pagination presentation type.\r\n * or Triggers the Native Ads insertion on the the SRP with Infinite scroll presentation type.\r\n */\r\nonResultLoad$\r\n .pipe(filter(({ fetchResultListingsStatus }) => fetchResultListingsStatus === LoadingStatus.Succeeded))\r\n .subscribe(refreshOrRegenerateNativeAds);\r\n\r\nonResultLoad$\r\n .pipe(\r\n filter(({ resultsPresentationType }) => resultsPresentationType === ResultPresentationType.Pagination.toString()),\r\n filter(({ fetchResultListingsStatus }) => fetchResultListingsStatus === LoadingStatus.Loading)\r\n )\r\n .subscribe(hideFooterAds);\r\n\r\n/**\r\n * Observale to check when chaging from Homes or Comms SRP to builder directory.\r\n */\r\nonResultLoad$\r\n .pipe(\r\n filter(\r\n ({ resultsPresentationType }) => resultsPresentationType === ResultPresentationType.InfiniteScrolling.toString()\r\n ),\r\n filter(({ paging }) => paging.page === 1),\r\n filter(({ fetchResultListingsStatus }) => fetchResultListingsStatus === LoadingStatus.Loading)\r\n )\r\n .subscribe(hideFooterAds);\r\n\r\n/**\r\n * Observale to check if the native ads information have changed.\r\n */\r\nconst nativeInformation$ = store$.pipe(map(selectNativeAdInformation), distinctUntilChanged());\r\n\r\n/**\r\n * Observale to check the UTM parameters changes.\r\n */\r\nconst onUtmParameterReady$ = store$.pipe(map(isLoading), filter(Boolean), distinctUntilChanged());\r\n\r\n/**\r\n * Observable for the UTM call ready and the ad state.\r\n */\r\nonUtmParameterReady$\r\n .pipe(\r\n withLatestFrom(nativeInformation$),\r\n map(([, nativeInformation]) => nativeInformation),\r\n filter(\r\n ({ resultsPresentationType }) =>\r\n resultsPresentationType === ResultPresentationType.Pagination.toString() ||\r\n resultsPresentationType === ResultPresentationType.InfiniteScrolling.toString()\r\n )\r\n )\r\n .subscribe(refreshOrRegenerateNativeAds);\r\n","import { store$ } from '@redux/store';\r\nimport { map, filter, distinctUntilChanged, withLatestFrom } from 'rxjs';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectAppliedFacets, selectFetchResultListingsStatus } from 'features/searchResultsFacets';\r\n\r\n/**\r\n * showNoFiltersHintsSection: when the user sees the no results because of landing in a location where there is\r\n * nothing to show, meaning: there were no filters applied that lead the search to no results, then the hints\r\n * section should show a different order on it's hints so the user follow the suggestion in a logical order.\r\n * The first hint in the section is to clear filters to see more results, but if the user landed in a location\r\n * where no results, then that hint is placed last and we preffer other hints more valuable for the situation\r\n * the user is facing.\r\n */\r\nconst showNoFiltersHintsSection = ({ filtersHintsSection, noFiltersHintsSection }) => {\r\n noFiltersHintsSection.removeAttribute('hidden');\r\n filtersHintsSection.setAttribute('hidden', '');\r\n};\r\n\r\n/**\r\n * listening to changes on the store. When filters are applied, this observable will emit an array of the\r\n * current active filters in the search results page.\r\n */\r\nconst onFiltersApplied$ = store$.pipe(map(selectAppliedFacets), distinctUntilChanged());\r\n\r\n/**\r\n * listening to changes on the store. When new results arrived to the search results page, this observable\r\n * will emit a \"Succeeded\" status that indicates new data is available for the user.\r\n */\r\nconst onNewResutsShown$ = store$.pipe(\r\n map(selectFetchResultListingsStatus),\r\n distinctUntilChanged(),\r\n filter(\r\n (fetchResultListingsStatus) =>\r\n fetchResultListingsStatus === LoadingStatus.Succeeded || fetchResultListingsStatus === LoadingStatus.Idle\r\n )\r\n);\r\n\r\n/**\r\n * this is a combination of onNewResutsShown$ and onFiltersApplied$ observables. The intention is to determine\r\n * if the no results page is shown by querying the DOM searching for the clear filters button of this page. If\r\n * the button is present in the DOM, then we consider the latest filters applied, if there was at least 1 filter\r\n * applied that means the user ended up in the no results page by applying filters, so we emit a value indicating\r\n * we have to set up the clear filters button by executing the initClearFilterButton function.\r\n */\r\nonNewResutsShown$\r\n .pipe(\r\n withLatestFrom(onFiltersApplied$),\r\n map(([, filtersApplied]) => ({\r\n filtersHintsSection: document.querySelector('[data-filter-applied-hints]'),\r\n noFiltersHintsSection: document.querySelector('[data-no-filter-applied-hints]'),\r\n filtersAppliedCount: filtersApplied.length,\r\n })),\r\n filter(({ filtersAppliedCount }) => filtersAppliedCount === 0),\r\n filter(({ filtersHintsSection }) => !!filtersHintsSection),\r\n filter(({ noFiltersHintsSection }) => !!noFiltersHintsSection)\r\n )\r\n .subscribe(showNoFiltersHintsSection);\r\n","/*\r\n* This module is in charge of handling clicks in clear filter button of no result page experience.\r\n*/\r\nimport { store } from '@redux/store';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\n\r\n/**\r\n * clearFilters: dispatches a clearFilters action in the searchParametersActions.\r\n */\r\nconst clearFilters = (event) => {\r\n if (!event.target || !Object.prototype.hasOwnProperty.call(event.target.dataset, 'noResultsClearButton')) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n store.dispatch(searchParametersActions.clearFilters());\r\n}\r\n\r\ndocument.addEventListener('click', clearFilters);","import {\r\n LocationType,\r\n PlanStatus,\r\n ProductType,\r\n ResultType,\r\n UrlSubdirectoryTypes,\r\n getInventoryStatusCombination,\r\n searchParametersActions,\r\n selectMarketingStatus,\r\n} from 'features/searchResultsFacets';\r\nimport MarketingStatus from 'enums/marketingStatus';\r\nimport { store } from '@redux/store';\r\nimport PillType from '../enums/popularPillsType';\r\n\r\nconst supportedLocationTypes = [LocationType.Market.toString(), LocationType.City.toString()];\r\n\r\n/**\r\n * Dispatches an action to fetch consumer promos based on whether a pill is active or not.\r\n * @param isActive - A boolean value indicating whether the hot deals should be checked or not.\r\n */\r\nconst actionOnActiveHotDeals = (isActive) => searchParametersActions.fetchConsumerPromos(isActive);\r\n\r\nconst actionOnInactiveHotDeals = (isActive) => searchParametersActions.fetchConsumerPromos(isActive);\r\n\r\n/**\r\n * Dispatches an action to fetch condos and Townhomes search parameters based on\r\n * whether a pill is active or not.\r\n * @param isActive - A boolean value indicating whether the Towhomes option is active or not.\r\n */\r\nconst updateCondosAndTownhomes = (isActive) => {\r\n const payload = {\r\n resultType: ResultType.Communities.toString(),\r\n productType: ProductType.Communities.toString(),\r\n condosAndTownHomes: isActive,\r\n };\r\n\r\n return searchParametersActions.fetchCondosAndTownHomes(payload);\r\n} \r\n\r\nconst actionOnActiveCondosAndTownhomes = () => updateCondosAndTownhomes(true);\r\n\r\nconst actionOnInactiveCondosAndTownhomes = () => updateCondosAndTownhomes(false);\r\n\r\n\r\n\r\n/**\r\n * Dispatches an action to update the search parameters with the value of `isActive` for the \"active adult\" parameter.\r\n * @param isActive - A boolean value indicating whether the adult content should be included in the\r\n * search results or not.\r\n */\r\nconst actionOnActiveAdult = (isActive) => searchParametersActions.fetchActiveAdult(isActive);\r\n\r\n/**\r\n * Dispatches an action to fetch the marketing status of \"Coming Soon\".\r\n */\r\nconst actionOnActiveComingSoon = () =>\r\n searchParametersActions.fetchMarketingStatus(MarketingStatus.ComingSoon.toString());\r\n\r\n/**\r\n * Dispatches an action to fetch move-in dates for plans with the status \"ReadyToBuild\".\r\n */\r\nconst actionOnActiveFloorPlans = () =>\r\n searchParametersActions.fetchMoveInDateByStatus(PlanStatus.ReadyToBuild.toString());\r\n\r\n/**\r\n * Dispatches an action to fetch the move-in date based on the inventory status combination.\r\n */\r\nconst actionOnActiveQuickMoveIns = () =>\r\n searchParametersActions.fetchMoveInDateByStatus(getInventoryStatusCombination());\r\n\r\n/**\r\n * Dispatches an action to fetch any communities when the \"Adult\" pill is inactive.\r\n */\r\nconst actionOnInactiveAdult = () => searchParametersActions.fetchAnyCommunities();\r\n\r\n/**\r\n * Dispatches an action to fetch marketing status when a pill is inactive.\r\n */\r\nconst actionOnInactiveComingSoon = () => {\r\n const state = store.getState();\r\n const currentMarketingStatus = selectMarketingStatus(state);\r\n const currentMarketingStatusList = currentMarketingStatus.split(',');\r\n\r\n // Filter out the 'Coming Soon' status\r\n const newMarketingStatus = currentMarketingStatusList.filter(\r\n status => status !== MarketingStatus.ComingSoon.toString()\r\n ).join(',');\r\n\r\n return searchParametersActions.fetchMarketingStatus(newMarketingStatus);\r\n}\r\n\r\n/**\r\n * Dispatches an action to clear the move-in date filter in the store.\r\n */\r\nconst actionOnInactiveFloorPlans = () => searchParametersActions.clearMoveInDateFilter();\r\n\r\n/**\r\n * The function clears the move-in date filter when the \"Quick Move-Ins\" pill is inactive.\r\n */\r\nconst actionOnInactiveQuickMoveIns = () => searchParametersActions.clearMoveInDateFilter();\r\n\r\n/**\r\n * This object is the source of truth for which pills should render when users are on a given subDirectory\r\n */\r\nconst pillsByUrlSubdirectory = {\r\n [UrlSubdirectoryTypes.Homes.toString()]: {\r\n [PillType.HotDeals.toString()]: {\r\n name: PillType.HotDeals.name,\r\n text: PillType.HotDeals.text,\r\n onActiveAction: actionOnActiveHotDeals,\r\n onInactiveAction: actionOnInactiveHotDeals,\r\n },\r\n [PillType.QuickMoveIns.toString()]: {\r\n name: PillType.QuickMoveIns.name,\r\n text: PillType.QuickMoveIns.text,\r\n onActiveAction: actionOnActiveQuickMoveIns,\r\n onInactiveAction: actionOnInactiveQuickMoveIns,\r\n },\r\n [PillType.FloorPlans.toString()]: {\r\n name: PillType.FloorPlans.name,\r\n text: PillType.FloorPlans.text,\r\n onActiveAction: actionOnActiveFloorPlans,\r\n onInactiveAction: actionOnInactiveFloorPlans,\r\n },\r\n },\r\n [UrlSubdirectoryTypes.Communities.toString()]: {\r\n [PillType.HotDeals.toString()]: {\r\n name: PillType.HotDeals.name,\r\n text: PillType.HotDeals.text,\r\n onActiveAction: actionOnActiveHotDeals,\r\n onInactiveAction: actionOnInactiveHotDeals,\r\n },\r\n [PillType.CondosAndTownhomes.toString()]: {\r\n name: PillType.CondosAndTownhomes.name,\r\n text: PillType.CondosAndTownhomes.text,\r\n onActiveAction: actionOnActiveCondosAndTownhomes,\r\n onInactiveAction: actionOnInactiveCondosAndTownhomes,\r\n },\r\n [PillType.Adult.toString()]: {\r\n name: PillType.Adult.name,\r\n text: PillType.Adult.text,\r\n onActiveAction: actionOnActiveAdult,\r\n onInactiveAction: actionOnInactiveAdult,\r\n },\r\n [PillType.ComingSoon.toString()]: {\r\n name: PillType.ComingSoon.name,\r\n text: PillType.ComingSoon.text,\r\n onActiveAction: actionOnActiveComingSoon,\r\n onInactiveAction: actionOnInactiveComingSoon,\r\n },\r\n },\r\n [UrlSubdirectoryTypes.CondosAndTownHomes.toString()]: {\r\n [PillType.HotDeals.toString()]: {\r\n name: PillType.HotDeals.name,\r\n text: PillType.HotDeals.text,\r\n onActiveAction: actionOnActiveHotDeals,\r\n onInactiveAction: actionOnInactiveHotDeals,\r\n },\r\n [PillType.QuickMoveIns.toString()]: {\r\n name: PillType.QuickMoveIns.name,\r\n text: PillType.QuickMoveIns.text,\r\n onActiveAction: actionOnActiveQuickMoveIns,\r\n onInactiveAction: actionOnInactiveQuickMoveIns,\r\n },\r\n [PillType.FloorPlans.toString()]: {\r\n name: PillType.FloorPlans.name,\r\n text: PillType.FloorPlans.text,\r\n onActiveAction: actionOnActiveFloorPlans,\r\n onInactiveAction: actionOnInactiveFloorPlans,\r\n },\r\n },\r\n [UrlSubdirectoryTypes.FloorPlans.toString()]: {\r\n [PillType.HotDeals.toString()]: {\r\n name: PillType.HotDeals.name,\r\n text: PillType.HotDeals.text,\r\n onActiveAction: actionOnActiveHotDeals,\r\n onInactiveAction: actionOnInactiveHotDeals,\r\n },\r\n [PillType.QuickMoveIns.toString()]: {\r\n name: PillType.QuickMoveIns.name,\r\n text: PillType.QuickMoveIns.text,\r\n onActiveAction: actionOnActiveQuickMoveIns,\r\n onInactiveAction: actionOnInactiveQuickMoveIns,\r\n },\r\n [PillType.FloorPlans.toString()]: {\r\n name: PillType.FloorPlans.name,\r\n text: PillType.FloorPlans.text,\r\n onActiveAction: actionOnActiveFloorPlans,\r\n onInactiveAction: actionOnInactiveFloorPlans,\r\n },\r\n },\r\n [UrlSubdirectoryTypes.CondoDevelopment.toString()]: {\r\n [PillType.HotDeals.toString()]: {\r\n name: PillType.HotDeals.name,\r\n text: PillType.HotDeals.text,\r\n onActiveAction: actionOnActiveHotDeals,\r\n onInactiveAction: actionOnInactiveHotDeals,\r\n },\r\n [PillType.CondosAndTownhomes.toString()]: {\r\n name: PillType.CondosAndTownhomes.name,\r\n text: PillType.CondosAndTownhomes.text,\r\n onActiveAction: actionOnActiveCondosAndTownhomes,\r\n onInactiveAction: actionOnInactiveCondosAndTownhomes,\r\n },\r\n [PillType.Adult.toString()]: {\r\n name: PillType.Adult.name,\r\n text: PillType.Adult.text,\r\n onActiveAction: actionOnActiveAdult,\r\n onInactiveAction: actionOnInactiveAdult,\r\n },\r\n [PillType.ComingSoon.toString()]: {\r\n name: PillType.ComingSoon.name,\r\n text: PillType.ComingSoon.text,\r\n onActiveAction: actionOnActiveComingSoon,\r\n onInactiveAction: actionOnInactiveComingSoon,\r\n },\r\n },\r\n};\r\n\r\n/**\r\n * Returns the pills that should render.\r\n * @param urlSubdirectory The url subdirectory that we want to render pills on.\r\n */\r\nexport function getPopularSearchesPillsForUrlSubdirectory(urlSubdirectory) {\r\n const popularPillsBySubdirectory = pillsByUrlSubdirectory[urlSubdirectory];\r\n const pillsByUrlToRender = { ...popularPillsBySubdirectory }\r\n\r\n return pillsByUrlToRender;\r\n}\r\n\r\n/**\r\n * The function `getPillsByCounts` takes a URL subdirectory and an array of pill types with counts, and\r\n * returns an array of pill details for the given URL subdirectory. Also, the pill could be set as\r\n * disabled if it does not have results to display, it is defined in `pillsWithCounts`. \r\n * @param urlSubdirectory - The `urlSubdirectory` parameter is a string that represents the\r\n * subdirectory of a URL. It is used to retrieve the popular searches pills for that specific\r\n * subdirectory.\r\n * @param pillsWithCounts - An array with the pills types that contians counts.\r\n * @returns an array of pill details based on the given URL subdirectory and pill types with counts.\r\n */\r\nexport function getPillsByCounts(urlSubdirectory, pillsWithCounts, locationType) {\r\n const pillsDetails = getPopularSearchesPillsForUrlSubdirectory(urlSubdirectory);\r\n if (!pillsDetails || !supportedLocationTypes.includes(locationType)) {\r\n return [];\r\n }\r\n\r\n // if the Pill is not presented in the `pillsWithCounts` when we perform a comparison\r\n // it will be disabled since it means that the pill does not have results to display. \r\n // Finally, by business rule the disabled pills will go at the end of the list.\r\n const pillsList = Object.values(pillsDetails).map((pill) => {\r\n pill.isEnabled = pillsWithCounts.includes(pill.name);\r\n return pill;\r\n }).sort((secondPill, firstPill) => firstPill.isEnabled - secondPill.isEnabled);\r\n\r\n return pillsList;\r\n}\r\n\r\n/**\r\n * The function `getPillAction` returns the action associated with a pill based on the URL\r\n * subdirectory, pill type, and whether it is active or inactive.\r\n * @param urlSubdirectory - The `urlSubdirectory` parameter is a string that represents the\r\n * subdirectory of a URL.\r\n * @param pillType - The `pillType` parameter represents the type of pill. It is used to access the\r\n * corresponding pill object from the `pills` array.\r\n * @param isActive - A boolean value indicating whether the pill is active or not.\r\n * @returns the action associated with the specified pill type and whether it is active or inactive.\r\n */\r\nexport function getPillAction(urlSubdirectory, pillType, isActive) {\r\n const pills = pillsByUrlSubdirectory[urlSubdirectory];\r\n const pill = pills?.[pillType];\r\n\r\n if (!pill) {\r\n return null;\r\n }\r\n\r\n const action = isActive ? pill.onActiveAction : pill.onInactiveAction;\r\n\r\n return action;\r\n}\r\n","import { closeSmallIconSvg } from 'constants/svg-assets.b1';\r\n\r\n/**\r\n * @classdesc The `Pill` class encapsulates the behavior and properties of a pill in the popular searches pills section.\r\n */\r\nexport default class Pill {\r\n /**\r\n * @param {string} params.name The unique identifier for the pill.\r\n * @param {string} params.text The text to be displayed for the pill.\r\n * @param {boolean} params.isEnabled The boolean to determine whether the pill is disabled or not.\r\n */\r\n constructor({ name, text, isEnabled, isActive }) {\r\n const parser = new DOMParser();\r\n this.name = name;\r\n this.text = text;\r\n this.id = `chk_${this.name}`;\r\n this.isEnabled = isEnabled;\r\n this.isActive = isActive;\r\n this.closeSmallIconSvgElement = parser.parseFromString(closeSmallIconSvg, 'image/svg+xml').documentElement;\r\n }\r\n\r\n /**\r\n * Generates the HTML representation of the pill based on constructed values.\r\n * @returns {string} The HTML string for the pill.\r\n */\r\n getHtml() {\r\n return ``;\r\n }\r\n\r\n getClose() {\r\n if (this.isActive) {\r\n return `\r\n ${this.closeSmallIconSvgElement.cloneNode(true).outerHTML}\r\n `;\r\n }\r\n\r\n return '';\r\n }\r\n\r\n /**\r\n * Retrieves the HTML element associated with the pill.\r\n * @returns {HTMLElement|null} The pill's HTML element or null if not found.\r\n */\r\n getNode() {\r\n return document?.getElementById(this.id);\r\n }\r\n\r\n /**\r\n * Checks the pill by adding the 'active' class.\r\n */\r\n check() {\r\n const pillNode = this.getNode();\r\n if (pillNode) {\r\n pillNode.checked = true;\r\n }\r\n }\r\n\r\n /**\r\n * Unchecks the pill by removing the 'active' class.\r\n */\r\n uncheck() {\r\n const pillNode = this.getNode();\r\n if (pillNode) {\r\n pillNode.checked = false;\r\n }\r\n }\r\n}\r\n","import { filter, fromEvent, map } from 'rxjs';\r\nimport fastdom from 'fastdom';\r\nimport Pill from './pill';\r\n\r\n/**\r\n * @classdesc A class representing a component for managing the popular searches pills section.\r\n */\r\nexport default class PillsSection {\r\n /**\r\n * Creates an instance of PillsSection and connects it to what is currently on the DOM.\r\n * @param {string} popularSearchesPillsSelector The selector to identify the popular searches pills section.\r\n */\r\n constructor(popularSearchesPillsSelector) {\r\n this.popularSearchesPills = document?.querySelector(popularSearchesPillsSelector);\r\n this.pills = {};\r\n this.marginLeftArrowClass = 'nhs-u-margin--left-650';\r\n\r\n if (!this.popularSearchesPills) {\r\n throw new Error(`Popular searches pills section with selector '${popularSearchesPillsSelector}' not found.`);\r\n }\r\n\r\n // Select child elements that we need to control\r\n this.pillsList = this.popularSearchesPills?.querySelector('[data-popular-searches-pills-list]');\r\n this.scrollLeftButton = this.popularSearchesPills?.querySelector('[data-popular-searches-pills-button-left]');\r\n this.scrollRightButton = this.popularSearchesPills?.querySelector('[data-popular-searches-pills-button-right]');\r\n\r\n if (!this.pillsList || !this.scrollLeftButton || !this.scrollRightButton) {\r\n throw new Error('One or more required DOM elements inside the popular searches pills section are missing.');\r\n }\r\n\r\n // Scroll left or right on button clicks\r\n this.scrollLeftButton.addEventListener('click', () => {\r\n this.scrollHorizontally(-100);\r\n });\r\n\r\n this.scrollRightButton.addEventListener('click', () => {\r\n this.scrollHorizontally(100);\r\n });\r\n\r\n // Update left button visibility when scrolling pillsList.\r\n this.pillsList.addEventListener('scroll', () => {\r\n this.updateChildElementsVisibility();\r\n });\r\n\r\n // Initially, check and set the visibility of the left button\r\n this.setRigthLimit();\r\n this.updateChildElementsVisibility();\r\n this.attachPillListEvents();\r\n\r\n const onResize$ = fromEvent(window, 'resize');\r\n onResize$.subscribe(this.setRigthLimit.bind(this));\r\n onResize$.subscribe(this.updateChildElementsVisibility.bind(this));\r\n }\r\n\r\n /**\r\n * Updates pill elements based on the provided pillsDetails.\r\n * @param {{ name, text }} pillsDetails Details of the pills to be rendered.\r\n * @param Object popularPillFilters contains filters for each pill type\r\n */\r\n updatePillsOnDOM(pillsDetails, popularPillFilters) {\r\n this.pills = {};\r\n pillsDetails.forEach(({ name, text, isEnabled }) => {\r\n const isActive = popularPillFilters[name];\r\n const pill = new Pill({ name, text, isEnabled, isActive });\r\n this.pills[name] = pill;\r\n });\r\n\r\n fastdom.mutate(() => {\r\n this.pillsList.innerHTML = this.getHtmlPills();\r\n this.setRigthLimit();\r\n this.updateChildElementsVisibility();\r\n this.updatePillStatus(popularPillFilters);\r\n this.show();\r\n });\r\n }\r\n\r\n /**\r\n * Returns the activated pills text value selected on the page.\r\n */\r\n getActivatedPillsText() {\r\n const pillsActive = Array.from(\r\n this.pillsList.querySelectorAll('[data-popular-searches-pill-type]:checked ~ label')\r\n );\r\n const textPills = pillsActive.map((pill) => pill.innerText);\r\n\r\n return textPills;\r\n }\r\n\r\n /**\r\n * Sets the right limit of the scroll element to check when there is no more option to scroll.\r\n */\r\n setRigthLimit() {\r\n requestAnimationFrame(() => {\r\n this.limitRight = this.pillsList.getBoundingClientRect().right;\r\n });\r\n }\r\n\r\n /**\r\n * Returns the HTML representation of all the pills in an object.\r\n * @returns a string that represents the HTML pill elements.\r\n */\r\n getHtmlPills() {\r\n return Object.values(this.pills)\r\n .map((pill) => pill.getHtml())\r\n .join('');\r\n }\r\n\r\n /**\r\n * It updates the status of pills based on the provided pill filters.\r\n * @param pillFilters - The `pillFilters` parameter is an object that contains filters for each pill\r\n * type. The keys of the object represent the pill types, and the values represent whether the filter\r\n * is enabled or disabled for that pill type.\r\n */\r\n updatePillStatus(pillFilters) {\r\n const { activedPills, inactivedPills } = this.getPillsStatus(pillFilters);\r\n this.activePills(activedPills);\r\n this.inactivePills(inactivedPills);\r\n }\r\n\r\n /**\r\n * It takes in a `pillFilters` object and returns an object with two\r\n * arrays, `activePills` and `inactivePills`, which contain the keys of the `pillFilters` object\r\n * based on their values.\r\n * @param pillFilters - The `pillFilters` parameter is an object that contains filters for each pill\r\n * type. Each key in the object represents a pill type, and the corresponding value indicates whether\r\n * the pill is active or not.\r\n * @returns an object with two properties: \"activedPills\" and \"inactivedPills\".\r\n */\r\n getPillsStatus(pillFilters) {\r\n return Object.keys(this.pills).reduce(\r\n (accumulator, pillType) => {\r\n const isPillActive = pillFilters[pillType];\r\n if (isPillActive) {\r\n accumulator.activedPills.push(pillType);\r\n return accumulator;\r\n }\r\n accumulator.inactivedPills.push(pillType);\r\n return accumulator;\r\n },\r\n { activedPills: [], inactivedPills: [] }\r\n );\r\n }\r\n\r\n /**\r\n * It takes an array of pill types and checks each pill type in the \"pills\" object.\r\n * @param pills - The `pills` parameter is an array of pill types.\r\n */\r\n activePills(pills) {\r\n pills.forEach((pillType) => {\r\n this.pills[pillType].check();\r\n });\r\n }\r\n\r\n /**\r\n * It unchecks all the pills of the specified types.\r\n * @param pills - The `pills` parameter is an array that contains the types of pills that need to be\r\n * marked as inactive.\r\n */\r\n inactivePills(pills) {\r\n pills.forEach((pillType) => {\r\n this.pills[pillType].uncheck();\r\n });\r\n }\r\n\r\n /**\r\n * The function attaches click event listeners to a list of pills and dispatches a custom event with\r\n * information about the clicked pill.\r\n */\r\n attachPillListEvents() {\r\n fromEvent(this.pillsList, 'click')\r\n .pipe(\r\n map((event) => event.target.closest('[data-popular-searches-pill-type]')),\r\n filter(Boolean),\r\n map((pill) => ({\r\n pillType: pill.dataset.popularSearchesPillType,\r\n isChecked: pill.checked,\r\n }))\r\n )\r\n .subscribe((information) => {\r\n document.body.dispatchEvent(\r\n new CustomEvent('pillClickEvent', {\r\n detail: {\r\n data: information,\r\n },\r\n })\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Unhides the entire popular searches pills section.\r\n */\r\n show() {\r\n this.popularSearchesPills.removeAttribute('hidden');\r\n }\r\n\r\n /**\r\n * Hides the entire popular searches pills section.\r\n */\r\n hide() {\r\n this.popularSearchesPills.setAttribute('hidden', true);\r\n }\r\n\r\n /**\r\n * Scroll the `pillsList` horizontally.\r\n * @param {number} amount The distance to scroll. Positive values scroll right, negative values scroll left.\r\n */\r\n scrollHorizontally(amount) {\r\n const initialScrollLeft = this.pillsList.scrollLeft;\r\n const targetScrollLeft = initialScrollLeft + amount;\r\n const duration = 500; // Can adjust scroll speed here\r\n const startTime = performance.now();\r\n\r\n const step = (currentTime) => {\r\n const elapsedTime = currentTime - startTime;\r\n if (elapsedTime < duration) {\r\n const newPosition = PillsSection.easeInOut(elapsedTime, initialScrollLeft, amount, duration);\r\n this.pillsList.scrollLeft = newPosition;\r\n requestAnimationFrame(step);\r\n } else {\r\n this.pillsList.scrollLeft = targetScrollLeft;\r\n this.updateChildElementsVisibility();\r\n }\r\n };\r\n\r\n requestAnimationFrame(step);\r\n }\r\n\r\n /**\r\n * Update visibility of left scroll button based on `pillsList` scroll position.\r\n * The \".marginLeft\" let to the left scroll button to have a background white space when the user scroll to the right.\r\n */\r\n updateChildElementsVisibility() {\r\n requestAnimationFrame(() => {\r\n const isListScrolledRight = this.pillsList.scrollLeft !== 0;\r\n\r\n if (isListScrolledRight) {\r\n this.pillsList.classList.add(this.marginLeftArrowClass);\r\n } else {\r\n this.pillsList.classList.remove(this.marginLeftArrowClass);\r\n }\r\n this.scrollLeftButton.style.visibility = isListScrolledRight ? 'visible' : 'hidden';\r\n\r\n if (this.pillsList.lastElementChild?.getBoundingClientRect().right > this.limitRight) {\r\n this.scrollRightButton.style.visibility = 'visible';\r\n } else {\r\n this.scrollRightButton.style.visibility = 'hidden';\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Transition function for smooth scrolling.\r\n * @param {number} time The current time of the transition, in milliseconds.\r\n * @param {number} initialValue The initial value of the transition.\r\n * @param {number} changeValue The total change in value over the duration of the transition.\r\n * @param {number} transitionDuration The total duration of the transition in milliseconds.\r\n * @returns {number} The new value of the transition at the given time.\r\n */\r\n static easeInOut(time, initialValue, changeValue, transitionDuration) {\r\n let newTime = time;\r\n newTime /= transitionDuration / 2;\r\n if (newTime < 1) {\r\n return (changeValue / 2) * newTime * newTime + initialValue;\r\n }\r\n newTime -= 1;\r\n return (-changeValue / 2) * (newTime * (newTime - 2) - 1) + initialValue;\r\n }\r\n}\r\n","import { distinctUntilChanged, fromEvent, map, skip } from 'rxjs';\r\nimport { store, store$ } from '@redux/store';\r\nimport { PillsSection, getPillAction, getPillsByCounts } from 'features/popularSearches';\r\nimport { ResultType, selectResultType } from 'features/searchResultsFacets';\r\nimport { selectUrlSubdirectory } from 'features/routing';\r\nimport GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { selectPopularSearchesPills } from '../redux/selectors';\r\n\r\nconst fetchPillAction = (data) => {\r\n const { pillType, isChecked } = data;\r\n const state = store.getState();\r\n const subdirectoryUrl = selectUrlSubdirectory(state);\r\n const fetchAction = getPillAction(subdirectoryUrl, pillType, isChecked);\r\n if (fetchAction) {\r\n store.dispatch(fetchAction(isChecked));\r\n }\r\n};\r\n\r\nconst click$ = fromEvent(document.body, 'pillClickEvent').pipe(map((event) => event.detail.data));\r\nclick$.subscribe(fetchPillAction);\r\n\r\n// Hydrate a new PillsSection on the initial server-side-rendered popular searches pills elements.\r\nconst popularSearchesPillsSelector = '[data-popular-searches-pills-group]';\r\nconst pillsSection = new PillsSection(popularSearchesPillsSelector);\r\n\r\n/**\r\n * Hides the pillsSection element.\r\n */\r\nconst hidePillsSection = () => pillsSection.hide();\r\n\r\n\r\n/**\r\n * Updates the pills section on the DOM based on the search counts and the current URL subdirectory.\r\n */\r\nfunction onPopularSearchPillsChange({ pillsWithCounts, urlSubdirectory, popularPillFilters, locationType }) {\r\n const popularPillsDetails = getPillsByCounts(urlSubdirectory, pillsWithCounts, locationType);\r\n if (popularPillsDetails?.length) {\r\n pillsSection.updatePillsOnDOM(popularPillsDetails, popularPillFilters);\r\n } else {\r\n hidePillsSection();\r\n }\r\n}\r\n\r\n/**\r\n * Tracks the user events related to activated pills in a\r\n * search interface and sends the data to Google Analytics.\r\n */\r\nfunction googleAnalyticsEventsForPills() {\r\n const activatedPillsText = pillsSection.getActivatedPillsText();\r\n\r\n if (activatedPillsText) {\r\n const state = store.getState();\r\n const resultType = selectResultType(state);\r\n const eventCategoty = 'Search Events';\r\n const eventAction = 'Popular Refinement';\r\n const resultTypeName = resultType === ResultType.Communities.toString() ? 'Community' : 'Homes';\r\n const eventLabel = `${resultTypeName} SRP - ${activatedPillsText.join(', ')}`;\r\n\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent(eventCategoty, eventAction, eventLabel);\r\n\r\n if (googleAnalyticsDTO) {\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create an observable pipeline to subscribe the `click$`. When a click\r\n * event occurs, the function is executed to log the GA Event for the Popular Searches Pills.\r\n */\r\nclick$.subscribe(googleAnalyticsEventsForPills);\r\n\r\n/**\r\n * The code snippet is creating an observable pipeline using RxJS operators to subscribe to changes in\r\n * the Redux store.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectPopularSearchesPills),\r\n distinctUntilChanged((previous, current) => JSON.stringify(previous) === JSON.stringify(current)),\r\n skip(1)\r\n )\r\n .subscribe(onPopularSearchPillsChange);\r\n","/**\r\n * This modules responsibility is to update the price high link in price high searches.\r\n * When the user interacts with filters in the page, this module will make sure to keep the\r\n * link up to date by contemplating the filters applied, so whenever clicked; the user gets\r\n * the same filters she/he is currently applying.\r\n */\r\nimport { map, distinctUntilChanged, filter, withLatestFrom } from 'rxjs/operators';\r\nimport { store$ } from \"@redux/store\";\r\nimport { selectFetchResultListingsStatus } from \"features/searchResultsFacets\";\r\nimport LoadingStatus from \"enums/loadingStatus\";\r\nimport { onQueryStringChanged$ } from '../redux/observables';\r\n\r\n/**\r\n * updatePriceHighLink: updates the href of the price high link in searches where price high is a filer.\r\n * @param {HTMLElement} priceHighLink is the anchor for price high searches in the HTML.\r\n * @param {HTMLElement} url to update the priceHighLink element.\r\n */\r\nconst updatePriceHighLink = ({priceHighLink, url}) => {\r\n priceHighLink.href = url;\r\n}\r\n\r\n/**\r\n * observable that emits a value every time results are loaded on screen.\r\n */\r\nconst onResultsLoaded$ = store$.pipe(\r\n map(selectFetchResultListingsStatus),\r\n distinctUntilChanged(),\r\n filter((status) => status === LoadingStatus.Succeeded)\r\n)\r\n\r\n/**\r\n * observable that takes the latest query string calculated value and emits it along the\r\n * price high link element for price high filters.\r\n */\r\nonResultsLoaded$.pipe(\r\n withLatestFrom(onQueryStringChanged$),\r\n map(([, queryString]) => {\r\n const priceHighLink = document.querySelector('[data-next-price-high-link]');\r\n\r\n const urlUpdateInformation = {\r\n priceHighLink,\r\n url: null,\r\n };\r\n\r\n if (!priceHighLink) {\r\n return urlUpdateInformation;\r\n }\r\n\r\n const url = new URL(priceHighLink.href);\r\n const parameters = new URLSearchParams(queryString);\r\n \r\n parameters.set('pricehigh', priceHighLink.getAttribute(\"data-price-high\"));\r\n url.search = parameters.toString();\r\n urlUpdateInformation.url = url.toString();\r\n\r\n return urlUpdateInformation;\r\n }),\r\n filter(({priceHighLink}) => priceHighLink),\r\n).subscribe(updatePriceHighLink);","/**\r\n * This class represents the very basic behavior that a Result Tab on the Search Results should follow.\r\n * For example, every tab should have an active state, an url to refer and its HTML constructor.\r\n * If it is require to update some of the logic to perform some of those actions, you can override the function.\r\n */\r\nexport default class ResultTab {\r\n setIsActive(isActive) {\r\n this.isActive = isActive;\r\n }\r\n \r\n updateUrl(newUrl) {\r\n this.url = newUrl;\r\n }\r\n\r\n getHTML() {\r\n const activeClass = this.isActive ? 'nhs-c-tab--active' : '';\r\n\r\n return `${this.content}`;\r\n }\r\n\r\n getNode() {\r\n return document.querySelector(`[data-result-type=\"${this.resultType}\"][data-product-type=\"${this.productType}\"]`);\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class CommunitiesTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'filters-result-type-communities';\r\n this.subdirectory = UrlSubdirectoryTypes.Communities.toString();\r\n this.content = 'Communities';\r\n this.resultType = ResultType.Communities.toString();\r\n this.productType = ProductType.Communities.toString();\r\n this.googleAnalyticTrackingClass = 'tagmanager_communitiestab';\r\n this.tabCLass = 'nhs-c-tab';\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged(),\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlSubdirectory, urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = componentsUrl;\r\n const newSubdirectory = this.updateSubdirectory(urlSubdirectory);\r\n const urlConfiguration = {\r\n urlSubdirectory: newSubdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n\r\n updateSubdirectory(urlSubdirectory) {\r\n switch (urlSubdirectory) {\r\n case UrlSubdirectoryTypes.Homes.toString():\r\n case UrlSubdirectoryTypes.Builders.toString():\r\n case UrlSubdirectoryTypes.FloorPlans.toString():\r\n case UrlSubdirectoryTypes.ModelHomes.toString():\r\n return this.subdirectory;\r\n\r\n case UrlSubdirectoryTypes.CondosAndTownHomes.toString():\r\n case UrlSubdirectoryTypes.CondoDevelopment.toString():\r\n return UrlSubdirectoryTypes.CondoDevelopment.toString();\r\n\r\n case UrlSubdirectoryTypes.SingleFamilyHomes.toString():\r\n case UrlSubdirectoryTypes.SingleFamilyCommunities.toString():\r\n return UrlSubdirectoryTypes.SingleFamilyCommunities.toString();\r\n\r\n default:\r\n return this.subdirectory;\r\n }\r\n }\r\n\r\n getHTML() {\r\n const classesList = [this.googleAnalyticsTrackingClass, this.tabCLass];\r\n if (this.isActive) {\r\n classesList.push('nhs-c-tab--active');\r\n }\r\n\r\n return `${this.content}`;\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class BuildersTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'filters-result-type-builders';\r\n this.subdirectory = UrlSubdirectoryTypes.Builders.toString();\r\n this.content = 'Builders';\r\n this.resultType = ResultType.Builders.toString();\r\n this.productType = ProductType.AllProducts.toString();\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged(),\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlCoordinatesQueryString, urlLocation } = componentsUrl;\r\n\r\n const urlConfiguration = {\r\n urlSubdirectory: this.subdirectory,\r\n urlLocation,\r\n urlQueryString: urlCoordinatesQueryString ?? '',\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class BuildOnYourLotTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'filters-result-type-locations';\r\n this.subdirectory = UrlSubdirectoryTypes.OnYourLot.toString();\r\n this.content = 'Build On Your Lot (BOYL)';\r\n this.resultType = ResultType.Locations.toString();\r\n this.productType = ProductType.BuildOnYourLot.toString();\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged()\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = componentsUrl;\r\n\r\n const urlConfiguration = {\r\n urlSubdirectory: this.subdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class CustomHomesTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'filters-result-type-homes';\r\n this.subdirectory = UrlSubdirectoryTypes.CustomHomes.toString();\r\n this.content = 'Custom Homes';\r\n this.resultType = ResultType.Homes.toString();\r\n this.productType = ProductType.Custom.toString();\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged()\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = componentsUrl;\r\n\r\n const urlConfiguration = {\r\n urlSubdirectory: this.subdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class ManufacturedHomesTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'manufactured-homes-tab';\r\n this.subdirectory = UrlSubdirectoryTypes.ManufacturedHomes.toString();\r\n this.content = 'Manufactured Homes';\r\n this.resultType = ResultType.Homes.toString();\r\n this.productType = ProductType.Manufactured.toString();\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged()\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = componentsUrl;\r\n\r\n const urlConfiguration = {\r\n urlSubdirectory: this.subdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n })\r\n }\r\n}\r\n","import { ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { routingSelectors, buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\n\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\nexport default class ManufacturedLocationsTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.qaAttribute = 'manufactured-tab';\r\n this.subdirectory = UrlSubdirectoryTypes.ManufacturedLocations.toString();\r\n this.content = 'Manufactured Builders';\r\n this.resultType = ResultType.Locations.toString();\r\n this.productType = ProductType.Manufactured.toString();\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsSelector),\r\n distinctUntilChanged()\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments(componentsUrl) {\r\n const { urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = componentsUrl;\r\n\r\n const urlConfiguration = {\r\n urlSubdirectory: this.subdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n}\r\n","import { ProductType } from 'features/searchResultsFacets';\r\nimport HomesTab from '../components/resultTabs/homesTab';\r\nimport CommunitiesTab from '../components/resultTabs/communitiesTab';\r\nimport BuildersTab from '../components/resultTabs/buildersTab';\r\nimport BuildOnYourLotLocationsTab from '../components/resultTabs/buildOnYourLotLocationsTab';\r\nimport CustomHomesTab from '../components/resultTabs/customHomesTab';\r\nimport ManufacturedHomesTab from '../components/resultTabs/manufacturedHomesTab';\r\nimport ManufacturedLocationsTab from '../components/resultTabs/manufacturedLocationsTab';\r\n\r\n// These lists are the tabs that will be shown in order.\r\nconst defaultTabs = [new HomesTab(), new CommunitiesTab(), new BuildersTab()];\r\nconst customAndBuildOnYourLotTabs = [new CustomHomesTab(), new BuildOnYourLotLocationsTab()];\r\nconst ManufacturedTabs = [new ManufacturedHomesTab(), new ManufacturedLocationsTab()];\r\n\r\nconst resultTabConfigurationMapper = new Map();\r\n\r\nresultTabConfigurationMapper.set(ProductType.AllProducts.toString(), defaultTabs);\r\nresultTabConfigurationMapper.set(ProductType.Communities.toString(), defaultTabs);\r\nresultTabConfigurationMapper.set(ProductType.Homes.toString(), defaultTabs);\r\nresultTabConfigurationMapper.set(ProductType.Custom.toString(), customAndBuildOnYourLotTabs);\r\nresultTabConfigurationMapper.set(ProductType.BuildOnYourLot.toString(), customAndBuildOnYourLotTabs);\r\nresultTabConfigurationMapper.set(ProductType.Manufactured.toString(), ManufacturedTabs);\r\n\r\n/**\r\n * getResultTabConfiguration: Gets configuration for the tabs to be used according to\r\n * the product type.\r\n * @param {string} productTypeName The name of the product type.\r\n * @returns The name of the result tab group according to the product type.\r\n */\r\nfunction getResultTabConfiguration(productTypeName) {\r\n const resultsTabConfiguration = resultTabConfigurationMapper.get(productTypeName);\r\n\r\n return resultsTabConfiguration ?? [];\r\n}\r\n\r\nexport default getResultTabConfiguration;","import { hasModelHome, hasReadyToBuild, ProductType, ResultType, selectResultType } from \"features/searchResultsFacets\";\r\nimport { store$ } from \"@redux/store\";\r\nimport { distinctUntilChanged, map } from \"rxjs\";\r\nimport { buildNewUrl } from \"features/routing\";\r\nimport fastdom from \"fastdom\";\r\nimport ResultTab from \"./resultTab\";\r\nimport UrlSubdirectoryTypes from \"../../enums/urlSubdirectoryTypes\";\r\nimport { urlComponentsWithHomeStatusSelector } from \"../../redux/selectors\";\r\n\r\nexport default class HomesTab extends ResultTab {\r\n constructor() {\r\n super();\r\n this.isActive = false;\r\n this.url = '';\r\n this.qaAttribute = 'filters-result-type-homes';\r\n this.subdirectory = UrlSubdirectoryTypes.Homes.toString();\r\n this.content = 'Homes';\r\n this.resultType = ResultType.Homes.toString();\r\n this.productType = ProductType.Homes.toString();\r\n this.googleAnalyticsTrackingClass = 'tagmanager_hometab';\r\n this.tabCLass = 'nhs-c-tab';\r\n\r\n const resultTypeChange$ = store$.pipe(\r\n map(selectResultType),\r\n map((resultType) => this.resultType === resultType),\r\n distinctUntilChanged(),\r\n );\r\n resultTypeChange$.subscribe(this.setIsActive.bind(this));\r\n\r\n const urlSegmentsChange$ = store$.pipe(\r\n map(urlComponentsWithHomeStatusSelector),\r\n distinctUntilChanged(),\r\n );\r\n\r\n urlSegmentsChange$.subscribe(this.updateUrlSegments.bind(this));\r\n }\r\n\r\n updateUrlSegments({ urlComponents, homeStatus }) {\r\n const { urlSubdirectory, urlCoordinatesQueryString, urlLocation, urlQueryString, urlBuilderName } = urlComponents;\r\n\r\n const newSubdirectory = this.updateSubdirectory(urlSubdirectory, homeStatus);\r\n const urlConfiguration = {\r\n urlSubdirectory: newSubdirectory,\r\n urlCoordinatesQueryString,\r\n urlLocation,\r\n urlQueryString,\r\n urlBuilderName,\r\n }\r\n\r\n this.url = buildNewUrl(urlConfiguration);\r\n this.updateUrl(this.url);\r\n fastdom.mutate(() => {\r\n const tabElement = this.getNode();\r\n if (tabElement) {\r\n tabElement.href = this.url;\r\n }\r\n });\r\n }\r\n\r\n updateSubdirectory(urlSubdirectory, homeStatus) {\r\n\r\n switch (true) {\r\n\r\n case urlSubdirectory === UrlSubdirectoryTypes.CondosAndTownHomes.toString():\r\n case urlSubdirectory === UrlSubdirectoryTypes.CondoDevelopment.toString():\r\n return UrlSubdirectoryTypes.CondosAndTownHomes.toString();\r\n\r\n case urlSubdirectory === UrlSubdirectoryTypes.SingleFamilyHomes.toString():\r\n case urlSubdirectory === UrlSubdirectoryTypes.SingleFamilyCommunities.toString():\r\n return UrlSubdirectoryTypes.SingleFamilyHomes.toString();\r\n\r\n case hasReadyToBuild(homeStatus):\r\n return UrlSubdirectoryTypes.FloorPlans.toString();\r\n\r\n case hasModelHome(homeStatus):\r\n return UrlSubdirectoryTypes.ModelHomes.toString();\r\n default:\r\n return this.subdirectory;\r\n }\r\n }\r\n\r\n getHTML() {\r\n const classesList = [this.googleAnalyticsTrackingClass, this.tabCLass];\r\n if (this.isActive) {\r\n classesList.push('nhs-c-tab--active');\r\n }\r\n\r\n return `${this.content}`;\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport { ProductType, ResultType } from 'features/searchResultsFacets';\r\n\r\nconst resultTabConfigurationMapper = new Map();\r\n/**\r\n * New const to handle the click on the tabs for Custom Build and Manufactured home results\r\n */\r\nconst searchEvents = 'Search Events';\r\nconst customboyltab = 'Custom & Build On Your Lot Tab';\r\nconst searchRefinement = 'Search Refinement';\r\n\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.Custom.toString()}-${ResultType.Homes.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, customboyltab, 'Custom Homes')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.BuildOnYourLot.toString()}-${ResultType.Locations.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, customboyltab, 'Build On Your Lot')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.Homes.toString()}-${ResultType.Homes.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, 'View Homes Tab Clicked')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.Communities.toString()}-${ResultType.Communities.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, 'View Communities Tab Clicked')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.AllProducts.toString()}-${ResultType.Builders.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, searchRefinement, 'View Builders Tab Clicked')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.Manufactured.toString()}-${ResultType.Homes.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, customboyltab, 'Manufactured Homes')\r\n);\r\nresultTabConfigurationMapper.set(\r\n `${ProductType.Manufactured.toString()}-${ResultType.Locations.toString()}`,\r\n new GoogleAnalyticsEvent(searchEvents, customboyltab, 'Manufactured Builders')\r\n);\r\n\r\n/**\r\n * getEventTabConfiguration: Gets event configuration for the tabs to be used according to\r\n * the product type and result type.\r\n * @param {string} productTypeName The name of the product type.\r\n * @returns The Google Analytics event.\r\n */\r\nfunction getEventTabConfiguration(productTypeName, resultTypeName) {\r\n const resultsTabConfiguration = resultTabConfigurationMapper.get(`${productTypeName}-${resultTypeName}`);\r\n\r\n return resultsTabConfiguration ?? null;\r\n}\r\n\r\nexport default getEventTabConfiguration;\r\n","import { fromEvent, map, filter, distinctUntilChanged, tap, skip } from 'rxjs';\r\nimport { store, store$ } from '@redux/store';\r\nimport {\r\n searchParametersActions,\r\n selectResultType,\r\n searchParametersSelectors,\r\n selectProductAndResultType,\r\n} from 'features/searchResultsFacets';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport fastdom from 'fastdom';\r\nimport PageLayout from '../../../layout/constants/pageLayoutNames';\r\nimport getResultTabConfiguration from '../services/resultTabConfiguration';\r\nimport getEventTabConfiguration from '../analytics/eventTabConfiguration';\r\n\r\nconst { selectProductType } = searchParametersSelectors;\r\nconst resultTabContainerElement = document.querySelector('[data-result-type-bar]');\r\n\r\n// need to listen to changes in the result type and change the currently active result type\r\nconst onResultsTypeChanged$ = store$.pipe(map(selectResultType), filter(Boolean), distinctUntilChanged());\r\n\r\nconst onTabChanged$ = store$.pipe(map(selectProductAndResultType), filter(Boolean), distinctUntilChanged());\r\n\r\nconst tabs = document.querySelectorAll('[data-result-type-bar]');\r\nconst tabsClicks$ = fromEvent(tabs, 'click');\r\n\r\n// observable created when there is a change in the tabs.\r\nconst resultType$ = tabsClicks$.pipe(\r\n filter((event) => event.target.hasAttribute('data-result-type')),\r\n tap((event) => event.preventDefault()),\r\n filter((event) => !event.target.dataset.active),\r\n map((event) => event.target.dataset),\r\n filter(Boolean)\r\n);\r\n\r\nconst uiStateActions = uiStateSlice.actions;\r\n\r\n// triggers the action to update the page layout.\r\nconst triggerUpdateLayout = (payload) => {\r\n const { productType, resultType } = payload;\r\n const key = `${productType}-${resultType}`;\r\n const pageLayoutName = PageLayout.fromKey(key).name;\r\n store.dispatch(uiStateActions.updatePageLayout(pageLayoutName));\r\n};\r\n\r\nonTabChanged$.subscribe(triggerUpdateLayout);\r\n\r\n// changes the tabs bar active element\r\nonResultsTypeChanged$.subscribe((value) => {\r\n const types = resultTabContainerElement.querySelectorAll('[data-result-type]');\r\n const element = resultTabContainerElement.querySelector(`[data-result-type=\"${value}\"]`);\r\n\r\n if (element) {\r\n types.forEach((sibling) => {\r\n sibling.classList.remove('nhs-c-tab--active');\r\n sibling.removeAttribute('data-active');\r\n });\r\n\r\n element.classList.add('nhs-c-tab--active');\r\n element.dataset.active = true;\r\n }\r\n});\r\n\r\n/**\r\n * updateResultType: Updates the Result type information on the store.\r\n * @param {Object} data Object with the information that relates to the selected result type.\r\n */\r\nfunction updateResultType(data) {\r\n const { resultType, productType } = data;\r\n store.dispatch(\r\n searchParametersActions.fetchResultsType({\r\n productType,\r\n resultType,\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * The function dispatches a user event by retrieving the event configuration based on the product type\r\n * and result type, and then dispatches the event to track the user event using Google Analytics.\r\n * @param data - The `data` parameter is an object that contains information about the user event. It\r\n * has two properties:\r\n */\r\nfunction dispatchUserEvent(data) {\r\n setTimeout(() => {\r\n const { productType, resultType } = data;\r\n const googleAnalyticsDTO = getEventTabConfiguration(productType, resultType);\r\n if (googleAnalyticsDTO) {\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n }\r\n });\r\n}\r\n\r\n// dispatch the action of the result type change\r\nresultType$.subscribe(dispatchUserEvent);\r\nresultType$.subscribe(updateResultType);\r\n\r\nconst resultTabsChanged$ = store$.pipe(\r\n map(selectProductType),\r\n distinctUntilChanged(),\r\n map((productType) => getResultTabConfiguration(productType)),\r\n distinctUntilChanged(),\r\n skip(1)\r\n);\r\n\r\n/**\r\n * Removes the current tabs from the DOM.\r\n */\r\nfunction removeAllTabs() {\r\n while (resultTabContainerElement.firstChild) {\r\n resultTabContainerElement.removeChild(resultTabContainerElement.firstChild);\r\n }\r\n}\r\n\r\n/**\r\n * Updates the list of tabs that will be shown on the DOM.\r\n * @param {Array} newTabs List of tab configurations to set.\r\n */\r\nfunction updateTabs(newTabs) {\r\n fastdom.mutate(() => {\r\n removeAllTabs();\r\n newTabs.forEach((tabConfiguration) => {\r\n const tab = document.createRange().createContextualFragment(tabConfiguration.getHTML());\r\n resultTabContainerElement.appendChild(tab);\r\n });\r\n })\r\n}\r\n\r\nresultTabsChanged$.subscribe(updateTabs);\r\n","/**\r\n * This component is the one in charge of observe a HTML node so when the user is close to it, dispatch an\r\n * event that will trigger the funnel that loads more results.\r\n */\r\nimport { Observable, distinctUntilChanged, distinctUntilKeyChanged, filter, map, takeWhile, zip } from 'rxjs';\r\nimport { store, store$ } from '@redux/store';\r\nimport { \r\n searchParametersActions,\r\n selectFetchResultListingsStatus } from 'features/searchResultsFacets';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport {\r\n resultStatusAndResultsPresentationType,\r\n selectPageInformationAndFetchResultsStatus } from 'pages/searchResults/redux/selectors';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport { selectResultsPresentationType } from 'layout/redux/selectors';\r\n\r\n/**\r\n * Basic configuration for the component. It has an intersection observer called \"intersectionObserver\" \r\n * to observe a given node and load results when the user is close to it.\r\n * It also has a RXJS observable called \"observableObserver\" that will emit a signal when the intersection\r\n * observer is intersecting with the observed node, this allow us to subscribe to that event\r\n * and run as many callbacks as we might need.\r\n * Finally, it has a reference to a HTML node called \"infiniteScrollTrigger\" which is the DOM element to\r\n * be observed in order to bring more results.\r\n */\r\nconst configuration = {\r\n intersectionObserver: null,\r\n observableObserver: null,\r\n infiniteScrollTrigger: document.querySelector('[data-more-results-check-point]'),\r\n}\r\n\r\n/**\r\n * fetchNextResults: dispatches an event so the funnel of bringing more results is triggered.\r\n */\r\nconst fetchNextResults = () => {\r\n store.dispatch(searchParametersActions.fetchPagingControlsNext());\r\n}\r\n\r\n/**\r\n * createObservable: this function will create the intersection observer and the observable to start\r\n * checking the infinite scroll trigger in order to load more results.\r\n */\r\nconst createObservable = () => {\r\n const observable$ = new Observable((observableObserver) => {\r\n const options = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0.5,\r\n };\r\n \r\n const onIntersection = (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting) {\r\n observableObserver.next(entry);\r\n }\r\n });\r\n };\r\n \r\n configuration.intersectionObserver = new IntersectionObserver(onIntersection, options);\r\n configuration.intersectionObserver.observe(configuration.infiniteScrollTrigger);\r\n configuration.observableObserver = observableObserver;\r\n });\r\n\r\n /**\r\n * This observable will emit values every time results are loaded,\r\n * including the initial load from the server side.\r\n */\r\n const onReadyToFetchNewResults$ = store$.pipe(\r\n map(selectPageInformationAndFetchResultsStatus),\r\n distinctUntilKeyChanged('fetchResultListingsStatus'),\r\n takeWhile(() => configuration.intersectionObserver),\r\n filter(({resultPresentationType}) =>\r\n resultPresentationType === ResultPresentationType.InfiniteScrolling.toString()),\r\n filter(({fetchResultListingsStatus}) =>\r\n fetchResultListingsStatus.name === LoadingStatus.Succeeded.toString() ||\r\n fetchResultListingsStatus.name === LoadingStatus.Idle.toString()),\r\n filter(({page, pageSize, listingCount}) => page * pageSize <= listingCount)\r\n );\r\n\r\n zip([observable$, onReadyToFetchNewResults$]).subscribe(fetchNextResults);\r\n}\r\n\r\n/**\r\n * destroyObservable: completes the RXJS observable and disconnects the intersection observable since\r\n * the Search Results Page shown is not of the type of infinite scrolling.\r\n * Sets these two values to null after disconnection and completeness.\r\n */\r\nconst destroyObservable = () => {\r\n configuration.intersectionObserver.disconnect();\r\n configuration.observableObserver.complete();\r\n configuration.intersectionObserver = null;\r\n configuration.observableObserver = null;\r\n}\r\n\r\n/**\r\n * manageObserver: this function pauses and resumes the intersection observer based on the\r\n * results listing status of the fetch operation. We disconnect the observer when results\r\n * are being loaded and connect it again when loading operation was succeeded.\r\n * This is particulary usefull to avoid intersecting several times in a row without waiting\r\n * for results to render, this could provoke to fetch page n and suddenly cancel it to fetch\r\n * page n+1, which is an issue since the user won't get to see all available results.\r\n * @param {LoadingStatus} loadingStatus of the current fetch results operation.\r\n * @returns \r\n */\r\nconst manageObserver = (loadingStatus) => {\r\n if (loadingStatus.name === LoadingStatus.Loading.toString()) {\r\n configuration.intersectionObserver.disconnect();\r\n return;\r\n }\r\n\r\n configuration.intersectionObserver.observe(configuration.infiniteScrollTrigger);\r\n}\r\n\r\n/**\r\n * Subscribing to the store, if loading status is idle (initial load rendered results) or\r\n * succeeded (ajax rendered results), and also the current Search Results Page is showing results\r\n * in an infinite scroll way, then we start the observables to be ready to load more results.\r\n */\r\nstore$.pipe(\r\n map(resultStatusAndResultsPresentationType),\r\n distinctUntilKeyChanged('fetchResultListingStatus'),\r\n filter(({fetchResultListingStatus}) =>\r\n fetchResultListingStatus.name === LoadingStatus.Succeeded.toString() ||\r\n fetchResultListingStatus.name === LoadingStatus.Idle.toString()),\r\n filter(({presentationType}) => presentationType === ResultPresentationType.InfiniteScrolling.toString()),\r\n filter(() => !configuration.intersectionObserver),\r\n ).subscribe(createObservable);\r\n\r\n/**\r\n * Subscribing to the store, if the current Search Results Page is showing results in a way \r\n * distinct than infinite scroll, then we stop the observables since they don't need to be in\r\n * charge of load results anymore.\r\n */\r\nstore$.pipe(\r\n map(selectResultsPresentationType),\r\n distinctUntilChanged(),\r\n filter((resultPresentationType) => resultPresentationType !== ResultPresentationType.InfiniteScrolling.toString()),\r\n filter(() => configuration.observableObserver),\r\n filter(() => configuration.intersectionObserver),\r\n ).subscribe(destroyObservable);\r\n\r\n /**\r\n * Subscribing to the store to detect changes in the result listing status\r\n */\r\nstore$.pipe(\r\n map(selectFetchResultListingsStatus),\r\n distinctUntilChanged(),\r\n filter(() => configuration.intersectionObserver)\r\n).subscribe(manageObserver)","import { store, store$ } from '@redux/store';\r\nimport { map, distinctUntilChanged, pairwise, distinctUntilKeyChanged } from 'rxjs';\r\nimport CardGridSkeleton from '@components/skeletons/cardSkeleton';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport { selectFetchResultListingsStatus } from '../../../features/searchResultsFacets/redux/selectors';\r\nimport { selectDisplaySkeletonAndResultsPresentationType } from '../redux/selectors';\r\n\r\nconst listViewContainerSelector = '[data-list-view-element]';\r\nconst skeleton = new CardGridSkeleton();\r\nconst uiStateActions = uiStateSlice.actions;\r\n\r\n// will look for changes in the fetching result state, which determines that results are buein requested.\r\nconst onFetchingResultsChanged$ = store$.pipe(map(selectFetchResultListingsStatus), distinctUntilChanged());\r\n\r\n// triggers a change in the ui state to flag is skeleton should be displayed\r\nconst triggerUpdateSkeleton = (fetchResultListingsStatus) => {\r\n store.dispatch(uiStateActions.updateCardGridSkeleton(fetchResultListingsStatus));\r\n};\r\n\r\nonFetchingResultsChanged$.subscribe(triggerUpdateSkeleton);\r\n\r\n// method to toggle the behavior of the skeleton component\r\nconst displayCardGridSkeleton = (displaySkeletonInformation) => {\r\n setTimeout(() => {\r\n skeleton.containerSelector = listViewContainerSelector;\r\n skeleton.cardCount = document.querySelectorAll(\r\n `${listViewContainerSelector} div[data-native], [data-card], [data-builder-brand-card]`\r\n ).length;\r\n skeleton.destroy();\r\n\r\n if (!displaySkeletonInformation.shouldDisplaySkeleton) {\r\n return;\r\n }\r\n\r\n if (displaySkeletonInformation.shouldCleanUpContainer) {\r\n document.querySelector(listViewContainerSelector).innerHTML = '';\r\n }\r\n\r\n if (displaySkeletonInformation.resultsPresentationType === ResultPresentationType.InfiniteScrolling.toString()) {\r\n skeleton.concat();\r\n } else {\r\n skeleton.create();\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * This observable subscribes to the store and observe changes in the display skeleton property and the\r\n * page layout property.\r\n * The observable maps information so their subscribers can determine if they should show the skeleton and\r\n * the way of showing it depending on the way we are presenting results to the user, ie: pagination, infinite scroll...\r\n * By the pairwise operator, we know if we should clean up the container before rendering the skeleton or not. If\r\n * we come from a change in the page layout, we will always clean up the container where the skeleton is going\r\n * to be rendered. For example: moving from Home results to Community Results. On the other hand, if we come from\r\n * an identical page layout, we are not going to clean the container first, since we could be presenting results\r\n * in an infinite scrolling way, so we need to preserve previous results and concat the skeleton after them.\r\n */\r\nconst onDisplaySkeletonChange$ = store$.pipe(\r\n map(selectDisplaySkeletonAndResultsPresentationType),\r\n distinctUntilKeyChanged('shouldDisplaySkeleton'),\r\n pairwise(),\r\n map((stateTransition) => ({\r\n shouldDisplaySkeleton: stateTransition[1].shouldDisplaySkeleton,\r\n resultsPresentationType: stateTransition[1].resultsPresentationType,\r\n shouldCleanUpContainer: stateTransition[0].resultsPresentationType !== stateTransition[1].resultsPresentationType,\r\n }))\r\n);\r\n\r\n// subscribe to the observable and call the toggleClearAllButton function\r\nonDisplaySkeletonChange$.subscribe(displayCardGridSkeleton);\r\n","import fastdom from 'fastdom';\r\n\r\n/**\r\n * This component is intended to build a skeleton card or a set of skeleton cards and place it in a given container.\r\n */\r\nexport default class CardGridSkeleton {\r\n constructor() {\r\n this.skeletonCustomDataValue = 'data-skeleton-card';\r\n this.containerSelector = null;\r\n this.cardCount = 8;\r\n }\r\n\r\n /**\r\n * create: creates a set of card skeletons and places them in a given container.\r\n */\r\n create() {\r\n fastdom.mutate(() => {\r\n const container = document.querySelector(this.containerSelector);\r\n\r\n if (container) {\r\n container.innerHTML = this.getCardSkeleton();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * concat: creates a set of card skeletons and appends them in a given container.\r\n */\r\n concat() {\r\n const container = document.querySelector(this.containerSelector);\r\n\r\n if (container) {\r\n const skeletonElements = document.createRange().createContextualFragment(this.getCardSkeleton());\r\n container.appendChild(skeletonElements);\r\n }\r\n }\r\n\r\n /**\r\n * getSkeletonCardNodes: retrieves the skeleton cards from a given container.\r\n * @returns a node list filled with skeleton card nodes.\r\n */\r\n getSkeletonCardNodes() {\r\n const container = document.querySelector(this.containerSelector);\r\n return container?.querySelectorAll(`[${this.skeletonCustomDataValue}]`);\r\n }\r\n\r\n /**\r\n * destroy: destroys the skeleton set from a given container.\r\n */\r\n destroy() {\r\n fastdom.mutate(() => {\r\n const skeletonElements = this.getSkeletonCardNodes();\r\n\r\n skeletonElements?.forEach((card) => {\r\n card.parentElement.removeChild(card);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * getCardSkeleton: builds and returns a string representing the skeleton cards to show.\r\n * @returns an string ready to create HTML nodes representing card grid skeletons.\r\n */\r\n getCardSkeleton() {\r\n const cardList = Array.from({ length: this.cardCount }, () => this.getCardHtml()).join('');\r\n return cardList;\r\n }\r\n\r\n /**\r\n * getCardHtml: builds and returns a string representing the template of a card skeleton.\r\n * @returns a card skeleton string ready to be used to create a HTML node.\r\n */\r\n getCardHtml() {\r\n return `
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
`;\r\n }\r\n}\r\n","import HousingProductType from \"constants/housingProductType\";\r\nimport SpecCard from \"../models/specCard\";\r\nimport PlanCard from \"../models/planCard\";\r\nimport CommunityCard from \"../models/communityCard\";\r\nimport BasicListingCard from \"../models/basicListing\";\r\n\r\nconst housingCardConstructor = new Map();\r\n\r\nhousingCardConstructor.set(HousingProductType.Spec().getName(), SpecCard);\r\nhousingCardConstructor.set(HousingProductType.Plan().getName(), PlanCard);\r\nhousingCardConstructor.set(HousingProductType.Community().getName(), CommunityCard);\r\nhousingCardConstructor.set(HousingProductType.BasicListing().getName(), BasicListingCard);\r\n\r\n/**\r\n * Returns the class constructor with the listing information according to the type.\r\n *\r\n * @param type - The type of listing (Spec, plan, community).\r\n * @param url - The listing URL.\r\n * @param listingInformation - The listing (Spec, plan, community) information.\r\n */\r\nexport default (type, url, listingInformation) => {\r\n const generator = housingCardConstructor.get(type);\r\n \r\n if (!generator) {\r\n return null;\r\n }\r\n \r\n return new generator.prototype.constructor(url, listingInformation);\r\n };\r\n ","import GoogleAnalyticsCustomDimensions from \"constants/googleAnalyticsCustomDimension\";\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class SpecCard {\r\n constructor(url, listing) {\r\n this.url = url;\r\n this.priceReductionLabel = listing.priceReductionLabel;\r\n this.communityName = listing.communityName;\r\n this.brandName = listing.brandName;\r\n this.marketId = listing.marketId;\r\n this.city = listing.city;\r\n this.marketName = listing.marketName;\r\n this.stateAbbreviation = listing.stateAbbreviation;\r\n this.id = listing.id;\r\n this.communityId = listing.communityId;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n \r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for card click.\r\n */\r\n getCardGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()] :\r\n this.priceReductionLabel,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.communityName,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.MarketId().getName()] : \r\n this.marketId,\r\n [GoogleAnalyticsCustomDimensions.City().getName()] : \r\n this.city,\r\n [GoogleAnalyticsCustomDimensions.MarketName().getName()] : \r\n `${this.marketName}, ${this.stateAbbreviation}`,\r\n [GoogleAnalyticsCustomDimensions.SpecId().getName()] :\r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] : \r\n this.communityId,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url, customDimensions);\r\n \r\n return googleAnalyticsDTO;\r\n }\r\n }\r\n ","import GoogleAnalyticsCustomDimensions from \"constants/googleAnalyticsCustomDimension\";\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class PlanCard {\r\n constructor(url, listing) {\r\n this.url = url;\r\n this.priceReductionLabel = listing.priceReductionLabel;\r\n this.communityName = listing.communityName;\r\n this.brandName = listing.brandName;\r\n this.marketId = listing.marketId;\r\n this.city = listing.city;\r\n this.marketName = listing.marketName;\r\n this.stateAbbreviation = listing.stateAbbreviation;\r\n this.id = listing.id;\r\n this.communityId = listing.communityId;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n \r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for card click.\r\n */\r\n getCardGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()] :\r\n this.priceReductionLabel,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.communityName,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.MarketId().getName()] : \r\n this.marketId,\r\n [GoogleAnalyticsCustomDimensions.City().getName()] : \r\n this.city,\r\n [GoogleAnalyticsCustomDimensions.MarketName().getName()] : \r\n `${this.marketName}, ${this.stateAbbreviation}`,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()] : \r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] : \r\n this.communityId,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url, customDimensions);\r\n \r\n return googleAnalyticsDTO;\r\n }\r\n }\r\n ","import GoogleAnalyticsCustomDimensions from \"constants/googleAnalyticsCustomDimension\";\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class CommunityCard {\r\n constructor(url, listing) {\r\n this.url = url;\r\n this.priceReductionLabel = listing.priceReductionLabel;\r\n this.communityName = listing.communityName;\r\n this.brandName = listing.brandName;\r\n this.marketId = listing.marketId;\r\n this.city = listing.city;\r\n this.marketName = listing.marketName;\r\n this.stateAbbreviation = listing.stateAbbreviation;\r\n this.id = listing.id;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n \r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for card click.\r\n */\r\n getCardGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.PriceReduction().getName()] :\r\n this.priceReductionLabel,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.communityName,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.MarketId().getName()] : \r\n this.marketId,\r\n [GoogleAnalyticsCustomDimensions.City().getName()] : \r\n this.city,\r\n [GoogleAnalyticsCustomDimensions.MarketName().getName()] : \r\n `${this.marketName}, ${this.stateAbbreviation}`,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] :\r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url, customDimensions);\r\n\r\n return googleAnalyticsDTO;\r\n }\r\n }\r\n ","import GoogleAnalyticsCustomDimensions from \"constants/googleAnalyticsCustomDimension\";\r\nimport GoogleAnalyticsEvent from \"dataTransferObjects/googleAnalyticsEvent\";\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class BasicListingCard {\r\n constructor(url, listing) {\r\n this.url = url; \r\n this.marketId = listing.marketId; \r\n this.marketName = listing.marketName;\r\n this.id = listing.id;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n \r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for card click.\r\n */\r\n getCardGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.MarketId().getName()] : \r\n this.marketId,\r\n [GoogleAnalyticsCustomDimensions.MarketName().getName()] : \r\n this.marketName,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()] : \r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n\r\n const googleAnalyticsDTO = new GoogleAnalyticsEvent('Card-Clicks', 'SRP-Card-Clicks', this.url, customDimensions);\r\n \r\n return googleAnalyticsDTO;\r\n }\r\n }\r\n ","import { store, store$ } from '@redux/store';\r\nimport uiStateSlice from 'layout/redux/uiStateSlice';\r\nimport { fromEvent, filter, map, distinctUntilChanged, distinctUntilKeyChanged } from 'rxjs';\r\nimport openLeadModal from 'features/searchResultsExtendedCard';\r\nimport { createMarkerHashedKey } from 'libraries/mapLibrary';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport fastdom from 'fastdom';\r\nimport housingCardConstructor from '../services/getHousingCard';\r\nimport { selectSelectedMarker } from '../redux/selectors';\r\n\r\nrequire('features/leadGenerators');\r\nrequire('../analytics/leads');\r\n\r\nconst listViewContainer = document.querySelector('[data-list-view-element]');\r\nconst searchResultsContainer = document.querySelector('[data-search-results-content]');\r\nconst containerClick$ = fromEvent(listViewContainer, 'click');\r\n\r\nconst isStandardCard = (event) => !!event.target.closest('[data-standard-card]');\r\nconst isAnchorElement = (event) => event.target instanceof HTMLAnchorElement;\r\nconst isFavoriteIcon = (event) => !!event.target.closest('.nhs-c-card__favorite-button');\r\nconst isLeadOpener = (event) => !!event.target.closest('[data-lead-generator-opener]');\r\n\r\nconst cardClick$ = containerClick$.pipe(\r\n filter(isStandardCard),\r\n filter((event) => !isFavoriteIcon(event)),\r\n filter((event) => !isAnchorElement(event)),\r\n filter((event) => !isLeadOpener(event))\r\n);\r\n\r\nconst leadOpenerClick$ = containerClick$.pipe(\r\n filter((event) => isLeadOpener(event)),\r\n map((event) => event.target.closest('[data-card]'))\r\n);\r\n\r\n/**\r\n * By using event delegation, a listener monitors mouseover events on the standard cards.\r\n * When a standard card receives the mouseover event, it will store information like\r\n * the listing id and type od the point of interest that card hovered represents.\r\n * When mouseover event is not happening on a standard card, then we remove any previous point of\r\n * interest values from the store.\r\n */\r\nfunction onStandardCardHovered(card) {\r\n if (card) {\r\n const cardLatitude = card.getAttribute('data-latitude');\r\n const cardLongitude = card.getAttribute('data-longitude');\r\n const geographicKey = createMarkerHashedKey(cardLatitude, cardLongitude);\r\n\r\n store.dispatch(\r\n uiStateSlice.actions.focusedListingInformation({\r\n id: card.getAttribute('data-id'),\r\n communityId: card.getAttribute('data-community-id'),\r\n geographicKey,\r\n })\r\n );\r\n\r\n return;\r\n }\r\n\r\n store.dispatch(\r\n uiStateSlice.actions.focusedListingInformation({\r\n id: null,\r\n communityId: null,\r\n geographicKey: null,\r\n })\r\n );\r\n}\r\n\r\nfunction onSelectedMarkerChange(id) {\r\n const cardPreviousSelected = listViewContainer.querySelector(`[data-standard-card][data-card-selected]`);\r\n delete cardPreviousSelected?.dataset?.cardSelected;\r\n cardPreviousSelected?.classList?.remove(\r\n 'nhs-mq-scroll--margin-top-medium',\r\n 'nhs-mq-scroll--margin-top-large',\r\n 'nhs-c-card--selected'\r\n );\r\n\r\n const card = listViewContainer.querySelector(`[data-standard-card][data-id='${id}']`);\r\n\r\n fastdom.mutate(() => {\r\n card?.setAttribute('data-card-selected', '');\r\n card?.classList?.add('nhs-mq-scroll--margin-top-medium', 'nhs-mq-scroll--margin-top-large', 'nhs-c-card--selected');\r\n card?.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n });\r\n}\r\n\r\n/**\r\n * Redirects the click on the SRP card to the detial page,\r\n * and removes the tooltip on the map once the URL is opened.\r\n */\r\nconst redirectClickEventToUrl = (url) => {\r\n if (!url) {\r\n return;\r\n }\r\n\r\n window.open(url, '_blank');\r\n onStandardCardHovered(null);\r\n};\r\n\r\ncardClick$.subscribe((event) => {\r\n const standardCardElement = event.target.closest('.nhs-c-card--housing');\r\n const url = event.target?.dataset?.url ?? standardCardElement?.querySelector('a')?.href;\r\n const cardInformation = standardCardElement.dataset;\r\n const googleAnalyticsDTO = housingCardConstructor(\r\n cardInformation.type,\r\n url,\r\n cardInformation\r\n ).getCardGoogleAnalyticsEvent();\r\n\r\n store.dispatch(uiStateSlice.actions.trackUserEvent({ googleAnalyticsDTO }));\r\n redirectClickEventToUrl(url);\r\n});\r\n\r\nleadOpenerClick$.subscribe((leadOpener) => openLeadModal(leadOpener.dataset.id, leadOpener.dataset.type));\r\n\r\n/**\r\n * The fromEvent observable detects mouseover events on the parent container of the standard cards.\r\n * By using the distinctUntilChanged pipe operator, we prevent an overflow of signals to the subscriber,\r\n * ensuring that only a single signal is emitted when a card is hovered or when it stops being hovered.\r\n */\r\nfromEvent(searchResultsContainer, 'mouseover')\r\n .pipe(\r\n map((event) => event.target?.closest('[data-standard-card]')),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(onStandardCardHovered);\r\n\r\n/*\r\n * Observable to listen when the selectedMarker,\r\n * to raise the SelectedMarkedChanged\r\n * Conditions\r\n * 1. When fetchResultListingsStatus change\r\n * 2. When selected marker change\r\n * 3. When fetchStatus is Succeeded or Idle\r\n * 4. The Page is the same of the last selected marker\r\n */\r\nstore$\r\n .pipe(\r\n map(selectSelectedMarker),\r\n filter(Boolean),\r\n distinctUntilKeyChanged('marker'),\r\n filter(\r\n ({ fetchResultListingsStatus }) =>\r\n fetchResultListingsStatus?.name === LoadingStatus.Succeeded.toString() ||\r\n fetchResultListingsStatus?.name === LoadingStatus.Idle.toString()\r\n ),\r\n filter(({ page, marker }) => page === marker?.pageNumber),\r\n map(({ marker }) => marker.id),\r\n filter(Boolean)\r\n )\r\n .subscribe(onSelectedMarkerChange);\r\n\r\n/*\r\n * Observable to listen when the selectedMarker,\r\n * to raise the SelectedMarkedChanged\r\n * Conditions\r\n * 1. When fetchResultListingsStatus change\r\n * 2. When selected marker change\r\n * 3. When fetchStatus is Succeeded or Idle\r\n * 4. When the page is diferent of the last selected marker\r\n */\r\nstore$\r\n .pipe(\r\n map(selectSelectedMarker),\r\n filter(Boolean),\r\n distinctUntilKeyChanged('fetchResultListingsStatus'),\r\n filter(\r\n ({ fetchResultListingsStatus }) =>\r\n fetchResultListingsStatus?.name === LoadingStatus.Succeeded.toString() ||\r\n fetchResultListingsStatus?.name === LoadingStatus.Idle.toString()\r\n ),\r\n map(({ marker }) => marker?.id),\r\n filter(Boolean),\r\n distinctUntilChanged()\r\n )\r\n .subscribe(onSelectedMarkerChange);\r\n","import { switchMap, of, catchError } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { getTypeaheadOptions } from 'constants/routes'\r\n\r\nfunction getTypeaheadSuggestions(searchTerm) {\r\n const url = `${getTypeaheadOptions}?searchTerm=${encodeURIComponent(searchTerm)}`;\r\n\r\n return fromFetch(url, {\r\n headers: {\r\n 'Accept': 'application/json',\r\n }\r\n }).pipe(\r\n switchMap((response) => response.json()),\r\n catchError(() => of([]))\r\n );\r\n}\r\n\r\nexport default getTypeaheadSuggestions;\r\n","/**\r\n * The idea behind this module is to separate the concerns of the typeahead\r\n * initially this was inside the typeahead.js file, but since it only handles what\r\n * we call keyboard accesibilty, we felt it was better that this code was separated from the\r\n * typeahead itself, and that modularize itself for easier reading of the typeahead code.\r\n */\r\n\r\nfunction typeaheadKeyboardHandler(config) {\r\n const suggestList = config.suggestList;\r\n const searchInput = config.searchInput;\r\n let selectedOptionIndex = config.selectedOptionIndex;\r\n const search$ = config.searchObserver;\r\n\r\n // reset index when a new search was performed\r\n search$.subscribe(() => {\r\n selectedOptionIndex = config.selectedOptionIndex;\r\n });\r\n\r\n /**\r\n * updateOptionsStatus: Adds the active class to options if they're being actively focused via keyboard.\r\n * remove the active class from previously selected options to avoid displaying multiple selected options.\r\n * @param {Number} activeOptionIndex the currently active option's index.\r\n */\r\n function updateOptionsStatus(activeOptionIndex) {\r\n const options = suggestList.children;\r\n for (let index = 0; index < options.length; index += 1) {\r\n if (activeOptionIndex === index) {\r\n options[index].classList.add('nhs-c-suggestion--hover');\r\n options[index].ariaSelected = true;\r\n } else {\r\n options[index].classList.remove('nhs-c-suggestion--hover');\r\n options[index].ariaSelected = false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * setSelectedOptionInTypeahead: Update the search input with the selected option.\r\n * @param {Number} optionIndex Option index that is active.\r\n */\r\n function setSelectedOptionInTypeahead(optionIndex) {\r\n const optionSelected = suggestList.children[optionIndex];\r\n searchInput.value = optionSelected.getAttribute('value');\r\n const end = searchInput.value.length;\r\n\r\n // move the cursor to the end of the input.\r\n searchInput.setSelectionRange(end, end);\r\n }\r\n\r\n /**\r\n * scrollToOption: Scrolls to the option to make it visible on screen.\r\n * @param {Number} optionIndex Option index that will be shown.\r\n */\r\n function scrollToOption(optionIndex) {\r\n const optionToShow = suggestList.children[optionIndex];\r\n optionToShow.scrollIntoViewIfNeeded();\r\n }\r\n\r\n /**\r\n * upArrowHandler: Handles the up arrow key when it is pressed.\r\n */\r\n function upArrowHandler() {\r\n if (selectedOptionIndex < 1) {\r\n return;\r\n }\r\n\r\n selectedOptionIndex -= 1;\r\n setSelectedOptionInTypeahead(selectedOptionIndex);\r\n updateOptionsStatus(selectedOptionIndex);\r\n scrollToOption(selectedOptionIndex);\r\n }\r\n\r\n /**\r\n * downArrowHandler: Handles the down arrow key when it is pressed.\r\n */\r\n function downArrowHandler() {\r\n const optionSize = suggestList.childElementCount;\r\n if (optionSize < 1 || selectedOptionIndex === optionSize - 1) {\r\n return;\r\n }\r\n\r\n selectedOptionIndex += 1;\r\n setSelectedOptionInTypeahead(selectedOptionIndex);\r\n updateOptionsStatus(selectedOptionIndex);\r\n scrollToOption(selectedOptionIndex);\r\n }\r\n\r\n /**\r\n * closeOptions: Closes the suggestion list.\r\n */\r\n function closeOptions() {\r\n suggestList.innerHTML = '';\r\n suggestList.setAttribute('hidden', '');\r\n selectedOptionIndex = -1;\r\n }\r\n\r\n /**\r\n * enterHandler: Handles the enter key when it is pressed.\r\n */\r\n function enterHandler() {\r\n const currentSearch = searchInput.value;\r\n const suggestedOption = suggestList.querySelector(`[value=\"${currentSearch}\"]`);\r\n if (suggestedOption) {\r\n suggestedOption.classList.add('nhs-c-suggestion--selected');\r\n suggestedOption.click();\r\n closeOptions();\r\n }\r\n }\r\n\r\n const keyHandlers = {\r\n ArrowDown: downArrowHandler,\r\n ArrowUp: upArrowHandler,\r\n Enter: enterHandler,\r\n };\r\n\r\n /**\r\n * keyDownHandler: Handles the all the key down events on the search input.\r\n * @param {Event} event Any key down event.\r\n */\r\n function keyDownHandler(event) {\r\n const arrowHandler = keyHandlers[event.key];\r\n if (arrowHandler) {\r\n event.preventDefault();\r\n arrowHandler();\r\n }\r\n }\r\n\r\n return keyDownHandler;\r\n}\r\n\r\nexport default typeaheadKeyboardHandler;\r\n","/**\r\n * This typeahead is written using rxjs and reactive programming, it should not be mistaken with the older\r\n * typeahead*.js files that exist in other folders such as GlobalResourcesMobile, GlobalResourceSMvc and\r\n * GlobalResources14.\r\n *\r\n * Those older modules should only be used on pages that use vanillaJs and requireJs for module loading.\r\n *\r\n * Scripts using the import {*} from \"XXX\" syntax for module loading should use this script.\r\n *\r\n * If you're working on anything after december 2022, THIS is the script you're looking for unless you're working\r\n * on a legacy script (Legacy scripts are contained on the GlobalResourcesMobile, GlobalResourceSMvc and\r\n * GlobalResources14 folders).\r\n *\r\n * May the force be with you.\r\n *\r\n * ________\r\n _,.-Y | | Y-._\r\n .-~\" || | | | \"-.\r\n I\" \"\"==\"|\" !\"\"! \"|\"[]\"\"| _____\r\n L__ [] |..------|: _[----I\" .-{\"-.\r\n I___| ..| l______|l_ [__L]_[I_/r(=}=-P\r\n [L______L_[________]______j~ '-=c_]/=-^\r\n \\_I_j.--.\\==I|I==_/.--L_]\r\n [_((==)[`-----\"](==)j\r\n I--I\"~~\"\"\"~~\"I--I\r\n |[]| |[]|\r\n l__j l__j\r\n |!!| |!!|\r\n |..| |..|\r\n ([]) ([])\r\n ]--[ ]--[\r\n [_L] [_L]\r\n /|..|\\ /|..|\\\r\n `=}--{=' `=}--{='\r\n .-^--r-^-. .-^--r-^-.\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n */\r\n\r\nimport { fromEvent, merge, filter, switchMap, map, debounceTime } from 'rxjs';\r\nimport getTypeaheadSuggestions from 'api/getTypeaheadOptions';\r\nimport StringExtensions from 'utils/stringExtensions';\r\nimport TypeaheadLocationType from 'enums/typeaheadLocationType';\r\nimport fastdom from 'fastdom';\r\nimport typeaheadKeyboardHandler from './typeaheadKeyboardHandler';\r\n\r\n/**\r\n * toggleErrorMessage: Displays or hides the error message.\r\n * @param {HTMLElement} errorContainer HTML Container where the error is.\r\n * @param {Boolean} shouldDisplayError Value to determine if should display error message or not.\r\n */\r\nfunction toggleErrorMessage(errorContainer, shouldDisplayError) {\r\n const form = errorContainer.closest('form');\r\n const errorContainers = errorContainer.parentElement.querySelectorAll('[data-typeahead-error]');\r\n\r\n errorContainers.forEach((container) => {\r\n container.setAttribute('hidden', '');\r\n });\r\n\r\n if (shouldDisplayError) {\r\n form.classList.add('nhs-c-typeahead__form--error');\r\n errorContainer.removeAttribute('hidden');\r\n } else {\r\n form.classList.remove('nhs-c-typeahead__form--error');\r\n }\r\n}\r\n\r\n/**\r\n * SearchFormComponent: Creates and configures the search form component (called as typeahead).\r\n * Also, returns an observable about when the search input changes.\r\n * @param {Object} config Configuration object with the required components to make the search form work.\r\n * @returns The selected suggestion observable of the search input text state.\r\n */\r\nfunction Typeahead(config) {\r\n const searchInput = config.searchInput;\r\n const suggestList = config.suggestionsContainer;\r\n const errorContainer = config.errorContainer;\r\n const clearButton = config.clearButton;\r\n const currentLocationSearchText = config.currentLocation?.searchText;\r\n const allowCurrentLocation = config.currentLocation?.isEnabled;\r\n const searchForm = searchInput.closest('form');\r\n\r\n // setting the value on initial load if available\r\n // we need to set the value using javascript because if the value is set on the HTML\r\n // it will be set as the input's default value, preventing the user from clearing the input\r\n // since the X icon is a button[type='reset'] which will reset the input to its default value instead of cleaning it.\r\n // for more: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/reset\r\n if (searchInput?.dataset?.value) {\r\n searchInput.value = searchInput.dataset.value;\r\n }\r\n\r\n const searchInput$ = fromEvent(searchInput, 'input');\r\n const searchFocus$ = fromEvent(searchInput, 'focus');\r\n const clearClicked$ = fromEvent(clearButton, 'click');\r\n const searchEvent$ = merge(searchInput$, searchFocus$, clearClicked$);\r\n const selectedSuggestion$ = fromEvent(suggestList, 'click');\r\n\r\n const keyDownHandler = typeaheadKeyboardHandler({\r\n suggestList,\r\n searchInput,\r\n searchForm,\r\n selectedOptionIndex: -1,\r\n searchObserver: searchEvent$,\r\n });\r\n\r\n /**\r\n * closeOptions: Closes the suggestion list.\r\n */\r\n function closeOptions() {\r\n fastdom.mutate(() => {\r\n suggestList.innerHTML = '';\r\n suggestList.setAttribute('hidden', '');\r\n });\r\n }\r\n\r\n const formOutClick$ = fromEvent(document, 'click').pipe(\r\n filter(() => !suggestList.hidden),\r\n filter((event) => !searchForm.contains(event.target))\r\n );\r\n const searchInputKeyDown$ = fromEvent(searchInput, 'keydown');\r\n\r\n formOutClick$.subscribe(closeOptions);\r\n searchInputKeyDown$.subscribe({\r\n next: (event) => {\r\n const shouldDisplayError = event.key === 'Enter' && event.target.value === '';\r\n\r\n if (shouldDisplayError) {\r\n event.preventDefault();\r\n toggleErrorMessage(errorContainer, shouldDisplayError);\r\n return;\r\n }\r\n\r\n keyDownHandler(event);\r\n },\r\n });\r\n\r\n /**\r\n * insertCurrentLocationOption: Inserts current location option as the first option in the suggestions list.\r\n */\r\n const insertCurrentLocationOption = () => {\r\n suggestList.innerHTML = '';\r\n\r\n if (!allowCurrentLocation || sessionStorage.getItem('geolocationPermission') === 'false') {\r\n suggestList.setAttribute('hidden', '');\r\n return;\r\n }\r\n\r\n suggestList.innerHTML = `
  • \r\n ${config.currentLocation.icon}\r\n ${currentLocationSearchText}\r\n
  • `;\r\n };\r\n\r\n /**\r\n * getPrimaryCounty: For cities options returned in the typeahead, we create a data attribute for the\r\n * primary county where the city belongs.\r\n * @param {Object} suggestion Typeahead suggestion to work with.\r\n */\r\n const getPrimaryCounty = (suggestion) =>\r\n suggestion.Type.toLowerCase() === TypeaheadLocationType.City.toString().toLowerCase() && suggestion.County\r\n ? `data-county=\"${suggestion.County}\"`\r\n : '';\r\n\r\n /**\r\n * render: Updates the suggestion list with the new suggestions.\r\n * @param {Array} suggestArr Suggestion array with the options to display.\r\n */\r\n function displaySuggestions(suggestArr = []) {\r\n if (allowCurrentLocation) {\r\n insertCurrentLocationOption();\r\n }\r\n\r\n if (suggestArr.length > 0) {\r\n suggestList.innerHTML += suggestArr\r\n .map((item, index) => {\r\n const syntheticGeographicName = StringExtensions.removeWordFromString(item.Name, ` ${item.MarketStateAbbr}`);\r\n const optionAdditionalAttributes = {\r\n City: `data-city=\"${item.CityName}\"`,\r\n Zip: `data-city=\"${item.CityName}\" data-zip=\"${item.Name}\" data-county=\"${item.County}\"`,\r\n // Given that, in County searches, the \"item.name\" has the value \"Travis County, TX\",\r\n // we will need to set \"Travis\" value, so we remove the rest of the string starting from\r\n // \"County\" using the new StringExtensions method.\r\n County: `data-county=\"${StringExtensions.removeWordFromString(item.Name, 'County')}\"`,\r\n SyntheticGeo: `data-synthetic-geographic-name=\"${syntheticGeographicName}\"`,\r\n Community: `data-community-id=\"${item.Id}\"`,\r\n MasterPlannedCommunity: `data-community-id=\"${item.Id}\"`,\r\n };\r\n\r\n if (item.Type === 'Developer') {\r\n item.Type = 'MasterPlannedCommunity';\r\n }\r\n\r\n return `
  • \r\n ${item.Name}\r\n
  • `;\r\n })\r\n .join('');\r\n\r\n if (!allowCurrentLocation || sessionStorage.getItem('geolocationPermission') === 'false') {\r\n suggestList.removeAttribute('hidden');\r\n }\r\n }\r\n }\r\n\r\n if (allowCurrentLocation) {\r\n merge(searchInput$, searchFocus$).subscribe(() => {\r\n suggestList.removeAttribute('hidden');\r\n insertCurrentLocationOption();\r\n });\r\n }\r\n\r\n searchEvent$\r\n .pipe(\r\n debounceTime(100),\r\n switchMap((event) => {\r\n const userInput = event.target.value;\r\n if (!userInput) {\r\n toggleErrorMessage(errorContainer, false);\r\n\r\n return [];\r\n }\r\n\r\n if (!userInput.trimStart()) {\r\n toggleErrorMessage(errorContainer, true);\r\n\r\n return [];\r\n }\r\n\r\n return getTypeaheadSuggestions(event.target.value);\r\n })\r\n )\r\n .subscribe({\r\n next: (list) => {\r\n if (allowCurrentLocation && sessionStorage.getItem('geolocationPermission') !== 'false') {\r\n const isCurrentLocationSelected = currentLocationSearchText\r\n .toLowerCase()\r\n .startsWith(searchInput.value.toLowerCase());\r\n\r\n const shouldDisplayError = list.length <= 0 && !isCurrentLocationSelected;\r\n toggleErrorMessage(errorContainer, shouldDisplayError);\r\n } else {\r\n const shouldDisplayError = list.length <= 0;\r\n toggleErrorMessage(errorContainer, shouldDisplayError);\r\n }\r\n\r\n displaySuggestions(list);\r\n },\r\n });\r\n\r\n const pipedObservable$ = selectedSuggestion$.pipe(\r\n filter((event) => event.target.closest('li')),\r\n map((event) => event.target.closest('li'))\r\n );\r\n\r\n pipedObservable$.subscribe((option) => {\r\n searchInput.value = option.innerText.trimStart();\r\n closeOptions();\r\n });\r\n\r\n // return the selected suggestion observable\r\n return pipedObservable$;\r\n}\r\n\r\nexport default Typeahead;\r\n","import { store } from '@redux/store';\r\nimport Typeahead from '@components/typeahead/geoLocationtypeahead';\r\nimport { locationIconSvg } from 'constants/svg-assets';\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\n\r\nconst parser = new DOMParser();\r\nexport const locationIconSvgElement = parser.parseFromString(locationIconSvg, 'image/svg+xml').documentElement;\r\n\r\nconst config = {\r\n searchInput: document.getElementById('srp_typeahead_input'),\r\n suggestionsContainer: document.getElementById('srp_typeahead_suggestions'),\r\n errorContainer: document.getElementById('srp_typeahead_error'),\r\n clearButton: document.querySelector('[data-typeahead-clear]'),\r\n currentLocation: {\r\n searchText: 'Current location',\r\n isEnabled: true,\r\n icon: `
    ${locationIconSvgElement.cloneNode(true).outerHTML}
    `,\r\n },\r\n};\r\n\r\nconst typeahead$ = Typeahead(config);\r\n\r\ntypeahead$.subscribe((suggestion) => {\r\n const payload = suggestion.dataset;\r\n delete payload.qa;\r\n\r\n if (suggestion.matches('[data-current-location-search]')) {\r\n return;\r\n }\r\n\r\n store.dispatch(searchParametersActions.fetchLocations(payload));\r\n});\r\n\r\nexport default typeahead$;\r\n","import { fromEvent, map, merge, tap } from 'rxjs';\r\n\r\nconst searchResultContent = document.querySelector('[data-page-layout-container]');\r\nconst mapButtonToggle = document.querySelector('[data-map-button-toggle]');\r\nconst listButtonToggle = document.querySelector('[data-list-button-toggle]');\r\n/**\r\n * This function adds specific classes to the container element to set it to a map view\r\n * layout.\r\n */\r\nconst setMapView = () => {\r\n searchResultContent.classList.add('nhs-c-wrapper--map-view', 'nhs-mq-wrapper--map-view-medium');\r\n};\r\n\r\n/**\r\n * This function removes specific classes from a container element and dispatches a custom\r\n * event to toggle the list view.\r\n */\r\nconst setListView = () => {\r\n searchResultContent.classList.remove('nhs-c-wrapper--map-view', 'nhs-mq-wrapper--map-view-medium');\r\n\r\n const event = new CustomEvent('listViewToggled');\r\n document.body.dispatchEvent(event);\r\n};\r\n\r\nconst sortButton = document.querySelector('#sort-select');\r\nconst sortButtons = document.querySelectorAll('[data-sort-element]');\r\n\r\nconst toggleSortVisibility = (button) => {\r\n const hide = button.dataset.state === 'map';\r\n const displayValue = hide ? 'none' : 'block';\r\n\r\n sortButton.style.display = displayValue;\r\n sortButtons.forEach((btn) => {\r\n btn.style.display = displayValue;\r\n });\r\n};\r\n\r\n/**\r\n * Hides the map view toggle button.\r\n */\r\nconst hideMapButton = () => mapButtonToggle.setAttribute('hidden', '');\r\n\r\n/**\r\n * Hides the list view toggle button.\r\n */\r\nconst hideListButton = () => listButtonToggle.setAttribute('hidden', '');\r\n\r\n/**\r\n * Shows the map view toggle button.\r\n */\r\nconst showMapButton = () => mapButtonToggle.removeAttribute('hidden');\r\n\r\n/**\r\n * Shows the list view toggle button.\r\n */\r\nconst showListButton = () => listButtonToggle.removeAttribute('hidden');\r\n\r\n/**\r\n * An observable stream that listens for click events on the `listButtonToggle` element.\r\n * When a click event occurs, it maps the event to the current target\r\n * element, then sequentially performs the following actions using the `tap` operator:\r\n * 1. `hideListButton`: Hides the list view toggle button.\r\n * 2. `showMapButton`: Shows the map view toggle button.\r\n * 3. `setListView`: Removes specific classes from a container element and dispatches a custom event to\r\n * toggle the list view.\r\n * 4. `toggleSortVisibility`: Toggles the visibility of sort buttons based on the button's dataset\r\n * state.\r\n */\r\nconst onListButtonClick$ = fromEvent(listButtonToggle, 'click').pipe(\r\n map((event) => event.currentTarget),\r\n tap(hideListButton),\r\n tap(showMapButton),\r\n tap(setListView),\r\n tap(toggleSortVisibility)\r\n);\r\n\r\n/**\r\n * An observable stream that listens for click events on the `mapButtonToggle` element.\r\n * When a click event occurs, it maps the event to the current target\r\n * element, then sequentially performs the following actions using the `tap` operator:\r\n * 1. `hideMapButton`: Hides the map view toggle button.\r\n * 2. `showListButton`: Shows the list view toggle button.\r\n * 3. `setMapView`: Sets specific classes from a container element.\r\n * 4. `toggleSortVisibility`: Toggles the visibility of sort buttons based on the button's dataset\r\n * state.\r\n */\r\nconst onMapButtonClick$ = fromEvent(mapButtonToggle, 'click').pipe(\r\n map((event) => event.currentTarget),\r\n tap(hideMapButton),\r\n tap(showListButton),\r\n tap(setMapView),\r\n tap(toggleSortVisibility)\r\n);\r\n\r\nmerge(onListButtonClick$, onMapButtonClick$).subscribe();\r\n","export default class UrlSubdirectoryTypes {\r\n /**\r\n * The function return the Url Subdirectory name for Communities.\r\n * @returns The method `Communities` is returning an instance of the class\r\n * `communities`.\r\n */\r\n static get Communities() {\r\n const configuration = {\r\n name: 'communities',\r\n pageType: 'Community_Results',\r\n luxLabel: 'Community Results',\r\n };\r\n return this.getInstance('communities', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Homes.\r\n * @returns The method `Homes` is returning an instance of the class\r\n * `homes`.\r\n */\r\n static get Homes() {\r\n const configuration = {\r\n name: 'homes',\r\n pageType: 'Home_Results',\r\n luxLabel: 'Home Results',\r\n };\r\n return this.getInstance('homes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Builder Directory.\r\n * @returns The method `Builders` is returning an instance of the class\r\n * `builders`.\r\n */\r\n static get Builders() {\r\n const configuration = {\r\n name: 'builders',\r\n pageType: 'Builders',\r\n luxLabel: 'Builder Directory',\r\n };\r\n return this.getInstance('builders', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Condo Developments.\r\n * @returns The method `CondoDevelopment` is returning an instance of the class\r\n * `condo-developments`.\r\n */\r\n static get CondoDevelopment() {\r\n const configuration = {\r\n name: 'condo-developments',\r\n pageType: 'Condo_Developments',\r\n luxLabel: 'Community Results',\r\n };\r\n return this.getInstance('condo-developments', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Condo Townhomes.\r\n * @returns The method `CondosAndTownHomes` is returning an instance of the class\r\n * `condo-townhomes`.\r\n */\r\n static get CondosAndTownHomes() {\r\n const configuration = {\r\n name: 'condo-townhomes',\r\n pageType: 'Condo_Townhomes',\r\n luxLabel: 'Home Results',\r\n };\r\n return this.getInstance('condo-townhomes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Single Family Homes.\r\n * @returns The method `SingleFamilyHomes` is returning an instance of the class\r\n * `single-family-homes`.\r\n */\r\n static get SingleFamilyHomes() {\r\n const configuration = {\r\n name: 'single-family-homes',\r\n pageType: 'Single_Family_Homes',\r\n luxLabel: 'Home Results',\r\n };\r\n return this.getInstance('single-family-homes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Single Family Communities.\r\n * @returns The method `SingleFamilyCommunties` is returning an instance of the class\r\n * `single-family-communities`.\r\n */\r\n static get SingleFamilyCommunities() {\r\n const configuration = {\r\n name: 'single-family-communities',\r\n pageType: 'Single_Family_Communities',\r\n luxLabel: 'Community Results',\r\n };\r\n return this.getInstance('single-family-communities', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Custom Homes.\r\n * @returns The method `CustomHomes` is returning an instance of the class\r\n * `custom-homes`.\r\n */\r\n static get CustomHomes() {\r\n const configuration = {\r\n name: 'custom-homes',\r\n pageType: 'Custom_Homes',\r\n luxLabel: 'Custom Home Results',\r\n };\r\n return this.getInstance('custom-homes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Build On Your Lot.\r\n * @returns The method `OnYourLot` is returning an instance of the class\r\n * `on-your-lot`.\r\n */\r\n static get OnYourLot() {\r\n const configuration = {\r\n name: 'on-your-lot',\r\n pageType: 'BoylResults',\r\n luxLabel: 'Build On Your Lot Results',\r\n };\r\n return this.getInstance('on-your-lot', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Custom Builders.\r\n * @returns The method `CustomBuilders` is returning an instance of the class\r\n * `builders`.\r\n */\r\n static get CustomBuilders() {\r\n const configuration = {\r\n name: 'custom-builders',\r\n pageType: 'CustomBuilders',\r\n luxLabel: 'Custom Builder Results',\r\n };\r\n return this.getInstance('custom-builders', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Manufactured Homes.\r\n * @returns The method `ManufacturedHomes` is returning an instance of the class\r\n * `manufactured-homes`.\r\n */\r\n static get ManufacturedHomes() {\r\n const configuration = {\r\n name: 'manufactured-homes',\r\n pageType: 'Manufactured_Homes',\r\n luxLabel: 'Manufactured Home Results',\r\n };\r\n return this.getInstance('manufactured-homes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Manufactured Locations.\r\n * @returns The method `ManufacturedLocations` is returning an instance of the class\r\n * `manufactured`.\r\n */\r\n static get ManufacturedLocations() {\r\n const configuration = {\r\n name: 'manufactured',\r\n pageType: 'Manufactured_Results',\r\n luxLabel: 'Manufactured Results',\r\n };\r\n return this.getInstance('manufactured', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Floor Plans.\r\n * @returns The method `FloorPlans` is returning an instance of the class\r\n * `floor-plans`.\r\n */\r\n static get FloorPlans() {\r\n const configuration = {\r\n name: 'floor-plans',\r\n pageType: 'FloorPlans',\r\n luxLabel: 'Home Results',\r\n };\r\n return this.getInstance('floor-plans', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Model Homes.\r\n * @returns The method `ModelHomes` is returning an instance of the class\r\n * `model-homes`.\r\n */\r\n static get ModelHomes() {\r\n const configuration = {\r\n name: 'model-homes',\r\n pageType: 'ModelHomes',\r\n luxLabel: 'Home Results',\r\n };\r\n return this.getInstance('model-homes', configuration);\r\n }\r\n\r\n /**\r\n * The function return the Url Subdirectory name for Learning Center.\r\n * @returns The method `LearningCenter` is returning an instance of the class\r\n * `learn`.\r\n */\r\n static get LearningCenter() {\r\n const configuration = {\r\n pageType: 'Learning Center',\r\n luxLabel: 'Blog',\r\n };\r\n return this.getInstance('learn', configuration);\r\n }\r\n\r\n static fromKey(key) {\r\n const subDirectoryTypeMap = {\r\n communities: UrlSubdirectoryTypes.Communities,\r\n homes: UrlSubdirectoryTypes.Homes,\r\n builders: UrlSubdirectoryTypes.Builders,\r\n 'condo-developments': UrlSubdirectoryTypes.CondoDevelopment,\r\n 'condo-townhomes': UrlSubdirectoryTypes.CondosAndTownHomes,\r\n 'single-family-homes': UrlSubdirectoryTypes.SingleFamilyHomes,\r\n 'single-family-communities': UrlSubdirectoryTypes.SingleFamilyCommunities,\r\n 'custom-homes': UrlSubdirectoryTypes.CustomHomes,\r\n 'on-your-lot': UrlSubdirectoryTypes.OnYourLot,\r\n 'custom-builders': UrlSubdirectoryTypes.CustomBuilders,\r\n 'manufactured-homes': UrlSubdirectoryTypes.ManufacturedHomes,\r\n manufactured: UrlSubdirectoryTypes.ManufacturedLocations,\r\n 'floor-plans': UrlSubdirectoryTypes.FloorPlans,\r\n 'model-homes': UrlSubdirectoryTypes.ModelHomes,\r\n [UrlSubdirectoryTypes.LearningCenter.toString()]: UrlSubdirectoryTypes.LearningCenter,\r\n };\r\n\r\n return subDirectoryTypeMap[key];\r\n }\r\n\r\n /**\r\n * The getInstance function returns an instance of the SubDirectoryTypes class based on the\r\n * provided key, creating a new instance if one does not already exist.\r\n * @param key - The \"name\" parameter is a unique identifier used to determine which instance of the\r\n * \"SubDirectoryTypes\" class to create or retrieve.\r\n * @param configuration an object that contains various properties and values that are used to configure\r\n * the instance of the UrlSubdirectoryTypes class that is being created.\r\n * @returns The instance of the SubDirectoryTypes class with the specified key.\r\n */\r\n static getInstance(key, configuration) {\r\n configuration.name = key;\r\n\r\n if (!this.instances[key]) {\r\n this.instances[key] = new UrlSubdirectoryTypes(configuration);\r\n }\r\n return this.instances[key];\r\n }\r\n\r\n /**\r\n * The constructor function initializes an object with a given name property.\r\n * @param configuration - The `configuration` parameter is an object that contains the configuration\r\n * settings for the constructor. It may contain properties such as `name` and\r\n * `pageType`. The `name` property is a string that represents the name of the\r\n * configuration.\r\n */\r\n constructor(configuration) {\r\n this.name = configuration.name;\r\n this.pageType = configuration.pageType;\r\n this.luxLabel = configuration.luxLabel;\r\n }\r\n\r\n /**\r\n * The toString() function returns the name property of an object as a string.\r\n * @returns The name property of the object.\r\n */\r\n toString() {\r\n return `${this.name}`;\r\n }\r\n}\r\n\r\nObject.defineProperty(UrlSubdirectoryTypes, 'instances', { value: {} });\r\n","import { createAction } from '@reduxjs/toolkit';\r\n\r\n/* Action dispatched after the list view is paitend in the DOM to handler side effects.\r\n */\r\nconst onListViewPaint = createAction('searchResults/listViewPaint');\r\n\r\nexport default onListViewPaint;\r\n","import { createListenerMiddleware } from '@reduxjs/toolkit';\r\nimport { addMiddleware } from 'redux-dynamic-middlewares';\r\nimport { mapStateActions } from 'features/searchResultsMap';\r\n\r\nconst typeaheadInput = document.querySelector('[data-typeahead-input]');\r\nconst listenerMiddleware = createListenerMiddleware();\r\n\r\n/**\r\n * Using the listener middleware to listen to the enableSearchWithinMap action.\r\n * This listener is in charge of cleaning the typeahead field when the enableSearchWithinMap action is dispatched.\r\n */\r\nlistenerMiddleware.startListening({\r\n type: mapStateActions.enableSearchWithinMap.type,\r\n effect: () => {\r\n typeaheadInput.value = '';\r\n },\r\n});\r\n\r\naddMiddleware(listenerMiddleware.middleware);\r\n","import { store$ } from '@redux/store';\r\nimport LeadFormType from 'features/leadGenerators';\r\nimport { selectFavorites, selectIsProfileFavoritesLoaded, selectPendingSaves } from 'features/userProfile';\r\nimport { selectedNearbyListingCarousel } from 'features/searchResultsMap';\r\nimport { selectModal, selectUiState } from 'layout/redux/selectors';\r\nimport { distinctUntilChanged, distinctUntilKeyChanged, filter, map, pairwise,\r\n withLatestFrom, fromEvent, combineLatest } from 'rxjs';\r\nimport RecommendedType from 'constants/RecommendedType';\r\nimport { selectConstructQueryString } from './selectors';\r\n\r\nconst modalTypesForModalSubmissionEvent = [\r\n LeadFormType.BrochureFormPaid.toString(),\r\n LeadFormType.InformationFormPaid.toString(),\r\n LeadFormType.InformationFormBasic.toString(),\r\n LeadFormType.AskQuestionFormPaid.toString(),\r\n];\r\n\r\n/**\r\n * getNewListingSaved: Gets the new listing that was saved.\r\n * @param {Array} previousFavorites Previous Favorite state.\r\n * @param {Array} currentFavorites Favorite state up-to-date.\r\n * @returns The favorite information of the new listing saved, or null if there's no new saved.\r\n */\r\nfunction getNewListingSaved([previousFavorites, currentFavorites]) {\r\n const lastFavorited = currentFavorites[currentFavorites.length - 1];\r\n if (previousFavorites.includes(lastFavorited)) {\r\n return null;\r\n }\r\n\r\n return lastFavorited;\r\n}\r\n\r\n/**\r\n * Allows us to filter by id to search for the deleted id.\r\n * @param {any} prevList previous favorites list.\r\n * @param {any} newList new favorites list.\r\n * @returns Returns the new list with the ids removed.\r\n */\r\nfunction findRemovedItems(prevList, newList) {\r\n const newIds = new Set(newList.map(item => item.listingId));\r\n return prevList.filter(prevItem => !newIds.has(prevItem.listingId));\r\n}\r\n\r\n/**\r\n * An observable that emits the selected marker from the store.\r\n */\r\nconst markerPinClicked$ = fromEvent(document.body, 'markerPinCLicked').pipe(\r\n map(event => event.detail.marker)\r\n);\r\n\r\n/**\r\n * communityStaticMapClicked$ will emit every time user clicks in a community static map.\r\n */\r\nconst communityStaticMapClicked$ = fromEvent(document.body, 'communityStaticMapCLicked').pipe(\r\n map(event => ({\r\n deviceType: event.detail.deviceType,\r\n communityStaticMap: event.detail.communityStaticMap,\r\n})));\r\n\r\n/**\r\n * communityStaticMapDoubleClicked$ will emit every time user doubleclicks in a community static map.\r\n */\r\nconst communityStaticMapDoubleClicked$ = fromEvent(document.body, 'communityStaticMapDoubleCLicked').pipe(\r\n map(event => ({\r\n deviceType: event.detail.deviceType,\r\n communityStaticMap: event.detail.communityStaticMap,\r\n})));\r\n\r\n/**\r\n * communityStaticMapZoomChanged$ will emit every time a community static map adjusted to a new zoom level.\r\n */\r\nconst communityStaticMapZoomChanged$ = fromEvent(document.body, 'communityStaticMapZoom').pipe(\r\n map(event => ({\r\n zoomGesture: event.detail.zoomGesture,\r\n communityStaticMap: event.detail.communityStaticMap,\r\n deviceType: event.detail.deviceType,\r\n zoomLevel: event.detail.zoomLevel,\r\n})));\r\n\r\n/**\r\n * communityStaticMapHovered$ will emit new values every time a community static map was done being hovered. \r\n */\r\nconst communityStaticMapHovered$ = fromEvent(document.body, 'communityStaticMapHover').pipe(\r\n map(event => ({\r\n hoverDuration: event.detail.hoverDuration,\r\n communityStaticMap: event.detail.communityStaticMap,\r\n deviceType: event.detail.deviceType,\r\n})));\r\n\r\n/**\r\n * An observable that emits the selected summary card from the store.\r\n */\r\nconst markerSummaryCardClicked$ = store$.pipe(map(selectedNearbyListingCarousel));\r\n\r\n/**\r\n * Generates an observable from a summaryCardLinkClick Custom Event, then\r\n * bind the data for the active summary card to the summary card link clicked.\r\n */\r\nconst summaryCardLinkClicked$ = fromEvent(document, 'summaryCardLinkClick').pipe(\r\n map((event) => event?.detail?.summaryCard)\r\n);\r\n\r\n/**\r\n * Generates an observable from a 'summaryCardCtaClick' Custom Event, \r\n * which is emitted when a user clicks on a summary card's call to action button.\r\n */\r\nconst summaryCardCtaClicked$ = fromEvent(document, \"summaryCardCtaClick\").pipe(\r\n map((event) => event.detail)\r\n);\r\n\r\n/**\r\n * An observable that emits the scroll event details when the nearby listings carousel is scrolled.\r\n */\r\nconst nearbyListingsCarouselScrolled$ = fromEvent(document, 'carouselScroll').pipe(\r\n map(event => event.detail),\r\n);\r\n\r\n/**\r\n * An observable that emits the details of the summary card close icon click event.\r\n */\r\nconst carouselCloseButtonClicked$ = fromEvent(document, \"carouselClose\").pipe(\r\n map(event => event.detail),\r\n);\r\n\r\nconst pendingListingSaves$ = store$.pipe(\r\n map(selectPendingSaves),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map(([previousPendingListingSaves]) => previousPendingListingSaves)\r\n);\r\n\r\n// Observable created when there is a \"pendingSaves\" object in the redux store.\r\n// This object contains a list of items that the user clicked the favorite button on but were not saved yet.\r\n// (User not logged in).\r\nconst pendingListingSavesFavorites$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise()\r\n);\r\n\r\nconst newListingSaved$ = store$.pipe(\r\n // We have to be sure when the Favorites from server were already loaded.\r\n filter(selectIsProfileFavoritesLoaded),\r\n map(selectFavorites),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map(getNewListingSaved),\r\n filter(Boolean),\r\n // We cannot work directly with the favorited information because it will have very simple information.\r\n // So, to get the listing information, we are going to consume pendingSaves property,\r\n // where the listing information is being saved by us. In this way we don't add more logic or information to the\r\n // favorited object that should be very basic as it is only a favorite.\r\n withLatestFrom(pendingListingSaves$),\r\n map(([newListingSaved, pendingListingSaves]) =>\r\n pendingListingSaves.find(\r\n (pendingSave) => Number(pendingSave.listingInformation.id) === Number(newListingSaved.listingId)\r\n )\r\n ),\r\n filter(Boolean)\r\n);\r\n\r\n// observable created when there is an add to the redux store object \"pendingSaves\".\r\n// this object contains a list of items that the user clicked but are not already saved. (User not logged in)\r\n// It will filter the actions to now when it changes.\r\nconst onPendingFavoritesChanged$ = store$.pipe(\r\n map(selectPendingSaves),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map(([lastValue, newValue]) => {\r\n const newItems = newValue.filter((item) => !lastValue.includes(item));\r\n return newItems;\r\n }),\r\n filter((newItems) => newItems.length > 0),\r\n map((newItems) => newItems[newItems.length - 1])\r\n);\r\n\r\n// Observable that emits when an item has been removed from the favorites list.\r\nconst removedFavorites$ = store$.pipe(\r\n filter(selectIsProfileFavoritesLoaded),\r\n map(selectFavorites),\r\n filter(Boolean),\r\n distinctUntilChanged(),\r\n pairwise(),\r\n map(([lastValue, newValue]) => findRemovedItems(lastValue, newValue)),\r\n filter((removedItems) => removedItems.length > 0),\r\n map((removedItems) => removedItems[removedItems.length - 1])\r\n);\r\n\r\nconst paidCommunityModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'community'),\r\n filter((modalInformation) => modalInformation.listingInformation.isBasic === 'false'),\r\n filter((modalInformation) => !modalInformation.listingInformation.isMasterPlanCommunity),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst basicCommunityModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'community'),\r\n filter((modalInformation) => modalInformation.listingInformation.isBasic === 'true'),\r\n filter((modalInformation) => !modalInformation.listingInformation.isMasterPlanCommunity),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst paidMasterPlanCommunityModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'community'),\r\n filter((modalInformation) => modalInformation.listingInformation.isMasterPlanCommunity === 'true'),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst recommendedCommunitiesSubmitted$ = store$.pipe(\r\n map(selectModal),\r\n filter(Boolean),\r\n distinctUntilKeyChanged('previousName'),\r\n filter(\r\n (modalInformation) =>\r\n modalInformation.type === 'community' || modalInformation.type === 'spec' || modalInformation.type === 'plan'\r\n ),\r\n filter((modalInformation) => modalInformation.previousName === 'recommendedScreen'),\r\n filter((modalInformation) => Boolean(modalInformation.selectedRecommendedCommunities)),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst recommendedCommunitiesSubmittedBasic$ = store$.pipe(\r\n map(selectModal),\r\n filter(Boolean),\r\n distinctUntilKeyChanged('previousName'),\r\n filter(\r\n (modalInformation) =>\r\n modalInformation.type === 'community' || \r\n modalInformation.type === 'spec' || \r\n modalInformation.type === 'plan' ||\r\n modalInformation.type === 'basicListing'\r\n ),\r\n filter((modalInformation) => modalInformation.previousName === 'recommendedScreenBasic'),\r\n filter((modalInformation) => Boolean(modalInformation.selectedRecommendedCommunities)),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst recommendedCommunitiesShow$ = store$.pipe(\r\n map(selectModal),\r\n filter(Boolean),\r\n filter(\r\n (modalInformation) =>\r\n modalInformation.name === RecommendedType.RecommendedPaid().getName() ||\r\n modalInformation.name === RecommendedType.RecommendedBasic().getName()\r\n ),\r\n distinctUntilChanged()\r\n);\r\n\r\nconst paidHomeModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'spec' || modalInformation.type === 'plan'),\r\n filter((modalInformation) => modalInformation.variation !== 'basic'),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst basicPlanModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'plan' ),\r\n filter((modalInformation) => modalInformation.variation === 'basic'),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst basicSpecModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'spec'),\r\n filter((modalInformation) => modalInformation.variation === 'basic'),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst basicListingModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'basicListing'),\r\n filter((modalInformation) => modalInformation.variation === 'basic'),\r\n filter((modalInformation) => modalTypesForModalSubmissionEvent.includes(modalInformation.leadGeneratorOpener))\r\n);\r\n\r\nconst paidManufacturedLocationModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'community'),\r\n filter(\r\n (modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.ManufacturedBrochureFormPaid.toString()\r\n )\r\n);\r\n\r\nconst paidManufacturedPlanModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'plan'),\r\n filter(\r\n (modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.ManufacturedBrochureFormPaid.toString()\r\n )\r\n);\r\n\r\nconst paidManufacturedSpecModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'spec'),\r\n filter(\r\n (modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.ManufacturedBrochureFormPaid.toString()\r\n )\r\n);\r\n\r\nconst paidAskAQuestionLocationModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'community'),\r\n filter((modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.AskQuestionFormPaid.toString())\r\n);\r\n\r\nconst paidAskAQuestionPlanModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'plan'),\r\n filter((modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.AskQuestionFormPaid.toString())\r\n);\r\n\r\nconst paidAskAQuestionSpecModalSubmission$ = store$.pipe(\r\n map(selectUiState),\r\n distinctUntilKeyChanged('isFetchingModal'),\r\n filter((uiState) => uiState.isFetchingModal),\r\n map((uiState) => uiState.modalInformation),\r\n filter((modalInformation) => modalInformation.name === 'leadGenerator'),\r\n filter((modalInformation) => modalInformation.type === 'spec'),\r\n filter((modalInformation) => modalInformation.leadGeneratorOpener === LeadFormType.AskQuestionFormPaid.toString())\r\n);\r\n\r\n/**\r\n * An observable that emits an event when the 'openMarkerUrl' event is triggered on the document body.\r\n * The observable filters the events to only include those where the marker Id is present in the event detail.\r\n */\r\nconst urlOpened$ = fromEvent(document.body, \"openMarkerUrl\").pipe(\r\n filter((event) => Boolean(event?.detail?.marker?.id))\r\n);\r\n\r\n\r\n/**\r\n * Emits an observable that combines the `markerClicked$` and `urlOpened$` observables,\r\n * and filters the result to only include events where the marker ID matches the event's marker ID.\r\n * The emitted value includes the interaction type, the marker, and the timestamp of the event.\r\n * The observable will only emit distinct values based on the timestamp. This is done in order to prevent\r\n * triggering multiple times for the same interaction.\r\n */\r\nconst markerUrlOpened$ = combineLatest([markerPinClicked$, urlOpened$]).pipe(\r\n filter(([marker, event]) => marker?.id === event?.detail?.marker?.id),\r\n map(([marker, event]) => ({\r\n interactionType: event?.detail.interactionType,\r\n marker,\r\n timeStamp: event.timeStamp,\r\n })),\r\n distinctUntilKeyChanged(\"timeStamp\")\r\n);\r\n\r\n/**\r\n * An observable that emits when the modal close button is clicked.\r\n * The emitted event contains the modal information in the `detail` property.\r\n */\r\nconst modalCloseButtonClicked$ = fromEvent(document.body, \"modalClosed\").pipe(\r\n filter((event) => Boolean(event?.detail?.modalInformation))\r\n);\r\n\r\n/**\r\n* This observable will stream any time the seach query string changes.\r\n*/\r\nconst onQueryStringChanged$ = store$.pipe(\r\n map(selectConstructQueryString),\r\n distinctUntilChanged(),\r\n);\r\n\r\nexport {\r\n newListingSaved$,\r\n paidCommunityModalSubmission$,\r\n basicCommunityModalSubmission$,\r\n paidMasterPlanCommunityModalSubmission$,\r\n recommendedCommunitiesSubmitted$,\r\n recommendedCommunitiesSubmittedBasic$,\r\n paidHomeModalSubmission$,\r\n basicPlanModalSubmission$,\r\n basicSpecModalSubmission$,\r\n basicListingModalSubmission$,\r\n paidManufacturedLocationModalSubmission$,\r\n paidManufacturedPlanModalSubmission$,\r\n paidManufacturedSpecModalSubmission$,\r\n paidAskAQuestionLocationModalSubmission$,\r\n paidAskAQuestionPlanModalSubmission$,\r\n paidAskAQuestionSpecModalSubmission$,\r\n markerPinClicked$,\r\n markerSummaryCardClicked$,\r\n summaryCardLinkClicked$,\r\n summaryCardCtaClicked$,\r\n markerUrlOpened$,\r\n modalCloseButtonClicked$,\r\n onQueryStringChanged$,\r\n onPendingFavoritesChanged$,\r\n pendingListingSavesFavorites$,\r\n removedFavorites$,\r\n nearbyListingsCarouselScrolled$,\r\n carouselCloseButtonClicked$,\r\n communityStaticMapClicked$,\r\n communityStaticMapDoubleClicked$,\r\n communityStaticMapZoomChanged$,\r\n communityStaticMapHovered$,\r\n recommendedCommunitiesShow$,\r\n};\r\n","import { createSelector } from '@reduxjs/toolkit';\r\nimport { PillType } from 'features/popularSearches';\r\nimport { selectUrlSubdirectory, routingSelectors, selectMapCoordinatesQueryString } from 'features/routing';\r\nimport {\r\n selectLocationType,\r\n selectSearchCount,\r\n activeAdultCommunitiesSelector,\r\n selectConsumerPromos,\r\n selectCondosAndTownHomes,\r\n selectMarketingStatus,\r\n selectHomeStatus,\r\n hasInventoryStatusCombination,\r\n hasReadyToBuild,\r\n selectFetchResultListingsStatus,\r\n selectPage,\r\n selectPageSize,\r\n selectListingCount,\r\n selectBedrooms,\r\n selectBathrooms,\r\n selectGatedCommunity,\r\n selectGolfCourse,\r\n selectGreen,\r\n selectLuxury,\r\n selectMaximumPrice,\r\n selectMinimumPrice,\r\n selectNatureAreas,\r\n selectParks,\r\n selectPool,\r\n selectSorting,\r\n selectSportsFacilities,\r\n selectViews,\r\n selectWaterfront,\r\n SortType,\r\n selectResultType,\r\n selectLivingAreas,\r\n selectGarages,\r\n selectStories,\r\n selectPrimaryBedroom,\r\n selectRvGarage,\r\n selectReviews,\r\n selectMoveInDateRange,\r\n hasAvailableNow,\r\n selectPriceReduction,\r\n ResultType,\r\n selectPaging,\r\n selectLocation,\r\n selectHomeOwnersAssociationFee,\r\n} from 'features/searchResultsFacets';\r\nimport { geoCoordinates, isMapIdle, selectedMarker } from 'features/searchResultsMap';\r\nimport LayoutBreakpoint from 'layout/enums/layoutBreakpoint';\r\nimport { selectDisplaySkeleton,\r\n selectIsMarkerAutoScrollFeatureEnabled,\r\n selectLayoutBreakpoint,\r\n selectResultsPresentationType } from 'layout/redux/selectors';\r\nimport { isComingSoon, isCloseOut, isGrandOpening, isActive } from 'services/marketingStatusValidator';\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\n/**\r\n * Returns true if the user is doing a current location search.\r\n * @param state - The state of the Redux store.\r\n */\r\nexport const selectIsCurrentLocationSearch = (state) => state?.searchParameters?.isCurrentLocationSearch;\r\n\r\n/**\r\n * Returns a composed selector that provides information to support current location searches.\r\n */\r\nexport const selectCurrentLocationSearchInformation = createSelector(\r\n geoCoordinates,\r\n selectIsCurrentLocationSearch,\r\n isMapIdle,\r\n (geographicCoordinates, isCurrentLocationSearch, isMapReady) => ({\r\n geographicCoordinates,\r\n isCurrentLocationSearch,\r\n isMapReady,\r\n })\r\n);\r\n\r\n/**\r\n * Selector that maps different pill types to their corresponding filter values.\r\n */\r\nexport const selectPopularPillFilters = createSelector(\r\n selectConsumerPromos,\r\n selectCondosAndTownHomes,\r\n activeAdultCommunitiesSelector,\r\n selectMarketingStatus,\r\n selectHomeStatus,\r\n (consumerPromos, condosAndTownHomes, activeAdultCommunities, marketingStatus, homeStatus) => ({\r\n [PillType.HotDeals.toString()]: consumerPromos,\r\n [PillType.CondosAndTownhomes.toString()]: condosAndTownHomes,\r\n [PillType.Adult.toString()]: activeAdultCommunities.only,\r\n [PillType.ComingSoon.toString()]: isComingSoon(marketingStatus),\r\n [PillType.FloorPlans.toString()]: hasReadyToBuild(homeStatus),\r\n [PillType.QuickMoveIns.toString()]: hasInventoryStatusCombination(homeStatus),\r\n })\r\n);\r\n\r\n/**\r\n * Composed selector that takes three input selectors the counts, urlSubdirectory and locationType\r\n * to paint the paints with this parameters information. The popularPillFilters is useful to check or un check pill.\r\n */\r\nexport const selectPopularSearchesPills = createSelector(\r\n selectSearchCount,\r\n selectUrlSubdirectory,\r\n selectLocationType,\r\n selectPopularPillFilters,\r\n (searchCounts, urlSubdirectory, locationType, popularPillFilters) => {\r\n const pillsCounts = {\r\n [PillType.HotDeals.toString()]: searchCounts.hotDealsCount,\r\n [PillType.CondosAndTownhomes.toString()]: searchCounts.multiFamilyCount, \r\n [PillType.Adult.toString()]: searchCounts.adultCount,\r\n [PillType.QuickMoveIns.toString()]: searchCounts.quickMoveInCount,\r\n [PillType.FloorPlans.toString()]: searchCounts.buildablePlansCount,\r\n [PillType.ComingSoon.toString()]: searchCounts.comingSoonCount,\r\n };\r\n\r\n const pillsWithCounts = Object.keys(pillsCounts).filter((pillType) => pillsCounts[pillType] > 0);\r\n\r\n return {\r\n pillsWithCounts,\r\n urlSubdirectory,\r\n locationType,\r\n popularPillFilters,\r\n };\r\n }\r\n);\r\n\r\n/**\r\n * Composed selector to map the subdirectory and location type. */\r\nexport const selectUrlSubdirectoryAndLocationType = createSelector(\r\n selectUrlSubdirectory,\r\n selectLocationType,\r\n (urlSubdirectory, locationType) => ({\r\n urlSubdirectory,\r\n locationType,\r\n })\r\n);\r\n\r\nexport const urlComponentsWithHomeStatusSelector = createSelector(\r\n urlComponentsSelector,\r\n selectHomeStatus,\r\n (urlComponents, homeStatus) => ({\r\n urlComponents,\r\n homeStatus,\r\n })\r\n);\r\n\r\n\r\n/**\r\n * Selector composed by the results to be loaded, current results presentation type and fetch result listings status.\r\n */\r\nexport const selectResultsLoadedAndResultsPresentationType = createSelector(\r\n selectResultsPresentationType,\r\n selectFetchResultListingsStatus,\r\n (presentationType, fetchListingStatus) => ({\r\n presentationType,\r\n fetchListingStatus,\r\n })\r\n);\r\n\r\n/**\r\n * Selector composed by the results presentation type and the fetch result listings status.\r\n */\r\nexport const resultStatusAndResultsPresentationType = createSelector(\r\n selectResultsPresentationType,\r\n selectFetchResultListingsStatus,\r\n (presentationType, fetchResultListingStatus) => ({\r\n presentationType,\r\n fetchResultListingStatus,\r\n })\r\n);\r\n\r\n/**\r\n * Selector to get a flag indicating if the grid skeleton needs to be shown,\r\n * and also the current presentation type of the Search Results Page\r\n */\r\nexport const selectDisplaySkeletonAndResultsPresentationType = createSelector(\r\n selectDisplaySkeleton,\r\n selectResultsPresentationType,\r\n (shouldDisplaySkeleton, resultsPresentationType) => ({\r\n shouldDisplaySkeleton,\r\n resultsPresentationType,\r\n })\r\n);\r\n\r\n/**\r\n * Selector composed by the current presentation type and the page number served to the user.\r\n */\r\nexport const selectPagingAndResultPresentationType = createSelector(\r\n selectResultsPresentationType,\r\n selectPage,\r\n (resultsPresentationType, page) => ({\r\n resultsPresentationType,\r\n page,\r\n })\r\n);\r\n\r\n/**\r\n * This selector is composed by the fetch listings status, current page number, amount of results shown per page\r\n * and the total of results of the current search.\r\n * With this set of information, we know if we already saw the total of results the current Search Results Page\r\n * has to offer, or is there are still more results to fetch for the user.\r\n */\r\nexport const selectPageInformationAndFetchResultsStatus = createSelector(\r\n selectFetchResultListingsStatus,\r\n selectResultsPresentationType,\r\n selectPage,\r\n selectPageSize,\r\n selectListingCount,\r\n (fetchResultListingsStatus, resultPresentationType, page, pageSize, listingCount) => ({\r\n fetchResultListingsStatus,\r\n resultPresentationType,\r\n page,\r\n pageSize,\r\n listingCount,\r\n })\r\n);\r\n\r\n/**\r\n * This selector is meant for derive the Search Results Page query string based in the current store values.\r\n * The selector transforms the store data into a string that represents the filters applied by the user.\r\n */\r\nexport const selectConstructQueryString = createSelector(\r\n selectBedrooms,\r\n selectBathrooms,\r\n selectNatureAreas,\r\n selectGreen,\r\n selectPool,\r\n selectGatedCommunity,\r\n selectGolfCourse,\r\n selectSportsFacilities,\r\n selectParks,\r\n selectViews,\r\n selectWaterfront,\r\n selectLuxury,\r\n selectMaximumPrice,\r\n selectMinimumPrice,\r\n selectSorting,\r\n selectMapCoordinatesQueryString,\r\n selectLivingAreas,\r\n selectGarages,\r\n selectStories,\r\n selectPrimaryBedroom,\r\n selectRvGarage,\r\n selectMarketingStatus,\r\n selectReviews,\r\n activeAdultCommunitiesSelector,\r\n selectHomeStatus,\r\n selectMoveInDateRange,\r\n selectConsumerPromos,\r\n selectPriceReduction,\r\n selectHomeOwnersAssociationFee,\r\n (\r\n bedrooms,\r\n bathrooms,\r\n natureAreas,\r\n green,\r\n pool,\r\n gated,\r\n golfcourse,\r\n sports,\r\n parks,\r\n views,\r\n waterFront,\r\n luxury,\r\n maximumPrice,\r\n minimumPrice,\r\n sorting,\r\n mapCoordinates,\r\n livingAreas,\r\n garages,\r\n stories,\r\n primaryBedroom,\r\n rvGarage,\r\n marketingStatus,\r\n reviews,\r\n activeAdult,\r\n homeStatus,\r\n moveInDateRange,\r\n consumerPromos,\r\n priceReduction,\r\n hasHomeOwnersAssociationFee\r\n ) => {\r\n\r\n const parameters = new URLSearchParams();\r\n\r\n // Helper function to append parameters only if they are valid\r\n const appendIfValid = (key, value) => {\r\n if (value && value !== \"0\") {\r\n parameters.append(key, value);\r\n }\r\n };\r\n\r\n // Transforms the primary bed store information into a recognizable query string.\r\n const getPrimaryBed = (primaryBed) => {\r\n switch (primaryBed) {\r\n case \"1\":\r\n return \"up\";\r\n case \"2\":\r\n return \"down\";\r\n default:\r\n return null;\r\n }\r\n };\r\n\r\n // Transform the move in date information into a recognizable query string.\r\n const getAvailability = (status, moveInDate) => {\r\n if (moveInDate) {\r\n return moveInDate;\r\n }\r\n\r\n return !hasInventoryStatusCombination(status) && hasAvailableNow(status) ? \"now\" : null;\r\n };\r\n\r\n appendIfValid('bed', bedrooms);\r\n appendIfValid('bath', bathrooms);\r\n appendIfValid('natureareas', natureAreas);\r\n appendIfValid('green', green);\r\n appendIfValid('pool', pool);\r\n appendIfValid('gated', gated);\r\n appendIfValid('golfcourse', golfcourse);\r\n appendIfValid('sports', sports);\r\n appendIfValid('parks', parks);\r\n appendIfValid('views', views);\r\n appendIfValid('waterfront', waterFront);\r\n appendIfValid('luxury', luxury);\r\n appendIfValid('pricehigh', maximumPrice);\r\n appendIfValid('pricelow', minimumPrice);\r\n appendIfValid('living', livingAreas);\r\n appendIfValid('garage', garages);\r\n appendIfValid('stories', stories);\r\n appendIfValid('rvgarage', rvGarage);\r\n appendIfValid('reviews', reviews);\r\n appendIfValid('hotdeals', consumerPromos);\r\n appendIfValid('pricedrop', priceReduction);\r\n appendIfValid('hoa', hasHomeOwnersAssociationFee);\r\n appendIfValid('comingsoon', isComingSoon(marketingStatus));\r\n appendIfValid('closeout', isCloseOut(marketingStatus));\r\n appendIfValid('grandopening', isGrandOpening(marketingStatus));\r\n appendIfValid('active', isActive(marketingStatus));\r\n appendIfValid('primarybed', getPrimaryBed(primaryBedroom));\r\n appendIfValid('availability', getAvailability(homeStatus, moveInDateRange));\r\n appendIfValid('inventory', hasInventoryStatusCombination(homeStatus));\r\n\r\n const { exclude, only } = activeAdult;\r\n appendIfValid('adult', only);\r\n appendIfValid('exclude55', exclude);\r\n\r\n // Facets are the first thing to appear in the query string, they must be alphabetically sorted.\r\n parameters.sort();\r\n\r\n // Map coordinates should appear after any user applied filter in the query string.\r\n const appendMapCoordinates = (coordinates) => {\r\n if (coordinates) {\r\n const [key, value] = coordinates.split('=');\r\n parameters.append(key, value);\r\n }\r\n };\r\n\r\n // Last thing to appear in the query string is any user applied sorting value\r\n const appendSortingOptions = (sort) => {\r\n if (sort && sort.sortBy && sort.sortBy !== SortType.CommunityId.toString()) {\r\n const sortingOption = SortType.fromKey(sort.sortBy.toLowerCase());\r\n parameters.append('sortby', sortingOption.getQueryStringValue(!sort.sortOrder));\r\n }\r\n };\r\n\r\n const constructQueryString = () => {\r\n const queryString = parameters.toString();\r\n return queryString ? `?${decodeURIComponent(queryString)}` : '';\r\n };\r\n\r\n appendMapCoordinates(mapCoordinates);\r\n appendSortingOptions(sorting);\r\n\r\n return constructQueryString();\r\n }\r\n);\r\n\r\n/**\r\n * This selector is meant for derive the Search Results Page no results query string based in the current store values.\r\n * The selector transforms the store data into a string that represents the filters applied by the user.\r\n */\r\nexport const selectConstructMinimumRequiredFiltersQueryString = createSelector(\r\n selectMapCoordinatesQueryString,\r\n selectSorting,\r\n selectResultType,\r\n (\r\n mapCoordinates,\r\n sorting,\r\n resultType,\r\n ) => {\r\n\r\n const parameters = new URLSearchParams();\r\n\r\n const appendMapCoordinates = (coordinates) => {\r\n if (coordinates) {\r\n const [key, value] = coordinates.split('=');\r\n parameters.append(key, value);\r\n }\r\n };\r\n\r\n const appendSortingOptions = (sort) => {\r\n if (sort && sort.sortBy && sort.sortBy !== SortType.CommunityId.toString()) {\r\n const sortingOption = SortType.fromKey(sort.sortBy.toLowerCase());\r\n parameters.append('sortby', sortingOption.getQueryStringValue(!sort.sortOrder));\r\n }\r\n };\r\n\r\n const constructQueryString = () => {\r\n const queryString = parameters.toString();\r\n return queryString ? `?${decodeURIComponent(queryString)}` : '';\r\n };\r\n\r\n appendMapCoordinates(mapCoordinates);\r\n\r\n if (resultType !== ResultType.Builders.toString()) {\r\n appendSortingOptions(sorting);\r\n }\r\n\r\n return constructQueryString();\r\n }\r\n);\r\n\r\n/**\r\n * Selects information about listing counts and query string constructor.\r\n */\r\nexport const selectCountsAndQueryString = createSelector(\r\n selectListingCount,\r\n selectFetchResultListingsStatus,\r\n selectResultType,\r\n selectConstructQueryString,\r\n selectConstructMinimumRequiredFiltersQueryString,\r\n (\r\n listingCounts,\r\n resultCountsStatus,\r\n resultType,\r\n queryString,\r\n minimumRequiredFiltersQueryString,\r\n ) =>\r\n ({ \r\n listingCounts,\r\n resultCountsStatus,\r\n resultType,\r\n queryString,\r\n minimumRequiredFiltersQueryString\r\n })\r\n );\r\n\r\n/**\r\n * This selector is created to retieve all the required information for tha native ads implementation\r\n * Returnig an Object with:\r\n * - Result Listing Status\r\n * - Presentation Type\r\n * - Paging\r\n * - Result Type\r\n * - Location\r\n * - Ads\r\n */\r\nexport const selectNativeAdInformation = createSelector(\r\n selectFetchResultListingsStatus,\r\n selectResultsPresentationType,\r\n selectPaging,\r\n selectResultType,\r\n selectLocation,\r\n (\r\n fetchResultListingsStatus,\r\n resultsPresentationType,\r\n paging,\r\n resultType,\r\n location,\r\n ) => ({ \r\n fetchResultListingsStatus,\r\n resultsPresentationType,\r\n paging,\r\n resultType,\r\n location,\r\n })\r\n );\r\n\r\n/*\r\n * Selector to get the SelectedMarker, FetchReult, ResultType, CurrentPageNumber, map visible and listview visible\r\n*/\r\nexport const selectSelectedMarker = createSelector(\r\n selectedMarker,\r\n selectFetchResultListingsStatus,\r\n selectResultType,\r\n selectPage,\r\n selectIsMarkerAutoScrollFeatureEnabled,\r\n selectLayoutBreakpoint,\r\n (marker, fetchResultListingsStatus, resultType, page, isMarkerAutoScrollFeatureEnabled, layoutBreakpoint) => {\r\n if (isMarkerAutoScrollFeatureEnabled === false || \r\n layoutBreakpoint.getValue() === LayoutBreakpoint.Small.getValue() ||\r\n resultType !== ResultType.Communities.toString()){\r\n return null;\r\n }\r\n \r\n return {\r\n marker,\r\n fetchResultListingsStatus,\r\n resultType,\r\n page,\r\n }\r\n }\r\n);","import { store, store$ } from '@redux/store';\r\nimport { getBrandName, routingStateActions } from 'features/routing';\r\nimport { map, distinctUntilChanged, filter, skip } from 'rxjs';\r\nimport { selectBrand, ResultType } from 'features/searchResultsFacets';\r\n\r\nconst onBuilderSelected$ = store$.pipe(map(selectBrand), filter(Boolean), distinctUntilChanged(), skip(1));\r\n\r\n/**\r\n * updateUrlPaging: Updates the page on the url.\r\n * @param {Number} pageNumber Number of the selected page.\r\n */\r\nconst updateBuilderName = (brand) => {\r\n setTimeout(() => {\r\n const { brandName, brandId, resultType } = brand;\r\n const builderSegment = resultType !== ResultType.Builders.toString() ? getBrandName(brandName, brandId) : '';\r\n\r\n store.dispatch(routingStateActions.updateBuilderName(builderSegment));\r\n });\r\n};\r\n\r\nonBuilderSelected$.subscribe(updateBuilderName);\r\n","/**\r\n * In this file we will import the code that handles other types of URL changes\r\n * For example, product type changes, pagination changes, amenities changes, etc\r\n */\r\nrequire('./locations');\r\nrequire('./subdirectory');\r\nrequire('./queryString');\r\nrequire('./paging');\r\nrequire('./pageUrls');\r\nrequire('./builderName');\r\nrequire('./mapCoordinatesUrl');","import { store$, store } from \"@redux/store\";\r\nimport { map, filter, distinctUntilChanged, skip } from \"rxjs\";\r\nimport { routingStateActions } from 'features/routing';\r\nimport { LocationType } from 'features/searchResultsFacets';\r\n\r\nconst locationSelector = (state) => state?.searchParameters?.location;\r\n\r\nconst validLocationTypes = [\r\n LocationType.County.toString(),\r\n LocationType.City.toString(),\r\n LocationType.Zip.toString(),\r\n LocationType.Market.toString(),\r\n LocationType.Synthetic.toString(),\r\n LocationType.RectangularArea.toString(),\r\n];\r\n\r\nconst onLocationChange$ = store$.pipe(\r\n map(locationSelector),\r\n filter((location) => validLocationTypes.includes(location.locationType)),\r\n distinctUntilChanged(),\r\n skip(1));\r\n\r\n/**\r\n * getUrlLocationSegments: Gets the url segments related to the location.\r\n * For example: tx/austin-area, tx/austin-area/round-rock, tx/houston-area/77433.\r\n * @param {Object} location Current location information.\r\n * @returns The url segments related to the location.\r\n */\r\nconst getUrlLocationSegments = (location) => {\r\n const locationType = location?.locationType;\r\n\r\n const locationSegmentsMap = {\r\n [LocationType.County.toString()]: `${location.marketState}/${location.marketName}-area/${location.county}-county`,\r\n [LocationType.City.toString()]: `${location.marketState}/${location.marketName}-area/${location.city}`,\r\n [LocationType.Zip.toString()]: `${location.marketState}/${location.marketName}-area/${location.zip}`,\r\n [LocationType.Market.toString()]: `${location.marketState}/${location.marketName}-area`,\r\n [LocationType.Synthetic.toString()]: `${location.syntheticGeographicName}`,\r\n [LocationType.RectangularArea.toString()]:\r\n `map?coordinates=${location.minimumLatitude},${location.minimumLongitude},${location.maximumLatitude},${location.maximumLongitude}`,\r\n };\r\n \r\n const urlLocationSegments = locationSegmentsMap[locationType];\r\n return urlLocationSegments.toLowerCase().replaceAll(' ','-');\r\n}\r\n\r\n/**\r\n * updateUrlOnLocationChanged: Updates the url location segments on store.\r\n * @param {Object} location Current location information.\r\n */\r\nconst updateUrlOnLocationChanged = (location) => {\r\n const newLocationSegments = getUrlLocationSegments(location);\r\n store.dispatch(routingStateActions.updateLocation(newLocationSegments));\r\n};\r\n\r\nonLocationChange$.subscribe(updateUrlOnLocationChanged);","import { store$, store } from \"@redux/store\";\r\nimport { routingStateActions } from 'features/routing';\r\nimport { LocationType, selectLocationType } from \"features/searchResultsFacets\";\r\nimport { locationSearchParameters, isSearchWithinMapEnabled } from \"features/searchResultsMap\";\r\nimport { distinctUntilChanged, filter, map, skip } from \"rxjs\";\r\nimport { getMapCoordinatesQueryString } from \"../services/pageUrlBuilder\";\r\n\r\n/**\r\n * This function updates the URL search query string with new map coordinates and sets the location as\r\n * \"/map\".\r\n * @param locationParameters - Has the location searchParameters property that provides the coordinates\r\n * used on the search to retrieve the listings based on the current search within map.\r\n */\r\nconst updateUrlSearchWithinMapQueryString = (locationParameters) => {\r\n\r\n const newUrlCoordinatesQueryString = getMapCoordinatesQueryString(locationParameters);\r\n\r\n store.dispatch(routingStateActions.updateRectangularSearchQueryString(newUrlCoordinatesQueryString));\r\n}\r\n\r\n/**\r\n * This function removes the search within map query string from the routing state.\r\n */\r\nconst removeUrlSearchWithinMapQueryString = () => {\r\n\r\n store.dispatch(routingStateActions.updateRectangularSearchQueryString(''));\r\n}\r\n\r\n/* This code is setting up a subscription to the `store$` observable, which emits the current state of\r\nthe Redux store. The subscription is using a series of operators to filter, map, and transform the\r\nemitted values before passing them to the `updateUrlSearchWithinMapQueryString` function. */\r\nstore$\r\n.pipe(\r\n filter(isSearchWithinMapEnabled),\r\n map(locationSearchParameters),\r\n distinctUntilChanged(),\r\n)\r\n.subscribe(updateUrlSearchWithinMapQueryString);\r\n\r\n/* This code sets up a subscription to the `store$` observable, which emits the current state of the\r\nRedux store. The subscription uses a series of operators to filter, map, and transform the emitted\r\nvalues before passing them to the `removeUrlSearchWithinMapQueryString` function. */\r\nstore$.pipe(\r\n map(selectLocationType),\r\n distinctUntilChanged(),\r\n skip(1),\r\n filter((locationType) => locationType !== LocationType.RectangularArea.toString())\r\n)\r\n.subscribe(removeUrlSearchWithinMapQueryString);","import { store, store$ } from '@redux/store';\r\nimport { createSelector } from '@reduxjs/toolkit';\r\nimport { getPaging, routingSelectors, routingStateActions } from 'features/routing';\r\nimport { pageCountSelector, selectPage } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, filter, map, skip, withLatestFrom } from 'rxjs';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport { selectResultsPresentationType } from 'layout/redux/selectors';\r\nimport { getNextPageUrl, getPreviousPageUrl } from '../services/pageUrlBuilder';\r\n\r\nconst { selectCurrentUrl, urlComponentsSelector } = routingSelectors;\r\nconst pageLinkDataSelector = createSelector(\r\n selectCurrentUrl,\r\n urlComponentsSelector,\r\n pageCountSelector,\r\n selectPage,\r\n (currentUrl, urlComponents, pageCount, currentPage) => ({ currentUrl, urlComponents, pageCount, currentPage })\r\n);\r\n\r\nconst presentationType$ = store$.pipe(map(selectResultsPresentationType), distinctUntilChanged());\r\n\r\n/**\r\n * cleanUpPreviousAndNextPages: this function clean up the previous and next pages for SEO concerns.\r\n */\r\nconst cleanUpPreviousAndNextPages = () => {\r\n store.dispatch(routingStateActions.updatePreviousPageUrl(''));\r\n store.dispatch(routingStateActions.updateNextPageUrl(''));\r\n};\r\n\r\nconst urlChange$ = store$.pipe(\r\n map(pageLinkDataSelector),\r\n distinctUntilChanged(),\r\n skip(1),\r\n withLatestFrom(presentationType$),\r\n filter(([, presentationType]) => presentationType !== ResultPresentationType.InfiniteScrolling.toString()),\r\n map(([urlInformation]) => urlInformation)\r\n);\r\n\r\n/**\r\n * updateNextPageUrl: Updates the next page url on the store.\r\n * @param {Object} urlComponents Object with the components used on the url.\r\n * @param {Number} currentPage Current page of the search.\r\n */\r\nfunction updateNextPageUrl({ urlComponents, currentPage, pageCount }) {\r\n const { urlSubdirectory, urlLocation, urlQueryString } = urlComponents;\r\n const nextPageUrlPagination = getPaging(currentPage + 1);\r\n\r\n const nextPageUrlComponents = {\r\n urlSubdirectory,\r\n urlLocation,\r\n urlPaging: nextPageUrlPagination,\r\n urlQueryString,\r\n };\r\n const pagingInformation = {\r\n currentPage,\r\n lastPage: pageCount,\r\n };\r\n\r\n const nextPageUrl = getNextPageUrl(pagingInformation, nextPageUrlComponents);\r\n setTimeout(() => store.dispatch(routingStateActions.updateNextPageUrl(nextPageUrl)), 0);\r\n}\r\n\r\nurlChange$.subscribe(updateNextPageUrl);\r\n\r\n/**\r\n * updatePreviousPageUrl: Updates the previous page url on the store.\r\n * @param {Object} urlComponents Object with the components used on the url.\r\n * @param {Number} currentPage Current page of the search.\r\n */\r\nfunction updatePreviousPageUrl({ urlComponents, currentPage }) {\r\n const { urlSubdirectory, urlLocation, urlQueryString } = urlComponents;\r\n const previousPageUrlPagination = getPaging(currentPage - 1);\r\n\r\n const previousPageUrlComponents = {\r\n urlSubdirectory,\r\n urlLocation,\r\n urlPaging: previousPageUrlPagination,\r\n urlQueryString,\r\n };\r\n\r\n const previousPageUrl = getPreviousPageUrl(currentPage, previousPageUrlComponents);\r\n setTimeout(() => store.dispatch(routingStateActions.updatePreviousPageUrl(previousPageUrl)), 0);\r\n}\r\n\r\nurlChange$.subscribe(updatePreviousPageUrl);\r\n\r\n/**\r\n * Subscribing to the store, if loading status is succeeded (ajax rendered results), and also\r\n * the current Search Results Page is showing results in an infinite scroll way, then we clean\r\n * up the previous and next pages in SEO since there is no pagination.\r\n */\r\nstore$\r\n .pipe(\r\n map(selectResultsPresentationType),\r\n distinctUntilChanged(),\r\n filter((presentationType) => presentationType === ResultPresentationType.InfiniteScrolling.toString())\r\n )\r\n .subscribe(cleanUpPreviousAndNextPages);\r\n","import { store, store$ } from '@redux/store';\r\nimport { getPaging, routingStateActions } from 'features/routing';\r\nimport ResultPresentationType from 'layout/constants/resultPresentationType';\r\nimport { selectResultsPresentationType } from 'layout/redux/selectors';\r\nimport { map, distinctUntilChanged, skip, filter } from 'rxjs';\r\nimport { selectPagingAndResultPresentationType } from '../redux/selectors';\r\n\r\nconst pagingBar = document.querySelector(\"[data-pagination]\");\r\nconst pageNumberChange$ = store$.pipe(\r\n map(selectPagingAndResultPresentationType),\r\n filter((information) => information.resultsPresentationType !== ResultPresentationType.InfiniteScrolling.toString()),\r\n map((information) => information.page),\r\n map(Number),\r\n distinctUntilChanged(),\r\n skip(1),\r\n);\r\n\r\n/**\r\n * updateUrlPaging: Updates the page on the url.\r\n * @param {Number} pageNumber Number of the selected page.\r\n */\r\nconst updateUrlPaging = (pageNumber) => {\r\n const newPagingSegment = getPaging(pageNumber);\r\n \r\n store.dispatch(routingStateActions.updatePagination(newPagingSegment));\r\n};\r\n\r\n/**\r\n * togglePagingBarVisibility: shows or hides the paging bar in function of the current result type.\r\n * @param {ResultPresentationType} resultsPresentationType represents the current result presentation type.\r\n */\r\nconst togglePagingBarVisibility = (resultsPresentationType) => {\r\n if (resultsPresentationType === ResultPresentationType.InfiniteScrolling.toString()) {\r\n pagingBar.setAttribute(\"hidden\", \"\");\r\n } else {\r\n pagingBar.removeAttribute(\"hidden\");\r\n }\r\n}\r\n\r\npageNumberChange$.subscribe(updateUrlPaging);\r\n\r\n/**\r\n * Subscribing to the store and mapping changes on the ResultType of the search results page.\r\n */\r\nstore$.pipe(\r\n map(selectResultsPresentationType),\r\n distinctUntilChanged(),\r\n).subscribe(togglePagingBarVisibility);","/**\r\n * This module is in charge of updating the queryString value by reacting to user interactions with the search filters.\r\n */\r\nimport { store$, store } from '@redux/store';\r\nimport { map, distinctUntilChanged, filter, skip } from 'rxjs/operators';\r\nimport { routingStateActions } from 'features/routing';\r\nimport { ResultType } from 'features/searchResultsFacets';\r\nimport LoadingStatus from 'enums/loadingStatus';\r\nimport { selectCountsAndQueryString } from '../redux/selectors';\r\nimport { onQueryStringChanged$ } from '../redux/observables';\r\n\r\n/**\r\n * updateQueryString: dispatches an action to the routing state in order to store a new query string.\r\n */\r\nconst onUpdateQueryString = (queryString) => {\r\n setTimeout(() => {\r\n store.dispatch(routingStateActions.updateQueryString(queryString));\r\n }, 0)\r\n}\r\n\r\n/**\r\n * This observable will stream any time there are new results in the Search Results Page.\r\n */\r\nconst onNewResults$ = store$.pipe(\r\n map(selectCountsAndQueryString),\r\n filter(({ resultCountsStatus }) => \r\n resultCountsStatus.name === LoadingStatus.Succeeded.toString()),\r\n distinctUntilChanged(),\r\n map(({ queryString, resultType, listingCounts, minimumRequiredFiltersQueryString }) => {\r\n if (resultType === ResultType.Builders.toString()) {\r\n return minimumRequiredFiltersQueryString;\r\n }\r\n\r\n if (listingCounts === 0) {\r\n return minimumRequiredFiltersQueryString;\r\n }\r\n\r\n return queryString;\r\n }),\r\n);\r\n\r\nonNewResults$.subscribe(onUpdateQueryString);\r\n\r\nonQueryStringChanged$.pipe(\r\n skip(1),\r\n).subscribe(onUpdateQueryString);","import { store$, store } from '@redux/store';\r\nimport { map, filter, distinctUntilChanged, skip } from 'rxjs';\r\nimport { routingStateActions } from 'features/routing';\r\nimport {\r\n ResultType,\r\n PlanStatus,\r\n SpecStatus,\r\n selectSubdirectory,\r\n UrlSubdirectoryTypes,\r\n hasModelHome,\r\n} from 'features/searchResultsFacets';\r\n\r\nconst hasValue = (value) => !!value;\r\nconst onResultTypeChange$ = store$.pipe(map(selectSubdirectory), filter(hasValue), distinctUntilChanged(), skip(1));\r\n\r\n// Get the page from the current state\r\nconst getPageFromCurrentState = (selector) => {\r\n const { condosAndTownHomes, singleFamily, resultType, homeStatus, custom, buildOnYourLot, manufactured } = selector;\r\n\r\n // the default is to use the resultType\r\n let subdirectory;\r\n\r\n switch (true) {\r\n case condosAndTownHomes && resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.CondosAndTownHomes.toString();\r\n break;\r\n case condosAndTownHomes && resultType === ResultType.Communities.toString():\r\n subdirectory = UrlSubdirectoryTypes.CondoDevelopment.toString();\r\n break;\r\n case singleFamily && resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.SingleFamilyHomes.toString();\r\n break;\r\n case singleFamily && resultType === ResultType.Communities.toString():\r\n subdirectory = UrlSubdirectoryTypes.SingleFamilyCommunities.toString();\r\n break;\r\n case custom && resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.CustomHomes.toString();\r\n break;\r\n case buildOnYourLot && resultType === ResultType.Locations.toString():\r\n subdirectory = UrlSubdirectoryTypes.OnYourLot.toString();\r\n break;\r\n case manufactured && resultType === ResultType.Locations.toString():\r\n subdirectory = UrlSubdirectoryTypes.ManufacturedLocations.toString();\r\n break;\r\n case manufactured && resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.ManufacturedHomes.toString();\r\n break;\r\n case (homeStatus === PlanStatus.ReadyToBuild.toString() || homeStatus === SpecStatus.ReadyToBuild.toString()) &&\r\n resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.FloorPlans.toString();\r\n break;\r\n case hasModelHome(homeStatus) && resultType === ResultType.Homes.toString():\r\n subdirectory = UrlSubdirectoryTypes.ModelHomes.toString();\r\n break;\r\n default:\r\n subdirectory = resultType;\r\n }\r\n\r\n return subdirectory;\r\n};\r\n\r\nconst updateUrlOnResultsTypeChanged = (result) => {\r\n const newSubdirectory = getPageFromCurrentState(result);\r\n\r\n setTimeout(() => store.dispatch(routingStateActions.updateSubdirectory(newSubdirectory)));\r\n};\r\n\r\nonResultTypeChange$.subscribe(updateUrlOnResultsTypeChanged);\r\n","import { Subject, fromEvent, map, filter, withLatestFrom } from \"rxjs\";\r\nimport { searchParametersActions } from 'features/searchResultsFacets';\r\nimport { store, store$ } from '@redux/store';\r\n\r\n/**\r\n * The function `mapPageElement` returns the closest ancestor element with a `data-page` attribute, and\r\n * prevents the default behavior of the event.\r\n * @param event - The event parameter is an object that represents the event that occurred, such as a\r\n * click or keypress event. It contains information about the event, including the target element that\r\n * triggered the event.\r\n * @returns the page element that is closest to the target element with the attribute \"data-page\".\r\n */\r\nconst mapPageElement = (event)=> {\r\n const pageElement = event.target.closest('[data-page]');\r\n if (pageElement) {\r\n event.preventDefault()\r\n }\r\n return pageElement;\r\n};\r\n\r\n/**\r\n * This class is in charge ONLY of the logic to change the page number at the search parameters.\r\n */\r\nclass Pager{\r\n constructor() {\r\n const container = document.querySelector('[data-pagination]');\r\n const previousButton = container.querySelector('[data-previous]');\r\n const nextButton = container.querySelector('[data-next]');\r\n this.optionListElement = container.querySelector('[data-option-list]');\r\n \r\n const getPageFromState = (state) => parseInt(state.searchParameters?.results?.paging?.page || 1, 10);\r\n\r\n const previousButtonClick$ = fromEvent(previousButton, 'click').pipe(\r\n withLatestFrom(store$),\r\n map((dataArray) => getPageFromState(dataArray[1])),\r\n );\r\n const nextButtonClick$ = fromEvent(nextButton, 'click').pipe(\r\n withLatestFrom(store$),\r\n map((dataArray) => getPageFromState(dataArray[1])),\r\n );\r\n const optionClick$ = fromEvent(this.optionListElement, 'click').pipe(\r\n map(mapPageElement),\r\n filter(Boolean)\r\n );\r\n\r\n optionClick$.subscribe(this.optionClickHandler.bind(this));\r\n previousButtonClick$.subscribe(Pager.previousButtonClickHandler);\r\n nextButtonClick$.subscribe((currentPage) => Pager.nextButtonClickHandler(currentPage, \r\n Number(this.optionListElement.dataset.pageCount)));\r\n \r\n this.pageChange$ = new Subject().pipe(\r\n withLatestFrom(store$),\r\n map((valuesArray) => {\r\n const pagination = {\r\n pageSelected: valuesArray[0],\r\n lastPage: valuesArray[1].searchParameters?.results?.paging?.page || 1\r\n }\r\n\r\n return pagination;\r\n }),\r\n filter(({ pageSelected, lastPage}) => pageSelected !== lastPage),\r\n map(({pageSelected}) => pageSelected)\r\n );\r\n\r\n this.pageChange$.subscribe((newPage) => store.dispatch(searchParametersActions.fetchPageNumber(newPage)));\r\n }\r\n\r\n /**\r\n * optionClickHandler: Handles when an option of the pagination is clicked.\r\n * @param {HTMLElement} optionElement Option element clicked.\r\n */\r\n optionClickHandler(optionElement) { \r\n const newPage = parseInt(optionElement.dataset.page, 10);\r\n this.pageChange$.next(newPage);\r\n }\r\n\r\n /**\r\n * previousButtonClickHandler: Handles when the previous button is clicked.\r\n * @param {Number} currentPage Current page on the state.\r\n */\r\n static previousButtonClickHandler(currentPage) {\r\n const newPage = currentPage - 1;\r\n if (newPage < 1) {\r\n return;\r\n }\r\n\r\n store.dispatch(searchParametersActions.fetchPagingControlsPrev(newPage));\r\n }\r\n\r\n /**\r\n * nextButtonClickHandler: Handles when the next button is clicked.\r\n * @param {Number} currentPage Current page on the state.\r\n */\r\n static nextButtonClickHandler(currentPage, optionCount) {\r\n const newPage = currentPage + 1;\r\n \r\n if (newPage > optionCount) {\r\n return;\r\n }\r\n\r\n store.dispatch(searchParametersActions.fetchPagingControlsNext(newPage));\r\n }\r\n}\r\n\r\nexport default Pager;\r\n","import { buildNewUrl, getPaging } from 'features/routing';\r\n\r\n/* The `PaginationNumberLink` class represents a link for a specific page number in a pagination component. */\r\nclass PaginationNumberLink {\r\n /**\r\n * Sets the value of the pageNumber property.\r\n * @param pageNumber - The pageNumber parameter is the number of the page that you want to set.\r\n */\r\n setPageNumber(pageNumber) {\r\n this.pageNumber = pageNumber;\r\n }\r\n\r\n /**\r\n * Sets the URL reference by combining the URL components and the paging segment.\r\n * @param urlComponents - urlComponents is an object that contains various components of a URL, such\r\n * as the protocol, domain, path, query parameters, etc.\r\n */\r\n setUrl(urlComponents) {\r\n const pagingSegment = getPaging(this.pageNumber);\r\n const urlSegments = { ...urlComponents, urlPaging: pagingSegment };\r\n this.urlReference = buildNewUrl(urlSegments);\r\n }\r\n\r\n /**\r\n * Returns an HTML string representing a list item with a link, including page number and URL reference.\r\n *\r\n * @returns an HTML string that represents a list item with a link. The values are being dynamically\r\n * generated based on the values of the properties `this.pageNumber` and `this.urlReference`.\r\n */\r\n getHtml() {\r\n return `
  • \r\n ${this.pageNumber}\r\n
  • `;\r\n }\r\n}\r\n\r\nexport default PaginationNumberLink;\r\n","import { store, store$ } from '@redux/store';\r\nimport { selectPaginationContext } from 'features/searchResultsFacets';\r\nimport { distinctUntilChanged, filter, map } from 'rxjs';\r\nimport { routingSelectors } from 'features/routing';\r\nimport Pager from './pager';\r\nimport PaginationNumberLink from './paginationNumberLink';\r\n\r\nconst { urlComponentsSelector } = routingSelectors;\r\n\r\n/**\r\n * This class is ONLY in charge of updates the pagination UI according to the current search parameters.\r\n */\r\nclass PaginationBar {\r\n constructor() {\r\n const container = document.querySelector('[data-pagination]');\r\n const initialData = container.querySelector('[data-compontent=\"pagination-data\"]');\r\n this.container = container;\r\n this.previousButton = container.querySelector('[data-previous]');\r\n this.nextButton = container.querySelector('[data-next]');\r\n this.totalResults = JSON.parse(initialData.innerHTML)?.TotalResults ?? 1;\r\n this.optionList = container.querySelector('[data-option-list]');\r\n this.pageCount = parseInt(this.optionList.dataset.pageCount, 10);\r\n this.maximumPagesToShow = 7;\r\n\r\n store$\r\n .pipe(\r\n map(selectPaginationContext),\r\n filter((parameters) => parameters.listingCount !== undefined),\r\n distinctUntilChanged((previous, current) => JSON.stringify(previous) === JSON.stringify(current))\r\n )\r\n .subscribe(this.changePagination.bind(this));\r\n\r\n (() => new Pager())();\r\n }\r\n\r\n /**\r\n * changePagination: Re build the pagination with the new data.\r\n * @param {Object} configuration Object with the data to update the component.\r\n */\r\n changePagination(parameters) {\r\n const { listingCount, pageSize, pageNumber } = parameters;\r\n this.totalResults = listingCount ?? this.totalResults;\r\n this.pageSize = pageSize ?? this.pageSize;\r\n this.activePageNumber = pageNumber ?? 1;\r\n this.updatePageCount();\r\n this.updateUrlComponents();\r\n this.getPagesToShow();\r\n this.build();\r\n this.updatePaginationBarVisibility();\r\n this.updateClasses();\r\n }\r\n\r\n /**\r\n * The function updates the URL components based on the current state of the store.\r\n */\r\n updateUrlComponents() {\r\n const state = store.getState();\r\n const urlComponents = urlComponentsSelector(state);\r\n\r\n this.urlComponents = urlComponents;\r\n }\r\n\r\n /**\r\n * updateCount: Updates the count with the actual data.\r\n */\r\n updatePageCount() {\r\n this.pageCount = Math.ceil(this.totalResults / this.pageSize);\r\n }\r\n\r\n /**\r\n * updateClasses: Updates the classes required for all the page HTML elements.\r\n */\r\n updateClasses() {\r\n const allOptions = this.optionList.querySelectorAll('[data-page]');\r\n allOptions.forEach((optionElement) => optionElement.classList.remove('active'));\r\n const activeOption = this.optionList.querySelector(`[data-page=\"${this.activePageNumber}\"]`);\r\n if (activeOption) {\r\n activeOption.classList.add('nhs-c-pagination__number--active');\r\n activeOption.dataset.qa = \"pagination_number_active\";\r\n }\r\n }\r\n\r\n /**\r\n * Determines which pages to display based on the active page number and the total number of pages.\r\n * Sets the value of `this.pagesToShow` to the `pages` array.\r\n */\r\n getPagesToShow() {\r\n let pages = [];\r\n\r\n // When we can show all the pages without three dots.\r\n if (this.maximumPagesToShow >= this.pageCount) {\r\n // Gets array of number until the page count.\r\n pages = [...Array(this.pageCount).keys()].map((index) => index + 1);\r\n this.pagesToShow = pages;\r\n return;\r\n }\r\n\r\n const firstPage = 1;\r\n const lastPage = this.pageCount;\r\n // We will need always the first page.\r\n pages.push(firstPage);\r\n\r\n const pageNumberToRight = lastPage - this.activePageNumber;\r\n const pageNumberToLeft = this.activePageNumber - firstPage;\r\n\r\n // This scenario is when the first page and the last have a distant of more than 3 pages with the active page.\r\n if (pageNumberToLeft > 3 && pageNumberToRight > 3) {\r\n pages.push(this.activePageNumber - 1);\r\n pages.push(this.activePageNumber);\r\n pages.push(this.activePageNumber + 1);\r\n }\r\n\r\n // This scenario is when the first page does not have a distant of 3 or more pages with the active page.\r\n if (pageNumberToLeft <= 3) {\r\n pages.push(firstPage + 1);\r\n pages.push(firstPage + 2);\r\n pages.push(firstPage + 3);\r\n pages.push(firstPage + 4);\r\n }\r\n\r\n // This scenario is when the last page does not have a distant of 3 or more pages with the active page.\r\n if (pageNumberToRight <= 3) {\r\n pages.push(lastPage - 4);\r\n pages.push(lastPage - 3);\r\n pages.push(lastPage - 2);\r\n pages.push(lastPage - 1);\r\n }\r\n\r\n // We will need always the last page.\r\n pages.push(lastPage);\r\n\r\n this.pagesToShow = pages;\r\n }\r\n\r\n /**\r\n * Updates the visibility of a pagination bar based on the number of pages to show.\r\n */\r\n updatePaginationBarVisibility() {\r\n if (this.pagesToShow.length > 0) {\r\n this.container.style.display = 'flex';\r\n } else {\r\n this.container.style.display = 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Updates the pagination UI based on the current active page number and the total number of pages.\r\n */\r\n build() {\r\n this.optionList.innerHTML = '';\r\n this.optionList.dataset.pageCount = this.pageCount;\r\n this.previousButton.disabled = this.activePageNumber === 1;\r\n this.nextButton.disabled = this.activePageNumber === this.pageCount;\r\n\r\n this.pagesToShow.forEach((pageNumber, pageIndex) => {\r\n const previousPageNumber = this.pagesToShow[pageIndex - 1] || 0;\r\n // We know when to add the three dots because there is a jump on the counting.\r\n if (previousPageNumber + 1 !== pageNumber) {\r\n const threeDotsElement = `
  • \r\n ...\r\n
  • `;\r\n this.optionList.innerHTML += threeDotsElement;\r\n }\r\n\r\n const newPaginationNumberLink = new PaginationNumberLink();\r\n newPaginationNumberLink.setPageNumber(pageNumber);\r\n newPaginationNumberLink.setUrl(this.urlComponents);\r\n this.optionList.innerHTML += newPaginationNumberLink.getHtml();\r\n });\r\n }\r\n}\r\n\r\nexport default PaginationBar;\r\n","import { store } from '@redux/store';\r\nimport { facetsReducers, searchParametersReducers } from 'features/searchResultsFacets';\r\nimport { createMap } from 'features/searchResultsMap';\r\nimport PaginationBar from './components/pagination/paginationBar';\r\n\r\nrequire('features/speedcurve');\r\nrequire('./components/eventTracking/speedcurveEventsHandler');\r\n\r\nstore.injectReducer('searchParameters', searchParametersReducers);\r\nstore.injectReducer('facetsState', facetsReducers);\r\n\r\ncreateMap();\r\n\r\nrequire('./analytics/uiUpdates');\r\nrequire('./components/images/handlerErrorImages');\r\nrequire('./components/typeahead');\r\nrequire('features/leadGenerators');\r\nrequire('features/searchResultsExtendedCard');\r\nrequire('features/routing');\r\nrequire('./components/facets');\r\nrequire('./components/viewToggler');\r\nrequire('./components/standardCard');\r\nrequire('features/locationContent');\r\nrequire('./components/formCertifier');\r\nrequire('./routing');\r\nrequire('./services/contentTemplateTypeHandler');\r\nrequire('./components/resultTypeTabs');\r\nrequire('./components/skeletonHandler');\r\nrequire('./components/popularSearchesPillsHandler');\r\nrequire('./components/builderDirectory/builderBrandCard');\r\nrequire('./analytics/analyticsDimensions');\r\nrequire('./components/containerUiUpdater');\r\nrequire('./analytics/facets');\r\nrequire('./analytics/favorites');\r\nrequire('./analytics/pagination');\r\nrequire('./analytics/phoneEventListener');\r\nrequire('./analytics/schedulerEventListener');\r\nrequire('./analytics/thankYouEventListener');\r\nrequire('./components/header/hamburgerMenu');\r\nrequire('features/segment');\r\nrequire('./components/eventTracking/segmentEventsHandler');\r\nrequire('features/googleAnalytics4');\r\nrequire('./components/eventTracking/googleAnalytics4EventsHandler');\r\nrequire('features/trackingProperties');\r\nrequire('./components/backToTopHandler'); // TODO : Remove this - NHSRB-324\r\nrequire('./components/backForwardHandler');\r\nrequire('./components/geoProximityHandler');\r\nrequire('./redux/listeners');\r\nrequire('./components/noResults/noResultsClearButton');\r\nrequire('./components/noResults/hintsSection');\r\nrequire('features/googleAds');\r\nrequire('./components/eventTracking/googleAdsEventsHandler');\r\nrequire('./components/resultsLazyLoader');\r\nrequire('./components/priceHighLink');\r\nrequire('./components/listViewHandler');\r\nrequire('./components/nativeAdsLoader');\r\nrequire('./components/filterPanel');\r\n\r\n(() => new PaginationBar())();\r\n","import { store$, store } from '@redux/store';\r\nimport {\r\n hasAvailableNow,\r\n hasReadyToBuild,\r\n searchParametersActions,\r\n searchParametersSelectors,\r\n} from 'features/searchResultsFacets';\r\nimport { map, distinctUntilChanged, skip } from 'rxjs';\r\n\r\nconst { selectContentTemplateTypeModifiers } = searchParametersSelectors;\r\n\r\nconst contentFacets = [\r\n 'adult',\r\n 'builderbrand',\r\n 'gatedcommunity',\r\n 'golfcourse',\r\n 'green',\r\n 'hotdeals',\r\n 'luxury',\r\n 'condosandtownhomes',\r\n 'natureareas',\r\n 'parks',\r\n 'pool',\r\n 'schooldistrict',\r\n 'singlefamily',\r\n 'sportsfacilities',\r\n 'views',\r\n 'waterfront',\r\n 'communityname',\r\n 'price',\r\n 'comingsoon',\r\n 'moveindate',\r\n 'customhomes',\r\n 'manufactured',\r\n 'modelhomes',\r\n];\r\n\r\n/**\r\n * The function returns a content template type based on the home status provided.\r\n * @param homeStatus - a string representing the status of a home plan, either \"AvailableNow\" or\r\n * \"ReadyToBuild\".\r\n * @returns The function `getContentTemplateTypeForMoveInDateFilters` returns a string value that\r\n * represents the content template type based on the `homeStatus` parameter. If `homeStatus` is equal\r\n * to `PlanStatus.AvailableNow.toString()`, it returns `'QuickMoveIn'`. If `homeStatus` is equal to\r\n * `PlanStatus.ReadyToBuild.toString()`, it returns `'ReadyToBuild\r\n */\r\nconst getContentTemplateTypeForMoveInDateFilters = (homeStatus) => {\r\n if (hasAvailableNow(homeStatus)) {\r\n return 'QuickMoveIn';\r\n }\r\n\r\n if (hasReadyToBuild(homeStatus)) {\r\n return 'ReadyToBuild';\r\n }\r\n\r\n return '';\r\n};\r\n\r\n/**\r\n * The function returns a content template type based on whether we have a brand id other than null.\r\n * @param brandId: A string representing the brand ID.\r\n * @returns The function `getContentTemplateTypeForBrandFilter` returns a string value that\r\n * represents the content template type.\r\n */\r\nconst getContentTemplateTypeForBrandFilter = (brandId) => {\r\n if (brandId !== null) {\r\n return 'builderbrand';\r\n }\r\n\r\n return '';\r\n};\r\n\r\n/**\r\n * getContentTemplateType: Gets the Content Template Type that is going to be used.\r\n * @param {Object} data Data related required to define the Content Template Type.\r\n * @returns A string with the Content Template Type.\r\n */\r\nfunction getContentTemplateType(data) {\r\n const { productType, appliedFacetList, homeStatus, brandId } = data;\r\n\r\n // We have to check first about the product type because its priority is higher than the facets content.\r\n if (productType === 'AllProducts') {\r\n return 'BuilderDirectory';\r\n }\r\n\r\n // Here we are getting the facets that have a content template.\r\n const appliedContentFacetList = appliedFacetList.filter((facet) => contentFacets.includes(facet.toLowerCase()));\r\n\r\n const lastItem = appliedContentFacetList[appliedContentFacetList.length - 1];\r\n\r\n if (lastItem === 'moveindate') {\r\n const moveInDateContentTemplate = getContentTemplateTypeForMoveInDateFilters(homeStatus);\r\n return moveInDateContentTemplate;\r\n }\r\n \r\n if (lastItem === 'modelhomes') {\r\n return 'ModelHomes';\r\n }\r\n\r\n if (lastItem === 'customhomes') {\r\n return 'CustomHomes'\r\n }\r\n\r\n if (lastItem === 'builderbrand') {\r\n const builderContentTemplate = getContentTemplateTypeForBrandFilter(brandId);\r\n return builderContentTemplate;\r\n }\r\n\r\n return appliedContentFacetList.pop() || '';\r\n}\r\n\r\nconst contentTemplateTypeModified$ = store$.pipe(\r\n map(selectContentTemplateTypeModifiers),\r\n distinctUntilChanged(),\r\n map(getContentTemplateType),\r\n distinctUntilChanged(),\r\n skip(1)\r\n);\r\n\r\n/**\r\n * updateContentTemplateType: Updates the content template type according to the last facet with content.\r\n * @param {string} contentTemplateType Content template type to show.\r\n */\r\nfunction updateContentTemplateType(contentTemplateType) {\r\n store.dispatch(searchParametersActions.fetchContentTemplateType(contentTemplateType));\r\n}\r\n\r\ncontentTemplateTypeModified$.subscribe(updateContentTemplateType);\r\n","import { buildNewUrl } from \"features/routing\";\r\n\r\nconst shouldHavePreviousPage = (currentPage) => currentPage > 1; \r\nconst shouldHaveNextPage = (currentPage, lastPage) => currentPage < lastPage; \r\n\r\n/**\r\n * getNextPageUrl: Gets the url for the Next Page Link Element.\r\n * @param {Object} paging Object with the information related to the pages. It includes the current and last page.\r\n * @param {Object} nextPageUrlConfig Object with the information related to the section for the url.\r\n * @returns An string with the url that is going to be used for the Next Page Link Element.\r\n */\r\nexport const getNextPageUrl = (paging, nextPageUrlConfig) => {\r\n const { currentPage, lastPage } = paging;\r\n const hasNextPage = shouldHaveNextPage(currentPage, lastPage);\r\n\r\n return hasNextPage ? buildNewUrl(nextPageUrlConfig) : '';\r\n}\r\n\r\n/**\r\n * getPreviousPageUrl: Gets the url for the Previous Page Link Element.\r\n * @param {Number} currentPage Number of the current page of the search.\r\n * @param {Object} previousPageUrlConfig Object with the information related to the sections for the url.\r\n * @returns An string with the url that is going to be used for the Previous Page Link Element.\r\n */\r\nexport const getPreviousPageUrl = (currentPage, previousPageUrlConfig) => {\r\n const hasPreviousPage = shouldHavePreviousPage(currentPage);\r\n\r\n return hasPreviousPage ? buildNewUrl(previousPageUrlConfig) : '';\r\n}\r\n\r\n/**\r\n * Takes in search location parameters and returns a string of map coordinates in a specific\r\n * format as a querystring value.\r\n * @param locationParameters - `locationParameters` is an object that contains four properties:\r\n * `minimumLatitude`, `maximumLatitude`, `minimumLongitude`, and `maximumLongitude`. These properties\r\n * represent the minimum and maximum latitude and longitude values for a map view. The function\r\n * `getMapCoordinatesQueryString` takes in this object as a parameter\r\n * @returns The function `getMapCoordinatesQueryString` is returning a string that contains the\r\n * coordinates of a map. The string is constructed using the values of the `locationParameters` object,\r\n * which should have properties `minimumLatitude`, `maximumLatitude`, `minimumLongitude`, and\r\n * `maximumLongitude`. The string is formatted as\r\n * `coordinates=29.513244482891352,31.014810450257787,-98.90597549023437,-96.57962050976562`.\r\n */\r\nexport const getMapCoordinatesQueryString = (locationParameters) => {\r\n\r\n const mapCoordinatesQueryString =\r\n `coordinates=${locationParameters?.minimumLatitude},${locationParameters?.minimumLongitude},` +\r\n `${locationParameters?.maximumLatitude},${locationParameters?.maximumLongitude}`;\r\n\r\n return mapCoordinatesQueryString;\r\n}","import { fromFetch } from 'rxjs/fetch';\r\nimport UrlExtensions from 'utils/urlExtension';\r\n\r\n/**\r\n * @private\r\n *\r\n * The function returns a the User profile URL.\r\n *\r\n * @returns user profile URL string with parameters for the user's profile page, including IP address.\r\n */\r\nfunction getUserProfileUrl() {\r\n const location = window.location;\r\n const path = '/getUserProfile';\r\n const ip = UrlExtensions.getParameterValue(location, 'ip');\r\n\r\n const url = UrlExtensions.setParameters(path, {\r\n ip,\r\n });\r\n return url;\r\n}\r\n\r\nexport default fromFetch(getUserProfileUrl(),\r\n {\r\n 'credentials': 'include',\r\n headers: {\r\n 'Accept': 'application/json',\r\n }\r\n });\r\n","import { fromFetch } from 'rxjs/fetch';\r\nimport { userProfileGetFavorites } from 'constants/routes';\r\n\r\nexport default fromFetch(userProfileGetFavorites, {\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // disabling cache to always get the latest favorites\r\n 'Cache-Control': 'no-cache',\r\n 'Accept': 'application/json',\r\n },\r\n});\r\n","import { switchMap, map } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { userSaveFavorite } from 'constants/routes';\r\nimport { camelCaseObjectKeys } from 'utils/camelCase';\r\n\r\nfunction saveUserFavorite(payload) {\r\n const url = `${userSaveFavorite}`;\r\n\r\n return fromFetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify(payload),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n }).pipe(\r\n switchMap((response) => response.json()),\r\n map((response) => camelCaseObjectKeys(response))\r\n );\r\n}\r\n\r\nexport default saveUserFavorite;\r\n","import { switchMap } from 'rxjs';\r\nimport { fromFetch } from 'rxjs/fetch';\r\nimport { userDeleteFavorite } from 'constants/routes';\r\n\r\nfunction deleteUserFavorite(id) {\r\n const url = `${userDeleteFavorite}?id=${id}`;\r\n\r\n return fromFetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n },\r\n }).pipe(switchMap((response) => response.json()));\r\n}\r\n\r\nexport default deleteUserFavorite;\r\n","import FavoriteType from \"../enums/favoriteType\";\r\nimport SpecProductType from \"../models/specProductType\";\r\nimport PlanProductType from \"../models/planProductType\";\r\nimport CommunityProductType from \"../models/communityProductType\";\r\n\r\nconst housingProductConstructor = new Map();\r\n\r\nhousingProductConstructor.set(FavoriteType.Spec.toString(), SpecProductType);\r\nhousingProductConstructor.set(FavoriteType.Plan.toString(), PlanProductType);\r\nhousingProductConstructor.set(FavoriteType.Community.toString(), CommunityProductType)\r\n\r\n/**\r\n * Returns the class constructor with the listing information according to the type.\r\n *\r\n * @param type - The type of listing (Spec, plan, community).\r\n * @param listingInformation - The listing (Spec, plan, community) information.\r\n */\r\n\r\nexport default (type, listingInformation) => {\r\n const generator = housingProductConstructor.get(type);\r\n \r\n if (!generator) {\r\n return null;\r\n }\r\n \r\n return new generator.prototype.constructor(listingInformation);\r\n };\r\n ","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\n\r\nconst tdvEvents = 'TDV Events';\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class SpecProductType {\r\n constructor(listing) {\r\n this.id = listing.id;\r\n this.brandName = listing.brandName;\r\n this.communityName = listing.communityName;\r\n this.communityId = listing.communityId;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for favorites.\r\n */\r\n getFavoriteGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.SpecId().getName()] :\r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.communityName,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] :\r\n this.communityId,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] :\r\n !this.isBasic,\r\n };\r\n return new GoogleAnalyticsEvent(tdvEvents, 'SRP Listing Card', 'Listing Saved', customDimensions);\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\n\r\nconst tdvEvents = 'TDV Events';\r\n\r\n/* Creates a new instance for housing product type. */\r\nexport default class PlanProductType {\r\n constructor(listing) {\r\n this.brandName = listing.brandName;\r\n this.communityName = listing.communityName;\r\n this.id = listing.id;\r\n this.communityId = listing.communityId;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action,\r\n * event label and custom dimensions set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class for favorites.\r\n */\r\n getFavoriteGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.communityName,\r\n [GoogleAnalyticsCustomDimensions.PlanId().getName()] :\r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] :\r\n this.communityId,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n return new GoogleAnalyticsEvent(tdvEvents, 'SRP Listing Card', 'Listing Saved', customDimensions);\r\n }\r\n}\r\n","import GoogleAnalyticsEvent from 'dataTransferObjects/googleAnalyticsEvent';\r\nimport GoogleAnalyticsCustomDimensions from 'constants/googleAnalyticsCustomDimension';\r\n\r\nconst tdvEvents = 'TDV Events';\r\n\r\n/* Creates a new instance of a community listing. */\r\nexport default class CommunityProductType {\r\n constructor(listing) {\r\n this.brandName = listing.brandName;\r\n this.name = listing.name;\r\n this.id = listing.id;\r\n this.isBasic = listing.isBasic === \"true\";\r\n }\r\n\r\n /**\r\n * This function returns a new GoogleAnalyticsEvent object with the event category, event action, and\r\n * event label set.\r\n * @returns A new instance of the GoogleAnalyticsEvent class.\r\n */\r\n getFavoriteGoogleAnalyticsEvent() {\r\n const customDimensions = { \r\n [GoogleAnalyticsCustomDimensions.BrandName().getName()] :\r\n this.brandName,\r\n [GoogleAnalyticsCustomDimensions.CommunityName().getName()] :\r\n this.name,\r\n [GoogleAnalyticsCustomDimensions.CommunityId().getName()] :\r\n this.id,\r\n [GoogleAnalyticsCustomDimensions.IsPaid().getName()] : \r\n !this.isBasic,\r\n };\r\n return new GoogleAnalyticsEvent(tdvEvents, 'SRP Listing Card', 'Listing Saved', customDimensions);\r\n }\r\n}\r\n","import { catchError, from, of, mergeMap, switchMap, map, filter } from 'rxjs';\r\nimport { ofType } from 'redux-observable';\r\nimport getUserProfile$ from '../apis/getUserProfile';\r\nimport getUserFavorites$ from '../apis/getUserFavorites';\r\nimport { userProfileSlice } from './slices';\r\nimport saveUserFavorite from '../apis/saveFavorite';\r\nimport deleteUserFavorite from '../apis/deleteFavorite';\r\nimport getFavoriteFromState from '../services/getFavoriteFromState';\r\nimport housingProductConstructor from '../services/getHousingProductType';\r\n\r\nconst actions = userProfileSlice.actions;\r\n\r\n// this epic requests the profile data for logged in users.\r\nexport const fetchUserProfileEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.fetch.type),\r\n switchMap(() =>\r\n getUserProfile$.pipe(\r\n switchMap((response) => from(response.json()).pipe(mergeMap((data) =>\r\n of(actions.apply(data))))),\r\n catchError((err) => of(actions.handleError(err)))\r\n )\r\n )\r\n );\r\n\r\n// this epic requests the profile data for logged in users.\r\nexport const fetchUserFavoritesEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.apply.type),\r\n filter((action) => action.payload && action.payload.IsLogin === true),\r\n switchMap(() =>\r\n getUserFavorites$.pipe(\r\n switchMap((response) => from(response.json()).pipe(mergeMap((data) =>\r\n of(actions.applyFavorites(data))))),\r\n catchError((err) => of(actions.handleError(err)))\r\n )\r\n )\r\n );\r\n\r\n// this epic is triggered when the user profile is loaded\r\n// it loads the user's favorites into the favorites slice.\r\nexport const getUserFavoritesEpic = (action$) =>\r\n action$.pipe(\r\n ofType(actions.apply.type),\r\n map((action) => actions.loadFavorites(action.payload))\r\n );\r\n\r\n// this epic is triggered when the user clicks on the favorite icon on a card \r\n// that is not already a favorite. \r\nexport const saveFavoriteEpic = (action$, state$) => \r\naction$.pipe( \r\n ofType(actions.saveFavorite.type),\r\n filter(() => state$.value?.userProfile?.isLogin),\r\n mergeMap((action) => { \r\n const { listingInformation, type, url, userId } = action.payload;\r\n const housingProductType = housingProductConstructor(type, listingInformation);\r\n const saveInformation = {\r\n id: listingInformation.id,\r\n type,\r\n url,\r\n userId\r\n };\r\n return saveUserFavorite(saveInformation).pipe(\r\n switchMap((data) => of(actions.saveFavoriteFulfilled({data, housingProductType})))\r\n );\r\n}));\r\n\r\n// this epic is triggered when the user clicks on the favorite icon on a card\r\n// that is already a favorite.\r\nexport const deleteFavoriteEpic = (action$, state$) =>\r\n action$.pipe(\r\n ofType(actions.deleteFavorite.type),\r\n switchMap((action) => {\r\n const payload = action.payload;\r\n \r\n // get the favorite from the state that matches the action.payload.id\r\n const favorite = getFavoriteFromState(state$.value, Number(payload.listingInformation.id));\r\n\r\n return deleteUserFavorite(favorite.id).pipe(\r\n switchMap(() => of(actions.deleteFavoriteFullfilled(favorite)))\r\n );\r\n }));","import { BehaviorSubject, mergeMap } from 'rxjs';\r\nimport { \r\n fetchUserProfileEpic,\r\n saveFavoriteEpic, \r\n deleteFavoriteEpic,\r\n fetchUserFavoritesEpic,\r\n} from 'features/userProfile';\r\nimport { combineEpics } from 'redux-observable';\r\n\r\nconst combinedUserProfileEpic = combineEpics(\r\n fetchUserProfileEpic,\r\n saveFavoriteEpic,\r\n deleteFavoriteEpic,\r\n fetchUserFavoritesEpic,\r\n );\r\n// Exports the Observable of 'epic' to allow other modules to dynamically register their epic.\r\nexport const epic$ = new BehaviorSubject(combinedUserProfileEpic);\r\n\r\nexport const rootEpic = (action$, state$) => epic$.pipe(mergeMap((epic) => epic(action$, state$)));","\r\n\r\n// this function is used to get the favorite from the state that matches the id of the action.payload.id\r\nexport default function getFavoriteFromState(state, id) {\r\n return state.userProfile?.favorites?.find((fav) => fav.listingId === id);\r\n }","import { distinctUntilChanged, from } from 'rxjs';\r\nimport { createEpicMiddleware } from 'redux-observable';\r\nimport { combineReducers, configureStore } from '@reduxjs/toolkit';\r\nimport dynamicMiddlewares from 'redux-dynamic-middlewares'\r\nimport { rootEpic } from './rootEpics';\r\n\r\n// Register global reducers if needed.\r\nconst staticReducers = {};\r\n\r\n// Function need to allow other modules to dynamically register their reducers.\r\nfunction createReducer(asyncReducers) {\r\n return combineReducers({\r\n ...staticReducers,\r\n ...asyncReducers,\r\n });\r\n}\r\n\r\n// Epic Middleware allow RxJS to work with Redux via Redux-Observable.\r\nconst epicMiddleware = createEpicMiddleware();\r\n\r\n// Creates, configure, and export the global store.\r\nexport const store = configureStore({\r\n reducer: staticReducers,\r\n middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(epicMiddleware).concat(dynamicMiddlewares),\r\n});\r\n\r\n// Observable store that notifies the latest changes.\r\n\r\nexport const store$ = from(store).pipe(distinctUntilChanged());\r\n// Add a dictionary to keep track of the registered async reducers.\r\nstore.asyncReducers = {};\r\n\r\n// Create an inject reducer function.\r\n// This function adds the async reducer, and creates a new combined reducer.\r\nstore.injectReducer = (key, asyncReducer) => {\r\n store.asyncReducers[key] = asyncReducer;\r\n store.replaceReducer(createReducer(store.asyncReducers));\r\n};\r\n\r\n// Run the root 'epic'.\r\nepicMiddleware.run(rootEpic);\r\nexport { epic$ } from './rootEpics';\r\n","import { UrlSubdirectoryTypes } from \"features/searchResultsFacets\";\r\n\r\nfunction getTrackerName() {\r\n const nhsTrackingId = 'UA-40843711-4';\r\n const trackers = window.ga.getAll().filter((element) => element.get('trackingId') === nhsTrackingId);\r\n const tracker = trackers[0].get('name');\r\n return tracker;\r\n}\r\n\r\nfunction getTrackerClientId() {\r\n const nhsTrackingId = 'UA-40843711-4';\r\n const trackers = window.ga.getAll().filter((element) => element.get('trackingId') === nhsTrackingId);\r\n const clientId = trackers[0].get('clientId');\r\n return clientId\r\n}\r\n\r\n/**\r\n * A function that returns a value the page type to be track in Google Analytics custom dimensions.\r\n * for instance, in Homes searches it will return `Home_Results`, in Single Family cases `Single_Family_Homes`.\r\n */\r\nconst getPageType = (page) => UrlSubdirectoryTypes.fromKey(page)?.pageType || '';\r\n\r\nexport { getTrackerName, getPageType, getTrackerClientId };\r\n","/**\r\n * Class to work as a DTO to hold the information of a event dispatched to Google Analytics 4.\r\n */\r\nclass GoogleAnalytics4Event {\r\n constructor(eventName, params = {}) {\r\n this.eventName = eventName;\r\n this.params = params;\r\n this.event = 'GA4Event';\r\n }\r\n\r\n /**\r\n * The function returns the value of the eventName property.\r\n * @returns The value of the variable `eventName`.\r\n */\r\n getEventName() {\r\n return this.eventName;\r\n }\r\n\r\n /**\r\n * The function returns the value of the \"params\" property.\r\n * @returns The `params` property is being returned.\r\n */\r\n getParams() {\r\n return this.params;\r\n }\r\n}\r\n\r\nexport default GoogleAnalytics4Event;\r\n","/**\r\n * get Central Standard Time (Austin time).\r\n *\r\n */\r\nconst getCentralStandardTime = () => {\r\n // Get current time\r\n const date = new Date();\r\n\r\n // The difference, in minutes, between the date as evaluated in the UTC time zone and\r\n // as evaluated in the local time zone. The actual local time algorithm is implementation-defined,\r\n // and the return value is allowed to be zero in runtimes without appropriate data.\r\n const browsertTimeZone = date.getTimezoneOffset();\r\n\r\n // convert browsertTimeZone to milliseconds\r\n // get UTC time in milliseconds\r\n const utc = date.getTime() + browsertTimeZone * 60000;\r\n\r\n // Get the number of milliseconds of central standard time.\r\n // 3600000 is the conversion of hours to milliseconds\r\n // -5 is the GMT-5 time zone of austin. We just need to multply the value.\r\n // 3600000 * -5 = -18000000 milliseconds\r\n const centralStandardTimeZone = -18000000;\r\n\r\n // Calculate the new date with the central standard timezone.\r\n const now = new Date(utc + centralStandardTimeZone);\r\n\r\n return (\r\n `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}` +\r\n `T${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}.${now.getMilliseconds()}-05:00`\r\n );\r\n};\r\n\r\nexport default getCentralStandardTime;\r\n","import { store } from '@redux/store';\r\nimport getTrackingCommonProperties from 'features/trackingProperties';\r\nimport merge from 'deepmerge';\r\nimport cleanObjectsEmptyProperties from 'utils/cleanObject';\r\nimport GoogleAnalytics4EventType from 'enums/googleAnalytics4EventType';\r\nimport GoogleAnalytics4Event from 'dataTransferObjects/googleAnalytics4Event';\r\nimport getCentralStandardTime from 'modules/getCentralStandardTime';\r\n\r\n/**\r\n * The getCommonProperties function returns an object containing the common properties\r\n * that are used in all Google Analytics 4 events.\r\n * @return An object\r\n */\r\nconst getCommonProperties = () => {\r\n const state = store.getState();\r\n const commonProperties = getTrackingCommonProperties(state);\r\n return commonProperties;\r\n};\r\n\r\n/**\r\n * concatenates a market name and a state abbreviation with a comma in between.\r\n * @param marketName - is a string representing the name of a market.\r\n * @param stateAbbreviation - represents a state. For example, \"CA\" for California or \"NY\" for New York.\r\n * @returns a string that concatenates the marketName and stateAbbreviation\r\n * with a comma and space in between. If `marketName` is falsy, the function returns `null`.\r\n */\r\nconst getMarketName = (marketName, stateAbbreviation) => {\r\n if (marketName) {\r\n return `${marketName}, ${stateAbbreviation}`;\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * It takes in a market ID and market name as parameters and returns a\r\n * string that combines the market name and ID.\r\n * @param marketId - is used to identify a specific market. It could be a unique\r\n * identifier or a code that represents the market.\r\n * @param marketName - is a string that represents the name of a market.\r\n * @param stateAbbreviation - is a string that represents the abbreviation name of the state.\r\n * @returns a string that concatenates the `marketName` and\r\n * `marketId` with a hyphen in between. If both `marketId` and `marketName` are provided, the function\r\n * returns the concatenated string. Otherwise, it returns an empty string.\r\n */\r\nexport const getMarketSession = (marketId, marketName, stateAbbreviation) => {\r\n if (marketId && marketName) {\r\n return `${marketName}, ${stateAbbreviation} - ${marketId}`;\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * The getLocation function returns a string that represents the location, including the city and state\r\n * name if provided.\r\n * @param city - The `city` parameter represents the name of a city.\r\n * @param stateName - The `stateName` parameter represents the name of a state.\r\n * @returns If the `city` parameter is provided, the function will return a string in the format \"city,\r\n * stateName\". If the `city` parameter is not provided, the function will return just the `stateName`.\r\n */\r\nexport const getLocation = (city, stateName) => {\r\n if (city) {\r\n return `${city}, ${stateName}`;\r\n }\r\n return stateName;\r\n};\r\n\r\n/**\r\n * The function filters the Google Analytics 4 common properties, and take only the ones needed for Track events.\r\n * ex. track don't need user information. user information is available in common properties.\r\n * @returns object containing the common properties for a Track event.\r\n */\r\nconst getTrackCommonProperties = () => {\r\n const commonProperties = getCommonProperties();\r\n\r\n const trackCommonProperties = {\r\n brandPartnerName: commonProperties.brandPartnerName,\r\n pageType: commonProperties.pageType,\r\n partnerId: commonProperties.partnerId,\r\n partnerName: commonProperties.partnerName,\r\n userMarketId: commonProperties.userLocationMarketId,\r\n userStatus: commonProperties.isLoggedIn ? 1 : 0,\r\n userZipCode: commonProperties.userLocationZipCode,\r\n user: commonProperties.userId,\r\n brandPartnerNamePartnerName: `${commonProperties.brandPartnerName}-${commonProperties.partnerName}`,\r\n gaUserId: commonProperties.userId,\r\n time: getCentralStandardTime(),\r\n neustarResponse: JSON.stringify({\r\n s: commonProperties.neustarSegment,\r\n z: commonProperties.neustarZip,\r\n a: commonProperties.neustarAge,\r\n g: commonProperties.neustarGender,\r\n }),\r\n referCode: commonProperties.referCode,\r\n market_id: commonProperties.marketId?.toString() || null,\r\n market_name: getMarketName(commonProperties.marketName, commonProperties.stateAbbreviation),\r\n market_session: getMarketSession(\r\n commonProperties.marketId?.toString(),\r\n commonProperties.marketName,\r\n commonProperties.stateAbbreviation\r\n ),\r\n location: getLocation(commonProperties.city, commonProperties.stateName),\r\n current_page_number: commonProperties.pageNumber || null,\r\n search_within_map: commonProperties.isSearchWithinMap || null,\r\n page_number: commonProperties.pageNumber || null,\r\n };\r\n\r\n const cleanedTrackCommonProperties = cleanObjectsEmptyProperties(trackCommonProperties);\r\n\r\n return cleanedTrackCommonProperties;\r\n};\r\n\r\n/**\r\n * The createTrackEvent function is a helper function that creates an event object\r\n * for the Google Analytics 4. The event object contains information about\r\n * the type of event, and any properties associated with it. This function returns\r\n * a redux-beacon middleware compatible action creator that can be dispatched to\r\n * trigger an analytics call to Google Analytics 4's servers.\r\n * @param eventName Identify the event name\r\n * @param customParams Pass in any additional properties that you want to be sent with the event\r\n *\r\n * @return A function that returns a GoogleAnalytics4Event\r\n */\r\nconst createTrackEvent = (eventName, customParams) => {\r\n const commonProperties = getTrackCommonProperties();\r\n const properties = merge(commonProperties, customParams);\r\n\r\n return () => new GoogleAnalytics4Event(eventName, properties);\r\n};\r\n\r\n/**\r\n * The getGoogleAnalytics4Event function returns a GoogleAnalytics4Event object.\r\n * @param eventType Determine which type of event to create\r\n * @param eventName Identify the event name\r\n * @param customParams Send custom parameters to the event.\r\n *\r\n * @return An GoogleAnalytics4Event object\r\n */\r\nexport const getGoogleAnalytics4Event = (eventType, eventName, customParams) => {\r\n if (eventType === GoogleAnalytics4EventType.Event) {\r\n return createTrackEvent(eventName, customParams);\r\n }\r\n\r\n return null;\r\n};\r\n","import MarketingStatus from 'enums/marketingStatus';\r\n\r\n/**\r\n * Checks if the marketingStatus has the Coming Soon (C) code.\r\n * @param {string} marketingStatus The status of the community.\r\n * @returns a flag indicating whether marketing Status has Coming Soon or not.\r\n */\r\nexport function isComingSoon(marketingStatus) {\r\n const statusArray = marketingStatus?.split?.(',');\r\n\r\n return statusArray?.some((key) => MarketingStatus.fromKey(key) === MarketingStatus.ComingSoon);\r\n}\r\n\r\n/**\r\n * Checks if the marketingStatus has the Close Out (X) code.\r\n * @param {string} marketingStatus The status of the community.\r\n * @returns a flag indicating whether marketing Status has Close Out or not.\r\n */\r\nexport function isCloseOut(marketingStatus) {\r\n const statusArray = marketingStatus?.split?.(',');\r\n\r\n return statusArray?.some((key) => MarketingStatus.fromKey(key) === MarketingStatus.CloseOut);\r\n}\r\n\r\n/**\r\n * Checks if the marketingStatus has the Grand Opening (G) code.\r\n * @param {string} marketingStatus The status of the community.\r\n * @returns a flag indicating whether marketing Status has Grand Opening or not.\r\n */\r\nexport function isGrandOpening(marketingStatus) {\r\n const statusArray = marketingStatus?.split?.(',');\r\n\r\n return statusArray?.some((key) => MarketingStatus.fromKey(key) === MarketingStatus.GrandOpening);\r\n}\r\n\r\n/**\r\n * Checks if the marketingStatus has the Active (N) code.\r\n * @param {string} marketingStatus The status of the community.\r\n * @returns a flag indicating whether marketing Status has Active or not.\r\n */\r\nexport function isActive(marketingStatus) {\r\n const statusArray = marketingStatus?.split?.(',');\r\n\r\n return statusArray?.some((key) => MarketingStatus.fromKey(key) === MarketingStatus.Active);\r\n}","/**\r\n * Recursively converts object keys to camel case\r\n */\r\nexport const camelCaseObjectKeys = (object) => {\r\n if (typeof object !== 'object' || !object) {\r\n return object;\r\n }\r\n\r\n // eslint-disable-next-line no-use-before-define\r\n const camelCaseObject = camelCaseArray(object) || {};\r\n\r\n if (object && !camelCaseObject.length) {\r\n Object.keys(object).forEach((key) => {\r\n const camelCaseKey = key.charAt(0).toLowerCase() + key.slice(1);\r\n camelCaseObject[camelCaseKey] = camelCaseObjectKeys(object[key]);\r\n });\r\n }\r\n\r\n return camelCaseObject;\r\n};\r\n\r\n/**\r\n * Recursively converts object keys to camel case\r\n * This function just change the properties of your object, not the value or the types of your properties.\r\n */\r\nexport const camelCaseArray = (object) => {\r\n if (Array.isArray(object)) {\r\n object.forEach((element, index) => {\r\n object[index] = camelCaseObjectKeys(element);\r\n });\r\n return object;\r\n }\r\n\r\n return null;\r\n};\r\n","/**\r\n * The cleanObjectsEmptyProperties function takes an object as a parameter\r\n * and returns the same object with all empty properties removed.\r\n * @param objectToClean Pass in the object that you want to clean\r\n *\r\n * @return Object without empty or null properties.\r\n */\r\nconst cleanObjectsEmptyProperties = (objectToClean) =>\r\n Object.fromEntries(Object.entries(objectToClean).filter(([, value]) => value !== null && value !== undefined));\r\n\r\nmodule.exports = cleanObjectsEmptyProperties;\r\n","const defaultFormats = {\r\n webp: 'image/webp',\r\n jpg: 'image/jpeg',\r\n};\r\n\r\nconst createQueryString = (parameters) =>\r\n Object.keys(parameters)\r\n .sort()\r\n .map((name) => `${name}=${parameters[name]}`)\r\n .join('&');\r\n\r\n/**\r\n * Generates image sources and src for the picture element using breakpoints.\r\n * @param {String} url Base image without parameter.\r\n * @param {Object} breakpoints Image breakpoints to generate the sources. It helps to generate 1x, 2x and 3x sources.\r\n * The object keys represents each breakpoint to create it.\r\n * @param {Object} formats (Optional) Supported formats.\r\n * @param {Object} irsParameters Image Resize Service parameter. Exclude size parameters like (width, height)\r\n * and format.\r\n *\r\n * @returns {Object} with two properties: sources and @{Array} with all the sources\r\n * Also src representing the image URL of img tag.\r\n */\r\nconst createPictureImageSources = ({ url, breakpoints = {}, formats = defaultFormats, irsParameters = {} }) => {\r\n const sources = Object.keys(formats).reduce((acc, format) => {\r\n const formattedSources = Object.keys(breakpoints).reduce((srcset, breakpoint) => {\r\n const parameters = { ...breakpoints[breakpoint], ...irsParameters, format };\r\n const queryString = createQueryString(parameters);\r\n return `${srcset}${url}?${queryString} ${breakpoint}, `;\r\n }, '');\r\n\r\n // Remove trailing comma and space from the final srcset\r\n acc.push({ srcset: formattedSources.slice(0, -2), format: formats[format] });\r\n return acc;\r\n }, []);\r\n\r\n const sizing = Object.values(breakpoints)[0] ?? {};\r\n const parameters = { ...sizing, ...irsParameters, format: 'jpg' };\r\n const queryString = createQueryString(parameters);\r\n const src = `${url}?${queryString}`;\r\n return { sources, src };\r\n};\r\n\r\nexport default createPictureImageSources;\r\n","function objectEquals (x, y) {\r\n return (x && y && typeof x === 'object' && typeof y === 'object') \r\n ? (Object.keys(x).length === Object.keys(y).length) && \r\n Object.keys(x).reduce((isEqual, key) => isEqual && objectEquals(x[key], y[key]), true)\r\n : (x === y)\r\n};\r\n\r\nexport default objectEquals","import { store } from '@redux/store';\r\nimport {selectConfigurationImageResizeService } from 'layout/redux/selectors';\r\n\r\nexport default function getRandomLifestyleImage(){\r\n const state = store.getState();\r\n const irsDomain = selectConfigurationImageResizeService(state);\r\n const random = Math.random();\r\n const number = Math.floor(random * 20) + 1;\r\n return `${irsDomain}/images/Lifestyle/lifestyle_${number}.jpg`;\r\n}","export default class StringExtensions {\r\n static toCamelCase(stringObject) {\r\n return stringObject.charAt(0).toLowerCase() + stringObject.slice(1);\r\n }\r\n\r\n /**\r\n * Method used to convert a string into kebab case\r\n * yeah, that's the name :P, you can read more about different type of cases here:\r\n * https://www.freecodecamp.org/news/snake-case-vs-camel-case-vs-pascal-case-vs-kebab-case-whats-the-difference/\r\n * @param {string} stringObject \r\n * @returns a new string in kebab case\r\n */\r\n static toKebabCase(stringObject) {\r\n if (!stringObject){\r\n return stringObject;\r\n }\r\n\r\n return stringObject.replace(/[^a-zA-Z0-9]/g, '-');\r\n }\r\n\r\n /**\r\n * Method used to remove special characters from a string\r\n * @param {string} stringObject \r\n * @returns a new string without special characters\r\n */\r\n static removeSpecialCharacters(stringObject, replace = '') {\r\n // Replace any non-alphanumeric characters except for spaces and the forward slash (\"/\") \r\n // character with an empty string\r\n if (!stringObject){\r\n return stringObject;\r\n }\r\n\r\n return stringObject.replace(/[^\\w\\s-]+/g, '').replace(/[\\s]+/g, replace).replace(/[-]+/g, '-').trim();\r\n }\r\n\r\n /**\r\n * Method used to encode a name string to be used in a URL\r\n * @param {string} stringObject \r\n * @returns a new string without special characters, kebab case and lower case\r\n */\r\n static encodeNameToUrl(stringObject) {\r\n if (!stringObject) {\r\n return '';\r\n }\r\n\r\n const nameWithoutSpecialCharacters = this.removeSpecialCharacters(stringObject, '-');\r\n const kebabCase = this.toKebabCase(nameWithoutSpecialCharacters);\r\n const name = kebabCase.replace(\"'\", '').replace('/', '');\r\n return name.toLowerCase();\r\n } \r\n\r\n/**\r\n * The function removes a specified word from a given string and returns the updated string.\r\n * @param {string} stringObject - A string that contains the word to be removed.\r\n * @param {string} wordToRemove - The word that needs to be removed from the string.\r\n * @returns a new string with the specified `wordToRemove` removed from the original `stringObject`.\r\n */\r\n static removeWordFromString(stringObject, wordToRemove){\r\n const startInIndex = stringObject.indexOf(wordToRemove) - 1;\r\n const newValue = stringObject.substring(0, startInIndex)\r\n\r\n return newValue;\r\n }\r\n\r\n/**\r\n * Adds a comma seperated value to a string if it does not already contain it.\r\n * @param existingString - The existing comma seperated value string.\r\n * @param targetValue - The new value to conditionally add.\r\n * @returns The new comma seperated value string.\r\n * @example \r\n * StringExtensions.addComaSeperatedValue('A,D,GG,Z,K', 'X') // 'A,D,GG,Z,K,X'\r\n * StringExtensions.addComaSeperatedValue('A,D,GG,Z,K', 'A') // 'A,D,GG,Z,K'\r\n */\r\n static addCommaSeperatedValue(existingString, targetValue){\r\n if(!existingString) {\r\n return targetValue\r\n }\r\n\r\n const valueArray = existingString?.split?.(',');\r\n\r\n const hasTargetValue = valueArray?.some(\r\n (key) => key === targetValue\r\n );\r\n\r\n return hasTargetValue ? existingString : existingString?.concat(',', targetValue)\r\n};\r\n\r\n/**\r\n* Removes a comma seperated value from a string if it contains it.\r\n* @param existingString - The existing comma seperated value string.\r\n* @param targetValue - The new value to conditionally remove.\r\n* @returns The new comma seperated value string.\r\n* @example\r\n* StringExtensions.removeCommaSeperatedValue('A,D,GG,Z,K', 'X') // 'A,D,GG,Z,K'\r\n* StringExtensions.removeCommaSeperatedValue('A,D,GG,Z,K', 'A') // 'D,GG,Z,K'\r\n*/\r\n static removeCommaSeperatedValue(existingString, targetValue){\r\n const valueArray = existingString?.split?.(',');\r\n\r\n const newValueArray = valueArray?.filter((value) => value !== targetValue)\r\n\r\n return newValueArray?.join(',');\r\n };\r\n\r\n}\r\n","/**\r\n * A utility class for working with URLs.\r\n */\r\nexport default class UrlExtensions {\r\n\r\n /**\r\n * Gets the subdirectory of a URL.\r\n * @param {URL} url - The URL to get the subdirectory from.\r\n * @returns {string|null} The subdirectory of the URL, or null if there is none.\r\n */\r\n static getSubdirectory(url) {\r\n const firstSegment = url.pathname?.split('/')?.[1];\r\n const subdirectory = firstSegment || null;\r\n\r\n return subdirectory;\r\n }\r\n\r\n /**\r\n * Removes the query string from a URL.\r\n * @param {string} url - The URL to remove the query string from.\r\n * @returns {string} The URL without the query string.\r\n */\r\n static removeQueryString(url) {\r\n if(!url){\r\n return url;\r\n }\r\n \r\n const urlWithoutQueryString = url?.split('?')[0];\r\n return urlWithoutQueryString;\r\n }\r\n\r\n /**\r\n * Gets the value of a query parameter from a URL.\r\n * @param {URL} url - The URL to get the parameter value from.\r\n * @param {string} parameter - The name of the parameter to get the value of.\r\n * @returns {string|null} The value of the parameter, or null if it doesn't exist.\r\n */\r\n static getParameterValue(url, parameter) {\r\n const searchParams = new URLSearchParams(url.search);\r\n return searchParams.get(parameter) ?? null;\r\n }\r\n\r\n /**\r\n * Gets the value of a query parameter from the URL hash.\r\n * @param {URL} url - The URL to get the parameter value from.\r\n * @param {string} parameter - The name of the parameter to get the value of.\r\n * @returns {string|null} The value of the parameter, or null if it doesn't exist.\r\n */\r\n static getParameterValueFromHash(url, parameter) {\r\n const search = url.hash.replace('#', '?');\r\n const searchParams = new URLSearchParams(search);\r\n return searchParams.get(parameter) ?? null;\r\n }\r\n\r\n /**\r\n * Sets query parameters on a URL.\r\n * @param {string} url - The URL to set the parameters on.\r\n * @param {Object.} parameters - An object containing the parameter names and values to set.\r\n * @returns {string} The URL with the new parameters set.\r\n */\r\n static setParameters(url, parameters) {\r\n const separator = url.includes('?') ? '&' : '?';\r\n const query = [];\r\n Object.keys(parameters).forEach((key) => {\r\n const value = parameters[key];\r\n if (value !== null) {\r\n query.push(`${key}=${encodeURIComponent(value)}`);\r\n }\r\n });\r\n\r\n if (query.length) {\r\n return `${url}${separator}${query.join('&')}`;\r\n }\r\n\r\n return `${url}`;\r\n }\r\n}\r\n","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\"","module.exports = \"\""],"names":["hasValue","value","constructor","element","this","checkbox$","pipe","event","target","closest","parent","Array","from","querySelectorAll","map","option","setSelector","selector","store$","subscribe","checkboxes","forEach","checkbox","checked","Boolean","getObservable","closePanel","panelToggle","setUpPanelEvents","handler","handleClickOutsideofElement","bind","document","removeEventListener","applyButton","container","querySelector","addEventListener","contains","configuration","once","select$","RecommendedType","static","type","getName","GoogleAnalyticsCustomDimensions","dimension","HousingProductType","baseElementUrl","attributes","href","window","location","origin","getBreadcrumbContent","getCommunitiesResults","getHousingProductSnippetContent","getListingCounts","getOnPageContent","getResultFacets","getTypeaheadOptions","leadsBasicCommunitySubmission","leadsBasicPlanSubmission","leadsBasicSpecSubmission","leadsBasicListingSubmission","leadsGetRecommendedCommunities","leadsPaidCommunitySubmission","leadsPaidPlanSubmission","leadsPaidSpecSubmission","leadsRecommendedCommunitySubmission","mapGetCommunitiesPoints","mapGetHomesPoints","totalDeliveryValueCommunityLogger","totalDeliveryValuePlanLogger","totalDeliveryValueSpecLogger","userDeleteFavorite","userProfileGetFavorites","userSaveFavorite","googleOneTapLogin","getCommunityNearbyListingsInfo","getBuildablePlanNearbylistingsInfo","getPlanNearbyListingsInfo","getSpecNearbyListingsInfo","searchCommunitySitePlans","getCommunityInteractiveSitePlanMarkers","getCommunitySummaryCard","getHousingUnitSummaryCard","backArrowSvg","closeIconSvg","closeModalIconSvg","thanksContentIconSvg","interactiveSitePlanSvg","thankYouHeartSvg","thankYouEmailSvg","thankYouPhoneSvg","thankYouSuccessSvg","callForPriceCommunityIconSvg","callForPriceCommunityActiveIconSvg","callForPriceHomeIconSvg","callForPriceHomeActiveIconSvg","priceReducedIconSvg","ratingStartIconSvg","locationIconSvg","markerArrowIconSvg","markerArrowHoverIconSvg","closeSmallIconSvg","category","action","label","customDimensions","eventCategory","eventAction","eventLabel","Object","assign","GoogleAnalytics4EventType","Event","getInstance","key","instances","name","toString","defineProperty","LoadingStatus","Failed","Idle","Loading","Succeeded","failed","idle","loading","succeeded","MarketingStatus","ComingSoon","Active","GrandOpening","CloseOut","ComingSoonGrandOpening","C","N","G","X","CG","PageType","Homes","Communities","Builders","BuildOnYorLotLocations","CustomHomes","ManufacturedHomes","Manufactured","LearningCenter","TypeaheadLocationType","City","Market","Community","MasterPlannedCommunity","Zip","Synthetic","County","GoogleAdsEventType","eventName","enhancedConversionData","ecData","getEvent","getEnhancedConversionData","createTrackEvent","data","state","store","commonProperties","email","phone_number","phone","getEnhancedConversionProperties","eventType","searchResultsGoogleTagManagerMiddleware","payload","getTarget","googleTagManager","customProperties","ThankScreenVariation","AskQuestion","Brochure","Tour","LimitedAvailability","Basic","comingSoon","askQuestion","brochure","tour","limitedAvailability","basic","DetailsAnchor","anchorId","bindEvents","getAnchor","onClickEvent","body","dispatchEvent","CustomEvent","detail","listingId","listingType","setUrl","url","setListingId","id","setListingType","getElementById","getHtml","SchedulerAnchor","PhoneAnchor","buttonId","setPhoneNumber","phoneNumber","replaceAll","userFriendlyPhone","revealPhone","anchor","getPhoneAnchor","getPhoneButton","setAttribute","removeAttribute","PhoneAnchorCallTracking","CreateAccountAnchor","ReturnToSearchAnchor","getContactBuilderAnchor","modalInformation","listingInformation","schedulerUrl","hasCallTracking","anchors","schedulerAnchor","push","condition","phoneCallTrackingAnchor","phoneAnchor","detailAnchor","find","getInternalBrowsingAnchor","isLoggedIn","backButton","privacyPolicyParagraph","closeButton","recommendedPolicyParagraph","CommunityInformationLead","formData","communityId","comments","includeRecommendations","includeRecommended","mailAddress","userPhoneNumber","leadAction","fromPage","excludeRecommendations","realtorQuestionAnswerId","realtorQuestion","postalCode","userPostalCode","livesOutside","setHousingInformation","properties","marketId","marketName","builderName","brandName","communityName","PlanInformationLead","planId","RecommendedBrochureLead","recoComms","getRecommendedCommunities","zip","international","firstName","lastName","builderId","recommendations","keys","filter","includes","JSON","parse","SpecInformationLead","specId","leadConstructor","Map","set","preferredContactMethod","date","super","xxTrustedFormCertUrl","generator","get","prototype","GoogleAnalyticsEventAction","DirectLeads","NonDirectLeads","Leads","R","A","GoogleAnalyticsEventCategory","TdvMetrics","TdvEvents","RealtimeEvents","EventTrackingTdvEventsMixin","model","getGoogleAnalyticsData","BasicLeadTrackingEvents","events","googleAnalytics","EventTrackingNonDirectLeadsMixin","EventTrackingRealTimeEventsMixin","EventTrackingTdvMetricsMixin","BrochureTrackingEvents","InformationTrackingEvents","TourTrackingEvents","AskQuestionTrackingEvent","postRecommendedLeadForm","leadInformation","uiStateSlice","isFetchingModal","parameters","postLeadBrochureForm","googleAnalyticsDTO","updateModalProgress","BrochureButton","getNode","CommentsTextArea","input","EmailInput","valueInput","errorMessageId","errorCssClass","errorMessage","matchingPattern","newValue","getOnChangeEvent","fromEvent","setInvalidState","node","classList","add","setValidState","remove","validate","cleanedValue","trim","replace","isValid","test","NameInput","pattern","RegExp","focus","PhoneInput","required","screenReaderMessage","phoneInput","maskPattern","removeRequired","placeholder","setRequired","isEmpy","isRequired","RecommendedCheckbox","hasUserOptedIntoRecommendationEmail","ZipInput","isInternationalInput","idForOutside","idForZip","labelForOutside","labelForZipCode","isInternational","getOutsideUsNode","onOutsideUsChanged","getZipNode","outSideNode","zipNode","onOutSideChange$","startWith","onZipChange$","combineLatest","zipInput","livesOutsideInput","skip","isOutsideUs","isValidZipCode","currentTarget","RealtorDropdown","selectedValue","realtorDropdown","setSelectedValue","realtorDropdownNode","optionsArray","options","selectedIndex","findIndex","isEmpty","BrochureFormPaid","userProfile","uiState","getBrochureButton","commentsTextArea","emailAddressInput","formId","fullNameInput","phoneNumberInput","postalCodeInput","recommendedCheckbox","stateAbbreviation","city","setHousingData","housingData","submitBrochureForm","preventDefault","validateNode","some","disabled","FormData","getForm","brochureInformation","fromEntries","entries","brochureLeadObject","bindChangeEvents","unbindEvents","BasicContactVendor","OpCity","PrimeStreet","CoffmanProperties","Dezka","MarketplaceHomes","NewHomeExpertsDetroit","NewHomeExpertsLasVegas","NewHomeExpertsSarasota","NHSAustin","defaultPrivacyPolicyParagraph","contactVendorName","InformationButtonBasic","InformationFormBasic","moreInformationButton","setPrivacyPolicyText","createElement","innerHTML","basicPrivacyPolicyParagraph","firstChild","outerHTML","submitInformationForm","leadObject","postLeadInformationFormBasic","InformationButton","InformationFormPaid","isPersistent","buttonText","postLeadInformationForm","ContactRadioGroup","idEmail","idPhone","idText","radioInputSelector","labelEmail","labelPhone","labelText","onChange","callback","DateInput","tomorrow","Date","toDateString","tomorrowIsoString","toISOString","split","error","SubmitRequestButton","TourRadioOptions","idContactOneOnOne","idVideoChat","radioChecked","inputContactOneOne","labelContactOneOne","inputVideoChat","labelVideoChat","getCheckedNode","getVideoChatLabelNode","getOneOnOnetLabelNode","nodeVideoChat","nodeOneOnOne","RequestTourForm","requestButton","contactRadioGroup","tourRadioOptions","dateInput","postLeadTourForm","onPreferredContactMethodChange","setRequiredAttributeInPhone","BrochureFormLimitedAvailability","AskQuestionButton","AskQuestionFormPaid","getAskQuestionButton","submitAskQuestionForm","formInformation","postLeadAskQuestionForm","ManufacturedBrochureFormPaid","leadGeneratorConstructors","RecommendedButton","SkipButton","closeModalSvg","thanksContentSvg","thankYouEmail","thankYouHeart","thankYouPhone","thankYouSuccess","RecommendedScreen","recommendationsHtml","closeAttribute","onSkipEvent","recommendedCheckAttribute","skipButton","submitRecommendationsForm","userName","slice","join","getThankYouModalInformation","skipModal","closeModal","elem","onRecommendationChecked","click","length","modalService","recommendedCommunities","selectedRecommendedCommunities","getRecommendedBrands","brandElements","DOMParser","parseFromString","brands","el","brand","textContent","RecommendedButtonBasic","RecommendedScreenBasic","getBrochureButtonBasic","getRecomendedBrands","ThankScreenAskQuestion","moreDetailsAnchor","emitMoreDetailsClickEvent","detailsLink","ThankScreenBasic","setInternalBrowsingAnchor","internalBrowsingAnchor","ThankScreenBrochure","closeBtnId","setContactBuilderAnchor","contactBuilderAnchor","getCloseBtn","clearHtml","ThankScreenComingSoon","ThankScreenLimitedAvailability","ThankScreenTour","message$","messageService","hasFinishedLoading","leadGeneratorInstance","recommendationsInstance","getFreeBrochureThankYouScreen","brochureThankYouScreen","getThankYouScreen","screenVariation","variation","comingSoonThankYouScreen","getComingSoonThankYouScreen","thankYouScreenBasic","getThankScreenBasicScreen","dataset","openerKey","leadGeneratorOpener","leadGenerator","leadGeneratorName","validListingInformation","getGoogleAnalyticsEventCallback","getFormOpenedAnalyticsData","getGoogleAnalyticsDTOCallback","newState","initialState","fn","overlayElement","distinctUntilChanged","screen","distinctUntilKeyChanged","html","msg","messageType","message","isBasic","LeadFormType","getRecommendedCommunities$","requestObject","method","stringify","leadCommand","headers","response","text","postCommunityBrochure","fetch","actions","action$","fetchModal","tap","switchMap","of","fetchModalFulfilled","postPlanBrochure","postSpecBrochure","postRecommendedCommunities","catchError","err","fetchModalError","postSpecBrochureBasic","postPlanBrochureBasic","postCommunityBrochureBasic","postBasicListingBrochureBasic","searchParameters","searchCommand","json","selectLocation","selectProductType","breadcrumbListContainer","breadcrumbJsonLdMarkupContainer","onLocationChange$","previousState","currentState","previousLocation","currentLocation","isSameLocation","isSameProductType","isSameResultType","mapState","isSearchWithinMap","onBreadcrumbReady$","product","results","shareReplay","createRootBreadcrumb","breadcrumb","anchorElement","Url","title","Title","breadcrumbRoot","spanElement","innerText","Name","append","createBaseBreadcrumb","BreadcrumbStack","breadcrumbList","currentBreadcrumbElements","children","index","breadcrumbElement","newBreadcrumb","liElement","newBreadcrumbElement","IsAnchorLink","createBreadcrumbElement","samePositionBreadcrumb","isEqualNode","replaceWith","BreadcrumbJsonLdMarkup","breadcrumbJsonLdMarkup","h1Element","h2Element","footer","readMoreButton","metaRobotsElement","isNotFetchingContent","results$","facts$","features$","location$","presentationType$","product$","resultsModifier$","onUrlFilterChange$","combinedValues","presentationType","paging","page","setH1Text$","heading1","setH2Text$","heading2","setFooter$","footerData","style","display","setTitle$","setCanonical$","canonicalData","canonical","canonicalUrl","canonicalElement","updateCurrentCanonicalElement","newCanonicalElement","head","appendChild","createCanonicalElement","setMetaRobots$","metaRobots","setMetaDescription$","metaDescriptionData","metaDescription","newMetaDescription","moveInDateRange","removeCanonicalOnMoveInDateFilterApplied","popularSearches","marketSnapshots","geoLocationProximity","marketSnapshotsContainer","marketSnapshotsTitle","toggleGeoLocationProximitySnippet","listingCounts","snippetInformation","toggleMarketSnapshotSnippet","togglePopularSearchesSnippet","onResultsReady$","debounceTime","snippetCommand","take","fetchResultCountsStatus","total","counts","listingCount","undefined","geoLocationProximitySnippet","GeoLocationProximitySnippet","Content","marketSnapshotSnippets","MarketSnapshotSnippets","popularSearchesSnippet","PopularSearchesSnippet","totalListingCount","htmlSnapshots","snapShot","combinedHtml","setMarketSnapshot","setPopularSearches","HousingProductLocationContentCommand","selectHousingProductLocationContentContext","urlQueryStringSelector","selectSearchCommandContext","selectConstructQueryString","selectHousingProduct","locationContentCommand","queryStringSelector","searchParams","queryString","URLSearchParams","queryStrings","structuredClone","createCanonicalUrlCommand","searchLocationCommand","contentCommandParameters","housingProductLocationContentCommand","command","state$","fetchFulfilled","fetchError","housingProductLocationContentActions","reducer","selectTitle","housingProductLocationContent","selectMetaDescription","selectMetaRobots","selectCanonical","selectHeading1","selectHeading2","selectFooter","selectFetchStatus","fetchStatus","selectRequestStatus","fetchingResultsCallStatuses","housingProductLocationFetchStatus","fetchResultListingsStatus","content","innerHTM","reducers","camelCase","PillType","HotDeals","Adult","FloorPlans","QuickMoveIns","CondosAndTownhomes","getPageLink","pageLinkType","relationType","relationElement","rel","createRelationElement","removePageLink","updatePageLink","pageLinkUrl","nextPageLinkUrl","previousPageLinkUrl","updatePagination","updateSubdirectory","updateLocation","updateQueryString","updateBuilderName","config","updateUrl","routingStateActions","routingSelectors","urlComponentsSelector","selectCurrentUrl","selectUrlLocation","routingActions","listenerMiddleware","startListening","effect","newUrl","history","pushState","middleware","selectUrlSubdirectory","routingState","urlSubdirectory","urlLocation","selectUrlQueryString","urlQueryString","selectNextPageUrl","nextPageUrl","selectPreviousPageUrl","previousPageUrl","currentUrl","selectRoutingState","selectMapCoordinatesQueryString","urlCoordinatesQueryString","urlPaging","urlBuilderName","urlFilterSelector","queryStringParameter","routingDataElement","routingData","URL","updatePreviousPageUrl","updateNextPageUrl","updateRectangularSearchQueryString","buildNewUrl","newPathName","subdirectory","urlSegments","buildUrlPathName","search","getPaging","pageNumber","getBrandName","brandId","counter","sliderItems","sliderLength","sliderWidth","clientWidth","slidesContainer","prevButton","nextButton","initSlider","scrollIntoView","checkArrowButtons","onresize","isSliderDisable","scrollWidth","navigator","maxTouchPoints","msMaxTouchPoints","behavior","inline","ReadMore","characterLimit","readMoreText","readLessText","dataReadSelector","getReadMoreHtml","hiddenText","closestReadMore","addReadMoreToggle","textElement","visibleText","substring","readMoreHtml","toggleReadMore","modal","extendedCardInformation","clearModal","previous","current","getBuildeablePlanCard$","getCommunityExtendCard$","getPlanExtendCard$","getSpecExtendCard$","ActiveAdultType","OnlyShowActiveAdultCommunities","ExcludeActiveAdultCommunities","AnyCommunities","only","Only","exclude","Exclude","any","Any","filters","clearButton","onFacetsApplied$","appliedFacets","appliedFilters","labelTxt","initialLabelText","buttonConfirmation","isResultTypeCommunity","resultType","isResultTypeLocations","onCountsAndResultsTypeChange$","resultCountsStatus","updateLabel","indexOf","toLocaleString","schools","marketingStatus","selectContainer","selectElement","allBuildersOption","selected","clearSelectOptions","optionElement","Id","Number","facetsValues","ignoredSorts","sort","ClearFilters","buttonElement","select","natureAreasElement","poolElement","golfCourseElement","greenElement","sportFacilitiesElement","parksElement","viewsElement","waterfrontElement","gatedCommunityElement","checkboxGroup","amenities$","amenities","amenity","natureAreas","pool","golfCourse","green","sportsFacilities","parks","views","waterfront","gatedCommunity","marketingStatusListContainer","labelTextContainer","allMarketingStatusOption","selectedOptions$","onMarketingStatusChanged$","statuses","selectedOptions","marketingStatuses","fetchMarketingStatus","selectedMarketingStatusNumber","selectedStatuses","defaultText","parentElement","toggle","HousingType","DefaultHousingType","SingleFamily","Custom","Luxury","CondosAndTownHomes","ModelHomes","Redirect","singleFamily","custom","luxury","condosAndTownHomes","manufactured","modelHomes","defaultHousingType","housingTypeConstructors","onSingleFamilyChange","onProductAndResultTypeChange","dispatchFetchResultAction","getSearchCommands","productType","productTypeToApply","resultTypeToApply","singleFamilyToApply","productAndResultType","toggleSelect","toggleBox","onLuxuryChange","luxuryToApply","onCondosAndTownHomesChange","condosAndTownHomesToApply","onProductOrResultTypeChange","typeParameters","onModelHomesChange","homeStatus","housingElements","housingTypeOptions","housingType","housingTypeName","housingTypeConstructor","selectChange$","lastState","reviews","facts","builderReviews","hotDeals","consumerPromos","priceReduction","homeOwnersAssociationFee","hasHomeOwnersAssociationFee","otherFilters","PriceDualSlider","onPriceChange$","maximumSliderValue","minimumSliderValue","highPriceLimit","rangeConfiguration","min","max","setDualRangeSlider","dualRangeSliderValueChange$","priceChangeHandler","minimumPrice","maximumPrice","updateValueSliders","minimumValue","maximumValue","minimumSliderLabel","maximumSliderLabel","slider","dualRangeSlider","start","connect","range","cssPrefix","setInputEvent","setChangeEvents","setQaDataAttributeTag","updateSliderLabels","values","noUiSlider","updateSliders","getSliderValues","sliderValues","Math","ceil","getLabel","getSlideEvent","qa","on","maximumPriceLimit","schoolListContainer","allSchoolsOption","cloneNode","isAllSchoolsInactive","setSchoolsList","schoolInformation","schoolId","inputElement","labelElement","createOptionElement","updateSelectedSchool","selectedSchools","defaultValue","actualDefaultOption","schoolOption","updateSchoolsLabel","selectedSchoolsNumber","String","shouldClearAllSchools","schoolIds","newSchoolDistricts$","schoolDistricts","schoolDistrictIdsChange$","features","schoolDistrictIds","schoolsSelected","isArray","LocationType","RectangularArea","market","rectangulararea","syntheticgeo","county","toLowerCase","MoveInDate","OneToTwoMonths","ThreeToSixMonths","BuildablePlans","OtherFiltersType","HomeOwnersAssociationFee","PriceReduction","Reviews","adult","PlanStatus","AvailableNow","Model","ReadyToBuild","UnderConstruction","UC","M","H","ProductType","AllProducts","BuildOnYourLot","allProducts","communities","homes","boyl","ResultType","cssSelectorForNativeAds","Locations","builders","locations","SortType","queryStringValueDescending","queryStringValueAscending","validResultTypes","Price","Bed","CommunityId","price","bed","community","getQueryStringValue","isAscendingOrder","SpecStatus","fetchRvGarages","fetchAmenities","fetchCustom","fetchSingleFamily","fetchLuxury","fetchCondosAndTownHomes","fetchManufactured","fetchModelHome","fetchConsumerPromos","fetchPriceReduction","fetchBuilderReviews","fetchActiveAdult","fetchPrice","fetchBedrooms","fetchBathrooms","fetchSchools","clearFilters","allOptions","fetchBrandId","fetchLivingAreas","fetchStories","fetchPrimaryBedroom","fetchGarages","fetchMoveInDateByRange","fetchMoveInDateByStatus","clearMoveInDateFilter","fetchViewBrandResults","fetchViewBrandMarketResults","fetchExcludeActiveAdult","fetchAnyCommunities","fetchGolfCourse","fetchSort","fetchHomeOwnersAssociationFee","fetchInteractiveSitePlanResults","FetchRequest","Listings","Counts","SchoolsAndBrandsFaceting","listings","schoolsAndBrandsFaceting","allResultsCalls","fetchRequestListByAction","fetchPageSize","fetchPageNumber","fetchPagingControlsNext","fetchPagingControlsPrev","fetchLocations","fetchResultsType","actionType","fetchRequest","fetchRequestList","isCommunityLocationTypeSearch","locationType","PriceFilterLabel","facetPriceLabel","priceSlider","priceMinimumSlider","priceMaximumSlider","onPriceChange","toggleActiveClass","updatePriceRangeText","minimum","maximum","priceLabels","SelectMoveInDate","moveInDate","onChangeMoveInDate","moveInDateChange$","setMoveInDateValue","onProductTypeChange","disable","enable","group","Bedroom","bedroomsGroup","updateValue","bedrooms","previousValue","Bathroom","bathroomGroup","bathrooms","BedroomAndBathroomFilterLabel","bedroomAndBathRoomLabel","bedroomElement","bedroomLabel","bathroomElement","bathroomLabel","onBedroomChange$","onBedroomChange","changeBedroomLabel","onBathroomChange$","onBathroomChange","changeBathroomLabel","minimumBedroom","minimumBathroom","facetsReducers","moveInDateElement","facetBedroomBathroomLabel","fetchResultCounts","fetchResultsCountsFulfilled","fetchResultsCountsError","fetchResultListings","fetchSchoolsAndBrandsFaceting","fetchResultFacetsFulfilled","fetchResultFacetsError","updateFilters","changeZipSearchtoCitySearch","searchParametersSelectors","selectContentTemplateTypeModifiers","isCommunity","isMasterPlannedCommunity","selectAdult","selectAgeRestricted","ageRestricted","isCustom","selectFetchResultCountsStatus","selectCommunityName","isBuildOnYourLot","isCustomHomes","buildOnYourLot","isManufactured","selectPriceReduction","selectMoveInDateRange","selectMinimumPrice","selectMaximumPrice","selectNatureAreas","selectPool","selectGolfCourse","selectGreen","selectSportsFacilities","selectParks","selectViews","selectWaterfront","selectGatedCommunity","selectMarketingStatus","selectConsumerPromos","selectRvGarage","recreationalVehicleGarage","selectHomeStatus","selectBathrooms","selectBedrooms","selectSchools","selectBrandId","selectBrandName","selectLivingAreas","livingAreas","selectStories","stories","selectPrimaryBedroom","primaryBedroom","selectGarages","garages","selectSingleFamily","selectLuxury","selectCondosAndTownHomes","selectPage","selectPaging","selectPrice","selectCounties","counties","selectAppliedFacets","facetsState","selectListingCount","selectProduct","selectResults","selectFeatures","selectFacts","selectResultsType","selectResultsModifiers","resultsModifiers","selectFetchResultListingsStatus","selectResultType","selectLocationType","selectSearchParameters","selectSorting","sorting","selectPageSize","pageSize","selectReviews","isNotCommunityLocationType","selectHomeOwnersAssociationFee","selectBrandInformation","selectExcludeAdult","excludeAdult","selectExcludeAgeRestricted","excludeAgeRestricted","housingOptionsSelector","model_homes","communityStatusSelector","coming_soon","grand_opening","active","closeout","selectCountsAndResultType","brandIdAndSchoolsSelector","activeAdultCommunitiesSelector","otherFiltersSelector","activeAdultCommunities","selectFetchCountsStatusAndsCounts","fetchingResultsCallStatusesSelector","selectSnippetCommand","contentTemplateType","selectProductAndResultType","selectSearchCount","hotDealsCount","adultCount","comingSoonCount","quickMoveInCount","buildablePlansCount","multiFamilyCount","selectLocationContentContext","syntheticGeographicName","marketState","schoolDistrictName","geoLocationType","syntheticName","selectSubdirectory","selectBrand","selectBrandFilterContext","communityAmenitiesSelector","appliedFacetList","selectPaginationContext","pageCountSelector","moveInDateSelector","isAnyHousingTypeActiveSelector","facetsSelector","rvGarage","customHomes","comingsoon","grandOpening","closeOut","schoolDistrict","builderBrand","exclude55","sortBy","selectSearchResultFacetsTrackingCommonProperties","brandInformation","facetsList","paginationContext","homeFactsSelectors","facetsPanelSelector","communityAmenities","homeFacts","brandAndSchools","housingOptions","communityStatus","selectLinkedPopularPillsFilters","selectResultTypeAndSorting","selectSearchModifiers","feature","modifiers","fetchResultsListingStatus","searchCommandElement","resultFacetsElement","resultCountsElement","resultFacets","resultCounts","Brands","SchoolDistricts","fetchSchoolsAndBrandsFacetingStatus","searchParametersSlice","fetchContentTemplateType","schoolList","school","firstSchoolName","fetchResultsListingError","newPage","parseInt","stateName","marketStateName","geoLocationState","originLatitude","originLongitude","minimumLatitude","maximumLatitude","minimumLongitude","maximumLongitude","isMaximum","sortType","sortOrder","sortFirstBy","Counties","ListingCount","HotDealsCount","ComingSoonCount","AdultCount","BuildablePlansCount","QuickMoveInCount","MultiFamilyCount","fetchResultsListingFulfilled","homeStatusApplied","newHomeStatus","clearModelHomeStatusFilter","toggleCurrentLocationSearch","isCurrentLocationSearch","getAppliedFilters","isCurrentlyActive","indexToRemove","item","splice","facetsSlice","hasAvailableNow","statusArray","hasReadyToBuild","hasModelHome","hasInventoryStatusCombination","isAvailableNowIncluded","isUnderConstructionIncluded","hasUnderConstruction","getInventoryStatusCombination","isMoveInDateApplied","getHomeStatusFilterApplied","getMovingDateFilterApplied","homeStatusFilterApplied","moveInDateFilterApplied","getMoveInDateFilterApplied","mapSearchEvent","getCoordinatesLabel","coordinates","east","north","south","west","toogleOn","toogleOff","boundaryProperties","onNewBoundariesShown$","newLocation$","onMapLoaded$","newMessages","newLocationSource","boundaries","mapBoundaries","information","BoundaryUrl","setTimeout","newBoundary","newMessage","newLocation","markerBoundary","every","property","hasOwn","locationBoundary","MinLatitude","MaxLatitude","MinLongitude","MaxLongitude","queryParams","communityIds","addInteractiveSitePlan","markers","marker","Status","HousingUnitId","HousePlanIds","newMarkerElement","Label","createMarkerHtmlElement","drawInteractiveSitePlan","scale","sitePlanId","markerElement","isVisible","className","left","center","x","top","y","removeInteractiveSitePlan","getCommunityInteractiveSitePlanInformation$","Set","mergeMap","interactiveSitePlans","previousProductType","previousResultType","markersBuffer","sitePlansBuffer","searchWithinMapCheckbox","getLotAvailableListings","lotListingIds","dispatchEnterInteractiveSitePlanResults","disableSearchWithinMap","removeInteractiveMarkers","interactiveSitePlan","areMarkersShown","setInteractiveSitePlan","setInteractiveSitePlanMarkersShownFlag","getInteractiveSitePlans","sitePlan","updateLotPolygon","groupName","polygons","removeHighlightedElements","addPolygonToGroup","lotPolygon","groupId","array","updateLotVisibility","getMarkers","getAvailability","zoomLevel","selectedLotId","areFiltersActive","excludedFilters","appliedFilter","areFiltersApplied","isInteractiveSitePlanShown","has","filteredMarkers","activeLots","inactiveLots","lotId","status","applyLotClassBasedOnStatus","lotIsVisible","toggleAttribute","isLotSelected","removeLotInformation","updatePlansVisibility","plans","currentPlans","updateSpecsVisibility","specs","currentSpecs","enableSitePlanInteraction","communityIdsForSorting","newMarkersContainer","interactiveMarkersContainerId","resource","onAdd","onDraw","onRemove","createInteractiveMarkers","currentSort","dispatchInteractiveSitePlanSorting","currentListingIds","trackLoadedSitePlans","loadingStatus","handleInteractiveSitePlanFetchResults","SitePlanLots","collection","SitePlanId","onProductTypeChanged$","onProductTypeDistinctThanHomes$","withLatestFrom","onProductTypeHomes$","onSitePlansChanged$","onNewCommunitiesWithInteractiveSitePlan$","sitePlans","isInteractiveSitePlan","onNewInteractiveSitePlans$","onTrackedInteractiveSitePlansChanged$","onInteractiveSitePlanRemoved$","pairwise","previousInteractive","currentInteractive","removed","onDistinctHomesMarkers$","onFetchInteractiveSitePlans$","trackedSitePlans","trackedPlan","onRemoveInteractiveMarkers$","previousZoom","currentZoom","onLotClicked$","allSitePlans","activeLotId","lotPath","plan","lotMarker","previousActiveLot","currentActiveLot","selectedGroup","updateActiveLotPolygonStyle","interactiveMarkersReady$","sitePlanDrawComplete$","onMarkersAndInteractiveMapReady$","merge","sitePlanSvg","lotPaths","lotsSvg","lotPixels","pixel","pixelBounds","getBoundingClientRect","path","pathBounds","shrunkPathBounds","width","right","height","bottom","getAttribute","onHoveredCardChanged$","focusedListing","onHoveredLot$","interestedLotPath","polygonId","polygonGroupId","cursor","hoverInformation","onInteractiveSitePlansRemoved$","onShowHiddenInteractiveMarkers$","prevItem","onExitInteractiveState$","onInteractiveCommunitiesZoomChanged$","onNewInteractiveSitePlanIds$","onZoomEnteringInteractiveState$","prevZoom","prevIds","currZoom","currIds","isZoomUnchanged","areIdsSame","onGoToSitePlanButtonCliked$","hasAttribute","goToSitePlanButton","latitude","longitude","shouldSwitchToHomeResults","fetchInteractiveSitePlanFromTooltipClick$","onLotInformationRemoved$","previousLot","currentLot","onEnterInteractiveState$","handleInteractiveMarkersOnZoomChange$","onWheelScrollOverTooltip$","passive","availableSpec","availablePlans","currentLotCommunityId","currentLotSpecId","currentLotCardStatus","lotNumber","interactiveSitePlanCardStatus","lotStatus","setLotInformation","sitePlanMap","polygonLots","async","sitePlansNodes","sitePlanNode","sitePlanLayers","layersToShow","flatMap","layers","layersToHide","layer","handleInteractiveMapLayersVisibility","removedInteractiveSitePlans","sitePlanIds","untrackInteractiveSitePlans","delete","isHomeResults","dispatchExitInteractiveSitePlanResults","lotPolygons","hoverGroup","activeGroup","visibilityFlag","lotInformation","clearSitePlanGroup","hoveredLotInformation","PaidInteractiveSitePlanCommunityCard","setInformation","summaryCard","availableSpecCount","availablePlanCount","errorImage","sources","src","createPictureImageSources","Thumbnail","breakpoints","irsParameters","mode","progressive","setLabel","handleOnErrorImage","picture","source","onerror","getElement","getTitle","getSubTitle","statusToShow","subTitleElements","plansLabel","getImage","srcset","format","PaidInteractiveSitePlanHousingUnitCard","specLable","interactiveSitePlanActions","summaryCardContainer","dispatchClearSummaryCardAction","clearInteractiveSitePlanCard","closeLotSummaryCard","cardsContainer","onLotSummaryCardLoading$","onLotSummaryCardNotSucceeded$","renderSummaryCard","card","fragment","createDocumentFragment","documentFragment","createRange","createContextualFragment","selectedLotSummaryCard$","lotSummaryCardSelected$","onCloseCard$","previousSummaryCard","currentSummaryCard","hamburgerMenuClicked$","advancedFiltersClicked$","ListViewToggled$","cardCloseClick$","onNoResults$","onRemovedInteractiveSitePlan$","lotCommunityId","onActiveLotChanged$","previousCard","currentCard","Type","summaryCardStatus","skeleton","defaultMapSettings","clickableIcons","disableDefaultUI","disableDoubleClickZoom","gestureHandling","minZoom","maxZoom","panControl","scrollwheel","zoomControl","zoomControlStyle","rectangularAreaMapSettings","defaultZoomLevels","syntheticGeo","rectangularArea","mapContainer","onSearchWithinMapReady","mapEvents","coordinatesChanged","mapBounds","isSearchWithinMapEnable","isSearchWithinMapReady","bounds","northEast","getNorthEast","southWest","getSouthWest","lng","lat","getBounds","newBounds","roundedZoom","round","extraMiles","milesToDegreesLat","newNorthEast","newSouthWest","expandBounds","updateCoordinates","dispatchBounds","mapLoaded","zoom","zIndex","updateMapZoomLevel","locationParameters","newPosition","updateMapPosition","setActiveMarker","selectedMarker","newSelectedMarker","isFeaturedListing","housing","setActiveNearbyListingsCarousel","setHoveredMarker","markerInformation","clonedMarker","clonedTooltip","tooltip","hoveredMarker","hideNotMainTooltips","tooltipArray","removeMarkerHovered","markerIcon","hovered","closeMarkerCard","isNoPrice","isSpotlight","isSelected","isPriceReduction","handleMarkerMapChanges","isMarkerSelected","carousel","openMarkerCard","viewed","isViewed","openUrl","interactionType","customEvent","open","onMarkerClicked","domEvent","srcElement","googleAnalyticsClickEvent","getState","isMarkerActive","hasExternalRepresentation","housingLocation","configureMarker","getGoogleAnalyticsEventForClicks","icon","getIcon","markerPosition","getType","metaData","getHousingLocationMetaData","getDetailUrl","description","getDescription","ignoreVisibilityUpdates","updateMarkers","markersFromStore","stateTransition","fetchResults","isFetchingResults","selectedMarker$","pastActive","geographicKey","mainMarker","pin","previousMarkerInfo","currentMarkerInfo","markerStyles","getValue","mapActions","onCardCtaClicked$","selectedNearbyListingCarousel$","previousCarousel","currentCarousel","carouselContainer","activeItem","closeNearbyListingsCarousel","layoutBreakpoint","nearbyListingsCarouselSelected$","observer","instance","previousCardPosition","observedElements","observeCards","cards","observerOptions","root","threshold","rootMargin","IntersectionObserver","entry","isIntersecting","currentCardPosition","parentNode","direction","cardLatitude","cardLongitude","listing","nextCardPosition","createIntersectionObserver","shift","unobserve","elements","observe","clearNearbyListingsCarousel","sitePlansReadyToRender","fetchMapsStatus","fetchStatus$","sitePlanHoveredStartTime","hoveredSitePlan","setFetchStatus","next","findMarker","markerId","preferredTypes","reduce","bestMarker","onNewMarkers$","isFetching","onRemoveNonNeededSitePlans$","mapRemovedSitePlans","onMapCoordinatesChanged$","isMapLoaded","removeSpecificSitePlans","removeSitePlan","onMapReadyTofetchAfterCoordinatesChanged$","onFetchMapsForNewMarkers$","fetchResults$","retrievedStaticMapIds","uniqueMarkers","onNewListings$","ondrawSitePlans$","onRemoveSitePlans$","onHoveredCard$","previousCommunityId","currentCommunityId","previousTooltip","currentTooltip","onNewCommunitySitePlans$","newSitePlan","previousMap","onZoomChanged$","zoomGesture","removedSitePlans","addedSitePlans","showSitePlanMarkers","hideSitePlanMarkers","isMouseMovingOnMap","communityMap","deviceType","now","hoverDuration","sitePlanToEmit","isInInteractiveState","seenCommunityIds","mapConfigurations","mapConfiguration","imageUrl","addSitePlan","createSitePlan","sitePlanConfiguration","viewboxHeight","ViewBoxHeight","viewboxWidth","ViewBoxWidth","rotationDegrees","Rotation","svgMask","SvgMask","MapImageUrl","TopRightLatitude","BottomLeftLatitude","TopRightLongitude","BottomLeftLongitude","IsInteractiveSitePlan","SvgLayers","mapsNotInViewPort","filteredSitePlans","visibleMap","NotVisibleMap","currentZoomLevel","promises","sitePlanContainer","Promise","all","overlay","polygonsContainer","onSingleClick$","onDoubleClick$","onMouseMove$","onMouseLeave$","SummaryCardSkeleton","CommunityLabel","IsFeaturedListing","CommunityType","getClassVariation","getText","HomeLabel","locationSearchParameters","factsSearchParameters","productSearchParameters","featuresSearchParameters","zoomLevelTriggers","zoomLevelEnterInteractiveStateTrigger","drawInteractiveSitePlanMarkers","zoomLevelSitePlansFetchTrigger","zoomLevelDrawSitePlansTrigger","zoomLevelLayersLookup","parser","priceReducedSvgElement","documentElement","callForPriceCommunitySvgElement","callForPriceCommunityActiveSvgElement","callForPriceHomeSvgElement","callForPriceHomeActiveSvgElement","ratingStarSvgElement","markerArrowSvgElement","markerArrowHoverSvgElement","LotPolygonType","Selected","Hovered","Inactive","default","empty","LotStatus","Sold","QuickMoveIn","Inventory","Unreleased","MarkerType","BuildablePlan","HousingDevelopment","PlanUnit","SpecUnit","buildeablePlan","spec","SitePlanLayer","LotNumbers","StreetNames","Walkway","Grass","Ground","LotPolygons","Street","Lots","Water","Golf","MainLots","getCommunityMapPoints$","getHomeMapPoints$","getEndpointsByFacts","defaultEndpoints","getDefaultEndpoints","endpointsByFacts","endpointsByProduct","endpoints","getEndpointsByProduct","endpointsByResult","result","getEndpointsByResult","showPlanCards","planIds","specIds","convertDegreesToRadians","deg","PI","getDistanceBetweenCoordinates","targetLatitude","targetLongitude","deltaLatitude","deltaLongitude","haversineFormula","sin","cos","atan2","sqrt","sortByDistanceAndPrice","a","b","distance","findNearbyPins","targetPin","pagination","targetPinWithDistance","nearbyMarkers","parseFloat","priceStr","basicMarkers","paidMarkers","sortedBasicMarkers","interactiveSitePlanReducer","onMapsLibraryLoaded","mapLibraryLoaded","onMapsLibraryErrored","mapLibraryErrored","apiRequests","forkJoin","fetchResultsFulfilled","MapBoundaries","fetchResultsError","allMarkers","ids","getNearbyListingsCarouselFulfilled","getNearbyListingsCarouselFailed","homeMarkers","nearbyPins","focusedListingInformation","fetchResultsPagesNumbers","enableSearchWithinMap","getInteractiveSitePlanCardFulfilled","getInteractiveSitePlanCardFailed","createMap","getGeoCoordinates","mapContainerDoubleClicked$","mapContainerClicked$","mapClicked$","mapDragStart$","selectIsSearchWithinMapReady","areMapBoundariesDefined","geoCoordinates","areMarkersAvailable","isMapIdle","selectMapLibraryStatus","mapLibraryStatus","isMapLibraryFetching","isMapLibraryLoaded","isSearchWithinMapEnabled","mapMarkers","selectedNearbyListingCarousel","nearbyListingsCarousel","selectedNearbyListingsCarouselStatus","nearbyListingsCarouselStatus","selectZoomLevel","selectSitePlans","selectInteractiveSitePlans","interactiveSitePlanState","selectTrackedInteractiveSitePlans","loadedInteractiveSitePlans","selectLotNumber","selectLotId","selectLotCommunityId","selectAvailablePlans","selectAvailableSpec","selectLotStatus","selectedLotSummaryCard","interactiveSitePlanCard","selectedLotSummaryCardStatus","selectNearbyListingsCarouselStatusAndMarkerData","selectLotInformation","selectLotCommunityIdAndSitePlans","selectHoveredMarker","selectFocusedListing","selectGeoCoordinatesAndLocation","selectSearchMapTrackingCommonProperties","selectedMarkerAndPage","selectSitePlansProperties","selectMarkersAndSitePlans","selectFocusedListingAndSitePlans","selectAllPlansAndSpecsIds","allPlanIds","allPlans","searchCommandData","Location","HousingDevelopmentMarker","housingInformation","geoId","GeoId","detailText","DetailText","IsBasic","Latitude","Longitude","priceText","PriceText","shortPrice","ShortPrice","totalPlans","TotalPlans","priceReducedText","PriceReducedText","priceReducedTrackingLabel","PriceReducedTrackingLabel","BuilderId","isCallForPrice","IsCallForPrice","Page","priceLow","PriceLow","priceHigh","PriceHigh","hasInteractiveSitePlan","HasInteractiveSitePlan","sitePlanCenterlatitude","SitePlanCenterLatitude","sitePlanCenterlongitude","SitePlanCenterLongitude","getMarkerText","getInteractiveSitePlanSection","getCardElement","hoverCard","getMarkerStyles","getFacts","getHtmlPinElement","getCardElementWithPriceReduction","isPaid","getCard","htmlPinElement","cardElement","getMarkerIcon","getShortPriceIconSection","base","setMarkerInformation","arrow","hoverArrow","BuildablePlanMarker","IsBl","getMarkerTextNode","PlanUnitMarker","previousPriceText","PreviousPriceText","getCardElementDefault","SpecUnitMarker","mapStateSlice","distinctHousingDevelopments","CommunityResults","allHousing","buildablePlans","interactiveSitePlanHomes","Plans","housingDevelopments","featuredPlans","getAllBuildablePlans","filterPlansFromBuildablePlans","Specs","isCommunitiesSearch","communityMarkers","i","sourceMarker","updatePageNumberOfMarkers","mapLibraryFetch","updateInteractiveSitePlanLoadingStatus","markersLoadingStatus","interactiveSitePlanSlice","existingIndex","markerConfiguration","viewedPlanMarkers","viewedSpecMarkers","viewedCommunitiesMarkers","isHousingDevelopmentViewed","isSpecViewed","isPlanViewed","saveCommunityMarkerViewed","saveViewedMarker","saveSpecMarkerViewed","sessionStorage","setItem","markersFromSession","markersViewed","loadViewedMarkers","isNumber","BasicCommunitySummaryCard","CommunityProjectType","emitCtaClickEvent","clickTarget","callToActionClickEvent","callToAction","emitLinkClickEvent","linkClickEvent","getPrice","Key","MarketId","BrandName","BuilderRating","PriceReductionLabel","IsLimited","BasicContactVendorName","MarketName","StateAbbreviation","StateName","FromPage","BasicPlanSummaryCard","getSquarefeet","SquareFeet","getSpecifications","Bedrooms","Bathrooms","CommunityName","StatusLabel","BasicSpecSummaryCard","Normal","Modular","Condo","TownHome","MasterPlanned","CustomLocation","SBC","CST","BYL","MFR","CON","ADU","THM","MPC","CSL","PaidCommunitySummaryCard","IsPriceReduction","getCallToAction","getBuilder","getLeadGeneratorOpener","getCallToActionButton","calltoAction","opener","PaidPlanSummaryCard","PriceReduced","CommunityStatus","PaidSpecSummaryCard","image","getCardInstance","combineAndSortListings","combinedListings","sortedIds","resolve","then","ok","blob","reader","FileReader","onloadend","readAsDataURL","catch","SitePlanTooltip","sitePlanCenterLatitude","sitePlanCenterLongitude","getPriceText","getDetailText","FormattedBedrooms","FormattedBathrooms","getPriceReducedText","formattedBedrooms","formattedBathrooms","priceReduced","getSitePlan","sitePlanInformation","sizeDeviceMap","getDeviceType","getActiveMarker","mapId","communityMarker","getInteractiveOverlay","rotationCenterX","rotationCenterY","svgContent","communityMapInteractive","getLotPathFromCoordinates","svg","elementsFromPoint","clientX","clientY","idMatch","match","getInteractiveMap","mapOverlays","candidate","interactiveMap","mapOverlay","originalTransform","transform","removeProperty","pathElement","siteplanSvg","point","createSVGPoint","transformMatrix","getScreenCTM","inverse","transformedPoint","matrixTransform","isPointInFill","isMouseOnSitePlan","isInteractive","isUserInteractingWithSitePlan","hideSitePlansTooltips","sitePlanTooltipId","removeActiveSitePlans","activeMap","communityMapWrapperId","onMouseLeaveSitePlan","onMouseHoveringInteractiveSitePlan","mouseMoveInformation","onMouseHoveringStaticSitePlan","mapRect","mouseX","mouseY","mapOffsetTop","offsetTop","onMouseMoveSitePlan","buttons","onDoubleClickSitePlan","activeMarker","onClickCommunityStaticMap","onClickSitePlan","latLng","onClickCommunityInteractiveMap","getSitePlanWrapper","mapWrapper","newMapWrapper","isInteractiveCommunity","polygonsContainerCommunityId","getCommunityStaticMapContainer","base64image","sitePlanWrapper","getSvgContent","svgUrl","btoa","unescape","encodeURIComponent","communityMapId","imgElement","createSVGGroup","svgDocument","lotType","createElementNS","setGroupAttributes","inactiveGroup","hoveredGroup","commonAttributes","setAttributes","layerStylingCallbacks","svgElement","paths","firstPath","otherPaths","getInteractiveSitePlanLayers","svgLayers","loadedLayers","layersToFetch","SvgLayerType","fetchPromises","svgContents","interactiveLayers","clipPathElement","parseSVG","Order","lotPolygonsGroup","groups","createLotPolygonGroups","sourceGroup","targetGroup","moveElementsToGroup","parentGroup","appendGroups","img","styledSvg","getCommunityInteractiveMapContainer","mainSitePlanWrapper","polygonsSvgNode","mainPolygonsContainer","polygonContainerId","appendSitePlanContainerToMainWrapper","getSitePlanTooltip","tooltipInformation","firstValueFrom","sitePlanTooltip","tooltipNode","communityMapTooltipId","sitePlanTooltipContainer","tooltipContainer","unsubscribe","drawSitePlan","southWestPoint","northEastPoint","isSitePlanVisible","handleSitePlanVisibility","overlaySvg","applySitePlanStylesOnDraw","centerX","centerY","searchSitePlans$","createClickObservable","sitePlanImage","expectedClickCount","mouseDown$","mouseUp$","startEvent","startX","startY","endEvent","endX","endY","abs","buffer","clicks","cssClassesToApply","paid","spotlight","noPrice","getStateClasses","markerTypeClasses","classesToReturn","analyticsInstance","isAnalyticsScriptLoaded","isAnalyticsScriptLoading","loadingAttemps","onAnalyticsError","reject","console","log","Error","onAnalyticsLoaded","isAnalyticsLoaded","appendAnalyticsScript","analytics","initialize","invoked","methods","factory","e","t","call","arguments","unshift","load","n","getElementsByTagName","insertBefore","_loadOptions","_writeKey","SNIPPET_VERSION","getSegmentApiKey","loadAnalytics","analyticsLoaded","analyticsErrored","segmentAnalyticsLoaded","segmentAnalyticsErrored","segmentTrack","segmentImpression","segmentIdentify","segmentPageView","SegmentEventType","Track","Impression","Identify","PageView","queue","IdleQueue","ensureTasksRun","startTime","pushTask","trackEvent","hitTypeHandlers","identify","userId","traits","pageview","track","alias","previousId","reset","isTimeExpired","hitType","eventDefinition","nextState","DateExtensions","dateString","toLocaleDateString","month","day","year","getCategory","getProperties","getOptions","getCommonProperties","getTrackCommonProperties","marketNameProperty","trackCommonProperties","market_id","market_name","brand_id","brand_name","page_type","pageType","code_version","buildCodeVersion","test_version","testVersion","response_version","responseVersion","partner_id","partnerId","partner_name","partnerName","brand_partner_name_partner_name","brandPartnerName","checkEmptyArray","getIdentifyProperties","savedElements","favorites","obj","savedDate","formatDateFromStringTimestamp","dateChanged","favoriteType","dateSaved","homeId","builderInfo","getUserSavedElements","identifyCommonProperties","user_id","first_name","last_name","userZip","outside_us","saved_communities","saved_homes","saved_builders","g_client_id","neustarSegment","n_segment","n_zip","neustarZip","n_year","neustarAge","n_gender","neustarGender","getMoveInDate","moveInInformation","getSearchLocation","locationInformation","searchLocationLabelDictionary","getMasterBedLocationLabel","bedroom","formatFiltersApplied","facets","moveIn","price_high","price_low","single_family","luxury_homes","condo_townhome","living_areas","master_bed_location","gated","golf_course","nature_areas","sports","hot_deals","price_reduction","listings_hoa_info","age_restricted","rv_garage","school_district_ids","move_in_date","mfr","search_location","facetsEntriesValues","facet","activeFacet","facetValue","getImpressionProperties","impressionCommonProperties","searchLocation","filters_applied","result_count","current_page_number","getImpressionBaseProperties","last_event","createIdentifyEvent","impressionProperties","createImpressionEvent","createPageEvent","isInProgress","end","speedCurveTrackConversion","speedCurveMarkStart","speedCurveMarkEnd","speedcurveTimingMetric","LUX","addData","mark","markNameEnd","measure","measureName","markNameStart","getMeasureName","getMarkNameStart","getMarkNameEnd","SpeedcurveEventType","Conversion","MarkStart","MarkEnd","TimingMetric","trackConversion","createTrackConversion","markStart","createTrackMarkStart","markEnd","createTrackMarkEnd","timingMetric","createTrackTiming","speedcurveState","totalDeliveryEvents","param","getAttributes","datasets","fireTdvEvent","trackingEvent","isFetchingEvent","trackingEventError","trackingEventFulfilled","totalDeliveryValueActions","totalDeliveryValueReducers","totalDeliveryValue","eventTracking","postPlanLogger$","postSpecLogger$","postCommunityLogger$","freeze","isMobileUserAgent","userAgent","selectTrackingCommonProperties","userLocation","utm","userLocationCity","userLocationCountry","userLocationMarketId","userLocationState","userLocationZipCode","referCode","refer","businnessInformationElement","businnessInformation","trackingCommonPropertiesFromStore","getCommonPropertiesFromStore","trackingCommonPropertiesFromOtherSources","isMobileDevice","getCommonPropertiesFromOtherSources","listingInformationGetter","marketingStatusLabel","getCardInformation","pathname","getListingInformation","getListingInformationFromDataset","toggleFavorite","cardInfo","isSaved","favorite","isFavoriteSaved","deleteFavorite","saveFavorite","dispatchSaveOrDeleteAction","updateSavedFavorites","favoritesIds","pendingSaves","pendingSave","isLogin","googleOneTapInstance","isGoogleOneTapLoaded","isGoogleOneTapLoading","clientId","onAuthenticated","onGoogleOneTapError","onGoogleOneTapLoaded","google","accounts","client_id","cancel_on_tap_outside","itp_support","use_fedcm_for_prompt","appendGoogleOneTapScript","script","defer","onload","token","base64","jsonPayload","decodeURIComponent","atob","character","charCodeAt","authActions","onLibraryLoaded","googleOneTapLibraryLoadingStatus","onLibraryErrored","onPageLoaded$","googleResponse","idToken","credential","locale","givenName","given_name","familyName","family_name","subject","sub","audience","aud","emailVerified","email_verified","notBeforeTimeSeconds","nbf","hostedDomain","hd","issuer","iss","issuedAtTimeSeconds","iat","expirationTimeSeconds","exp","jwtId","jti","keepMeLogged","Success","reload","googleOneTapConfiguration$","googleOneTapInformation","googleOneTapConfiguration","prompt","cancel","signUpField","regex","validator","hint","valid","configElement","keepMeLoggedSection","legalContentSection","configObject","additionalSignUpFields","modalActions","modalReducers","authenticationReducers","onCloseModal","onClose","localStorage","authenticationActions","onAuthLibraryLoaded","authLibraryLoaded","onAuthLibraryErrored","authLibraryErrored","openModal","onOpen","isSignInElement","onOpenModal","updateNeustarInformation","partnerIdElement","getCookieName","isPartnerCookie","documentClicks$","debounce","interval","sessionAliveElement","sessionAliveMin","updateSession","cookieName","items","cookie","nameLength","cookieFound","readCookie","mins","expires","setTime","getTime","toGMTString","createCookieByMins","componentLinksToInclude","subMenuAccountList","subMenuAccountContainer","links","link","component","li","ShouldOpenNewTab","signInToggle","isAuthLibraryLoaded","authentication","isAuthLibraryNotLoaded","isAuthModalOpen","pendingSavesSessionStorageKey","favoritesSessionStorageKey","FavoriteType","Plan","Spec","Builder","builder","userProfileActions","userProfileReducers","matcher","deleteFavoriteFullfilled","saveFavoriteFulfilled","selectIsLoggedIn","selectFavorites","selectPendingSaves","selectIsProfileFavoritesLoaded","isProfileFavoritesLoaded","selectUserId","selectNeustarStatus","neustarStatus","selectGoogleOneTapLibraryLoadingStatus","selectUserIdAndPendingSaves","selectUserLocation","userCity","userCountry","userMarketId","userState","userZipCode","selectUserProfileTrackingCommonProperties","neustarInformation","s","z","g","pendingSavesData","getItem","favoritesData","userProfileSlice","apply","profile","imageProfile","isLoading","applyFavorites","update","userInfo","handleError","newFavorite","authenticationSlice","modalSlice","utmParameters","selectUtmTrackingCommonProperties","updateDataLayer","dataLayer","PageLayout","BoylLocations","ManufacturedLocations","ResultPresentationType","Pagination","InfiniteScrolling","LayoutBreakpoint","Small","Medium","Big","mediaQuery","getMediaQuery","selectUiState","selectDisplaySkeleton","displayCardGridSkeleton","selectResultsPresentationType","resultsPresentationType","selectModal","selectLoading","selectConfigurationSegmentApiKey","segmentApiKey","selectConfigurationImageResizeService","imageResizeService","selectConfigurationGoogleOneTapClientId","googleOneTapClientId","selectIsMarkerAutoScrollFeatureEnabled","isMarkerAutoScrollFeatureEnabled","selectLayoutBreakpoint","selectResourcesHostNames","resourceDomain","staticImagesHostName","lookup","layoutName","updatePageLayout","pageLayout","updateCardGridSkeleton","previousName","newModalInformation","updateLayoutBreakpoint","trackUserEvent","getMessage","asObservable","sendMessage","onHtmlReady","onHtmlRemoved","setHtml","setPreviousHtml","global","AppNexus","apntag","baseUrl","CONFIGURATION","constants","ASTURL","PARAMETERSURL","HTMLDIVPREFIX","MEMBERID","SKINADID","constantName","isAstLoaded","isAstLoading","areParametersDefined","loadAdsEvent","createEvent","atsLoadedEvent","onParametersLoaded","nativeAdTemplates","getNodeIdsFromSelectors","selectors","accumulator","concat","getIdsFromElements","getUtCallGroups","isNaN","groupsAsQuerySelector","requestHttpGet","request","XMLHttpRequest","send","replaceTemplateContent","template","clone","alt","sponsoredBy","clickUrl","cta","createNativeAd","native","nativeAdKey","targetId","impressionTrackers","clickTrackers","jsTrackers","iframeForNativeAd","cssForIframe","circularFontPath","souvenirFontPath","styleElement","iframeStyles","Image","contentWindow","exec","javascriptTrackers","scr","bindEventsToNativeAdCard","loaded","_omit","original","undesiredKeys","clonedObject","_ajaxRequest","_dispatchAdParametersStartEvent","xmlHttpRequest","onreadystatechange","readyState","responseText","_dispatchAdParametersEndEvent","setRequestHeader","_astAdAvailableHandler","adType","_astAdNoBidHandler","_printAdInformation","_dispatchAdRequestEndEvent","noRemove","_astGlobalOptions","setPageOpts","member","disablePsa","_astDefineTag","divElementId","nativeLayouts","allowedFormatsArray","keywords","isNativeSupported","currentPlacement","placements","max_length","ref","defineTag","tagId","sizes","allowedFormats","customIframeProps","showTag","_executeRequestToAppNexus","_createAppNexusRequest","overwriteAds","elementId","appNexusRequests","adElements","indexA","indexB","internalNativeAdTemplate","offsetParent","anq","loadTags","_astAdLoadedHandler","_astLoadedCallback","onEvent","_attachEventToLoad","object","attachEvent","_loadAstScriptAsync","_dispatchAdsScriptStartEvent","tag","_dispatchAdsScriptEndEvent","protocol","_adParametersLoadedCallback","_adParametersLoadedAndRefreshCallback","refresh","utCalls","adIds","useLazyLoad","clearRequest","setKeywords","override","fastdom","mutate","utCall","_printInformation","time","info","performance","_dispatchAdRequestStartEvent","_loadAds","escape","params","paramname","skinAd","refreshAd","refreshAllAds","refreshAllAdsAndUpdateParams","deleteAdOnDemand","requests","tags","deleteAdsOnDemand","tagsId","generateAllAds","regenerateAdCalls","overwrite","createAdOnDemand","randomNumber","floor","random","deleteAdsBySelector","nativeIds","div","initEvent","createRequestsCallback","nativePosition","iframeBody","clickAdFunction","j","refreshAds","refreshAdsAndUpdateParams","refreshAdByName","regenerateAds","loadAdOnDemand","deleteAdByTagName","deleteAllAdsBySelector","authObject","isAuth0Loaded","isAuth0Loading","lock","settings","Auth0Lock","onAuth0Error","onAuth0Loaded","loadAuth0Module","isAuthLoaded","onSignUpReady","onkeypress","evt","charCode","which","keyCode","outsideUS","onchange","prefill","lastElementChild","after","authResult","accessToken","keepMeLoggedValue","auth0Authenticated","afterLogin","nextPage","onSigninReady","referenceElement","loadAuth0","authLoaded","authError","createAuthInstance","auth0ClientId","auth0Domain","showModal","show","mapInstance","isGoogleMapLoaded","isGoogleMapsLoading","markersHashed","interactiveMarkersOverlays","mapCursor","pointer","grab","grabbing","googleMapsSource","onGoogleMapsError","onGoogleMapsLoaded","appendGoogleMapsScript","initMap","isGoogleMapsLoaded","createMarkerHashedKey","toFixed","cloneAndAppendTooltipToAdvanceMarker","destinationMarker","hashMarker","advancedMarker","markersOnThisPosition","markerToolTips","firstTooltip","otherTooltips","clonedFirstTooltip","setMultipleInformationInSingleMarker","setMarkerVisibility","position","collisionBehavior","maps","CollisionBehavior","OPTIONAL_AND_HIDES_LOWER_PRIORITY","REQUIRED","onMapVisibilityChange","intersectionRatio","loadGoogleMaps","googleMapsLoaded","googleMapsErrored","createMapInstance","addListenerOnce","mapInitialInformation","getZoom","addListener","newZoom","isZoomIn","mapObserver","removeMarkers","paintMarker","AdvancedMarkerElement","gmpClickable","createMarker","updateBoundaries","hasOwnProperty","LatLngBounds","southwestPoint","LatLng","extend","northeastPoint","fitBounds","updateMarkersVisibility","markerA","markerB","updateMapCenter","setCenter","showMarkers","markerToShow","hideMarkers","markerToHide","setMap","updateMinimumZoomLevel","newZoomLimit","doesZoomLevelNeedToBeUpdated","setOptions","setZoom","dispatchCustomEventOnDocument","eventDetail","drawBoundary","boundaryUrl","KmlLayer","suppressInfoWindows","preserveViewport","getDefaultViewport","getStatus","addOverlay","panes","getPanes","mainWrapper","overlayLayer","overlayMouseTarget","mapPane","isSitePlanInViewport","intersects","overlayBounds","isSitePlanIntersectingMapBounds","sitePlanBounds","drawOverlay","overlayProjection","getProjection","fromLatLngToDivPixel","removeOverlay","createSitePlanOverlay","overlayView","OverlayView","communityMapUrl","draw","removeSitePlanOverlay","getSitePlansOutOfViewport","toggleDoubleClickZoom","isDoubleClickZoomEnabled","addOverlayMarkers","markerLayer","drawOverlayMarkers","createInteractiveSitePlanMarkersOverlay","removeInteractiveMarkersOverlay","setZoomLevel","changeMapCursorPointer","cursorOption","draggableCursor","locationChanged$","paginationChanged$","housingTypeChanged$","countsChanged$","countiesChanged$","Value","leadModalOpened$","priceReductionLabel","leadModalClosed$","searchEvents","searchRefinement","priceChanged","getPriceAction","getPriceLabel","bedChanged","bathChanged","customHousingBoxClick","manufacturedHousingBoxClick","builderChanged","livingAreasChanged","storiesChanged","primaryBedroomChanged","garagesChanged","searchChanged","filterLabelDictionary","filterSelected","schoolsChanged","amenitiesLabelDictionary","amenitiesChanged","amenitiesSelected","sortSelectOpt","sortChanged","sortingValue","sortingOption","homeTypeLabelDictionary","homeTypeNameDictionary","homeTypeChanged","homeTypeName","moveInLabels","moveInChanged","urlChange","routing","favoritesSaved","housingProductType","getFavoriteGoogleAnalyticsEvent","getGoogleAnalyticsDTO","uiStateActions","getURL","urlComponents","pageNumberChanged","pageSizeChanged","pagingControlsClickPrevious","pagingControlsClickNext","backToTopButtonElement","clickBackToTop$","scrollTo","initBackToTopElement","listViewContainer","containerClick$","isBrandCard","isBasicBrandCard","doesCardPointToReviewsBuilderShowcasePage","isViewHomesLinkClick","isViewCommunitiesLinkClick","isBrandNameLinkClick","isBrandLogoLinkClick","hasAboutPage","addCustomDimensions","emitGoogleAnalyticsEvent","dimensions","isLearnMoreLinkClick","cardClick$","reviewsCardClick$","viewHomesClick$","viewCommunitiesClick$","emitFetchBrandAction","resultTypeRedirect","productTypeRedirect","locationTypeRedirect","searchParametersState","suggestedResultsCard","redirectClickEventToUrl","pageLayoutDivContainer","lastValue","lastPageLayoutName","newPageLayoutName","newLayoutClass","layoutClassToRemove","excludeForms","isNoResultsPage","siteLinksEventName","buyingGuideEventsName","pageWindowClick$","recommendationLinkDetailClick$","listViewSection","listViewSectionClicks$","cardFavoriteButtonSelector","noResultsListingLink","noResultsClearButton","paidMasterPlanCommunityCardSelector","basicListingCardSelector","paidCommunityCardSelector","paidPlanCardSelector","paidSpecCardSelector","basicCommunityCardSelector","basicPlanCardSelector","basicSpecCardSelector","defaultMarketingStatus","paidBuilderCardSelector","basicBuilderCardSelector","brandNameLink","viewCommunitiesLink","viewHomesLink","brandLogoLink","reviewsArea","learnMoreLink","paginationSection","paginationSectionClicks$","pageSizeElement","pageSizeChange$","popularSearchSection","popularSearchSectionClicks$","marketSnapshotsSection","marketSnapshotsSectionClicks$","geoLocationSearchSection","geoLocationSearchSectionClicks$","paidCommunityAndPaidLocationSelector","paidPlanSelector","paidSpecSelector","basicCommunityAndBasicLocationSelector","basicPlanSelector","basicSpecSelector","areaClickedPerCardElement","planName","specAddress","seoContentSection","seoContentSectionClicks$","click_target","search_value","previousElementSibling","click_target1","googleAnalytics4","getPaidBuilderCardProperties","is_paid","cardDataset","elementName","destination","paidBuilderCardClickedArea$","triggerBuilderPaidCommunitiesClickEvent","triggerBuilderPaidLogoClickEvent","getBasicBuilderCardProperties","cardLinkElement","isPriced","getPosition","getPaidCommunityCardProperties","trustbuilder_reviews","hasBuilderReviews","min_price","max_price","market_session","community_name","community_status","community_id","is_limited_availability","hasLimitedInformation","is_priced","zip_code","builder_id","builder_name","is_spotlight","getBasicCommunityCardProperties","getPaidPlanCardProperties","plan_id","home_status","is_spec","is_plan","getPaidSpecCardProperties","spec_id","getBasicPlanCardProperties","getBasicSpecCardProperties","getBasicListingCardProperties","listing_id","getClickTargetText","isMapCard","srpClickTargetText","clickEvent","anchorLink","anchorText","is_zero_results","filter_name","cardAreaClicked","isNoResults","favoritedInformation","itemId","event_type","currency","MarketingStatusLabel","HasBuilderReviews","HasLimitedInformation","buttonDataset","button_name","buttonAction","detailAnchorClicked$","getRealtorQuestionAnswerText","realtorSelect","realtorQuestionAnswer","triggerPaidCommunityModalSubmitted","realtor_question","triggerPaidPlanModalSubmitted","triggerPaidSpecModalSubmitted","org_button_name","summaryCardCta","skipModalRecommendedCommunitiesClick$","closeModalRecommendedCommunitiesClick$","getCustomPropertiesByType","modalInfo","customPropertiesByType","footerLinks","footerLinksClicks$","clickedLinkFooter","footer_55_plus","footer_condos_townhouses","footer_custom_homes_center","footer_first_time_homebuyers","footer_luxury_homes","footer_modular_homes","footer_learning_center","footer_ratings_and_reviews","footer_real_estate_professionals","footer_livabl","footer_houseplans","footer_casas_nuevas","footer_start_fresh_buy_new","footer_about_us","footer_contact_us","footer_list_your_homes","footer_unsubscribe","footer_accessibility","footer_terms_of_use","footer_privacy_policy","footer_site_help","footer_do_not_sell_my_info","footer_facebook_link","footer_pinterest_link","footer_twitter_link","footer_youtube_link","footer_instagram_link","footerLink","nameLinkClicked","eventNameLinkClicked","logoHeaderElement","metroAreaLinksContainerElement","metroAreaLinkClick$","homesByStateLinksContainerElement","homesByStateLinkClick$","triggerFindAHomeLinkClickEvent","clickedElement","sectionName","resourcesContainerElement","resourceLinkClick$","advertisingLinkElement","advertisingLinkClick$","navLinksEventNames","navLinksNames","triggerHeaderLinkClickEvent","navLinkValue","navLink","signInClickTargetValue","signEventNames","signOptionSelected","provider","mapContainerElement","mapClick$","mapToggleButtonElement","mapToggleButtonClick$","toggleClickTargetValues","list","elementState","zoomButton","mapContainerTouchstart$","mapContainerTouchend$","mapZoomChange$","mapPinchStart$","touchstartEvent","touches","mapPinchEnd$","touchendEvent","mapPinch$","lastPinchEvent","mapZoomChangeEvent","mapWheel$","delay","lastMapZoomEvent","lastMapWheelEvent","maxTime","timeStamp","facetPanel","facetPanelClicks$","getPropertiesFacets","panelOption","searchInformation","current_location","priceContainer","fromEventPattern","newValues","trunc","bedFilter","bathFilter","panelBathChange$","panelBedChange$","homeFacts$","homeFact","moveInDateFilter","sortChanged$","sortSelectElement","getSortingLabel","sortingInformation","allFiltersPanel","allFiltersPanelChanges$","getParametersActive","activeFilters","getOthersproperties","otherProperties","facetsSelector$","facetsData","home_type","school_districts","primary_bedroom","other_features","other_filters","popularPillsFilters","popularPillsFiltersClicks$","getPopularPillsAppliedProperties","popularPillsSelector$","filtersPopular","communityStaticMap","hover_duration","device_type","redirected_to","zoom_level","current_card_position","next_card_position","ImpressionEventObserver","callbackOnIntersection","intersectionObserver","intersectedElement","getIntersectionObserver","paidBuildOnYourLotCommunityCardSelector","paidCustomCommunityCardSelector","paidManufacturedCommunityCardSelector","basicBuildOnYourLotCommunityCardSelector","basicCustomCommunityCardSelector","basicManufacturedCommunityCardSelector","basicCustomPlanCardSelector","basicCustomSpecCardSelector","basicBuildOnYourLotPlanCardSelector","basicBuildOnYourLotSpecCardSelector","paidManufacturedPlanCardSelector","paidManufacturedSpecCardSelector","basicManufacturedPlanCardSelector","basicManufacturedSpecCardSelector","paidCustomPlanCardSelector","paidCustomSpecCardSelector","paidBuildOnYourLotPlanCardSelector","paidBuildOnYourLotSpecCardSelector","cardfavoriteButtonSelector","customAndBuildOnYourLotHomesSelectors","customAndBuildOnYourLotCommunitiesSelectors","isNotResultPage","segmentAreaClickedPerCardElement","ratingsScore","getCardImageUrls","imageElements","primaryImage","secondaryImage","terciaryImage","getLeadButtonClickedCommunityCustomProperties","primary_image_url","community_low_price","community_high_price","button_action","community_type","communityType","paidCommunityLeadButtonClicked$","paidCustomCommunityLeadButtonClicked$","paidBuildOnYourLotCommunityLeadButtonClicked$","paidManufacturedCommunityLeadButtonClicked$","basicCommunityLeadButtonClicked$","basicBuildOnYourLotCommunityLeadButtonClicked$","basicCustomCommunityLeadButtonClicked$","basicManufacturedCommunityLeadButtonClicked$","cardImages","area_clicked","image_1_url","image_2_url","image_3_url","newFavoritedItems","typeCard","getLeadButtonClickedHomesCustomProperties","primaryImageUrl","home_price","paidPlanLeadButtonClicked$","paidSpecLeadButtonClicked$","paidManufacturedPlanLeadButtonClicked$","paidManufacturedSpecLeadButtonClicked$","paidCustomPlanLeadButtonClicked$","paidCustomSpecLeadButtonClicked$","paidBuildOnYourLotPlanLeadButtonClicked$","paidBuildOnYourLotSpecLeadButtonClicked$","basicPlanLeadButtonClicked$","basicSpecLeadButtonClicked$","basicManufacturedPlanLeadButtonClicked$","basicManufacturedSpecLeadButtonClicked$","basicCustomPlanLeadButtonClicked$","basicCustomSpecLeadButtonClicked$","basicBuildOnYourLotPlanLeadButtonClicked$","basicBuildOnYourLotSpecLeadButtonClicked$","basicListingLeadButtonClicked$","paidPlanCardClicked$","paidSpecCardClicked$","manufacturedPlanCardClicked$","manufacturedSpecCardClicked$","paidCustomPlanCardClicked$","basicListingCardClicked$","basicPlanCardClicked$","basicSpecCardClicked$","foundSelector","filterFavoritedByType","manufacturedHomeSpecPendingFavoritesChanged$","manufacturedHomePlanPendingFavoritesChanged$","itemType","newCommunityListingSaved$","favoriteInformation","newPaidSpecListingSaved$","removedCommunity$","triggerHomeRemovedEvent","removedSpecHome$","removedPlanHome$","nearbyListings","Images","Srcset","newPaidPlanListingSaved$","sort_value","tabsContainer","tabsContainerClicks$","homesButtonClicks$","communitiesButtonClicks$","onUrlChange$","onHousingProductLocationFetchStatus$","countsChange$","housingProductFetchStatus","triggerRecommendedCommunitySubmittedEvents","ImageUrl","triggerPaidHomeModalSubmitted","triggerBasicHomeModalSubmitted","housingProductStatus","triggerIdentifyCommunityModalSubmission","triggerIdentifyHomeModalSubmission","triggerIdentifyRemovedHomeFavorite","isAutoScroll","selectedMarkerInformation","paidCommunityResultsDisplayedEventObserver","viewedCard","secondaryImageUrl","tertiaryImageUrl","is_auto_scroll","basicCommunityResultsDisplayedEventObserver","bindBasicCommunityResultsDisplayedEvents","basicCommunitiesListings","basicCommunityContainerObserver","basicSpecListingResultsDisplayedEventObserver","bindBasicSpecResultsDisplayedEvents","basicHomesListingCards","basicSpecListingContainerObserver","basicPlanListingResultsDisplayedEventObserver","bindBasicPlanResultsDisplayedEvents","basicPlanHomesListingCards","basicPlanListingContainerObserver","basicListingResultsDisplayedEventObserver","bindBasicListingResultsDisplayedEvents","basicListingCards","basicListingContainerObserver","bindPaidCommunityResultsDisplayedEvents","paidCommunityListings","communityContainerObserver","resultsChanged$","paidHomeResultsDisplayedEventObserver","homeType","bindPaidHomeResultsDisplayedEvents","paidHomeListingCards","homeContainerObserver","plan_name","spec_name","isLuxDefined","startSpeedcurveTracking","luxLabel","init","speedcurveStateActions","onMapLibraryStatusChange$","onMapResultsChange$","scriptResources","linkResources","fontResources","scripts","fonts","resources","getEntriesByType","speedcurveResources","duration","getKeyAd","markStartEvent","trackListViewLoaded","tabContainer","tabsClicks$","listViewLoaded$","measureListViewOnTabsInteraction$","resultsModifiers$","measureListViewOnFiltersIteraction$","measureListViewOnLocationIteraction$","measureNames","pathname$","onPageLoadedOnAjax$","markLoadTime","newPageSize","disableMapSearch","fetchSearchWithinMapResults","searchWithinMapCheckboxClicks$","previousLocationType","isMapLibraryLoaded$","onNewCoordinates$","prevCoordinates","currentCoordinates","sortElement","onResultsTypeChanged$","onlyResultTypes","synchronizeSortElement","sortElementValue","panelsElements","isBuildersResultType","onResultTypeChange$","NewHomeSource","queryScript","eventToAttach","TrustedForm","executeMethod","MutationObserver","mutations","mutation","addedNodes","disconnect","childList","subtree","characterData","tf","trustedForm","currentLocationSearchSettings","mapViewButton","toggleCurrentLocationSearchFlag","handleLocationPermissionGranted","geolocation","coords","handleLocationPermissionDenied","errorContainer","isMapReady","geographicCoordinates","matches","getCurrentPosition","toggleButton","toggleButtonHandler","menuToggle","isOpen","findAHomeSubmenu","resourcesSubmenu","accordionToggleHandle","menu","isSameNode","resourcesHostNames$","getLifeStyleImage","generateRandomNumber","onErrorImage","resourcesHostNames","removeSource","imageSrc","getBrandLogoPlaceholderImage","handlerErrorInLazyImages","first","imageWithError","handlerErrorInEagerImages","handlerError","selectedMarkerId","getDataset","trackEvents","firedCommunitiesResultsEvents","firedHomesResultsEvents","firedMasterPlanEvents","resultsContainer","isNoResultSectionVisible","hiddenSections","fetchListingStatus","onResultLoad$","loadResults","footerAds","hideFooterAds","previousPaging","refreshOrRegenerateNativeAds","currentResultType","currentPaging","locationChanged","resultTypeChanged","pagingChanged","nativeInformation$","nativeInformation","onFiltersApplied$","filtersApplied","filtersHintsSection","noFiltersHintsSection","filtersAppliedCount","supportedLocationTypes","actionOnActiveHotDeals","isActive","actionOnInactiveHotDeals","updateCondosAndTownhomes","actionOnActiveCondosAndTownhomes","actionOnInactiveCondosAndTownhomes","actionOnActiveAdult","actionOnActiveComingSoon","actionOnActiveFloorPlans","actionOnActiveQuickMoveIns","actionOnInactiveAdult","actionOnInactiveComingSoon","newMarketingStatus","actionOnInactiveFloorPlans","actionOnInactiveQuickMoveIns","pillsByUrlSubdirectory","onActiveAction","onInactiveAction","getPillsByCounts","pillsWithCounts","pillsDetails","getPopularSearchesPillsForUrlSubdirectory","pill","isEnabled","secondPill","firstPill","Pill","closeSmallIconSvgElement","getClose","check","pillNode","uncheck","PillsSection","popularSearchesPillsSelector","popularSearchesPills","pills","marginLeftArrowClass","pillsList","scrollLeftButton","scrollRightButton","scrollHorizontally","updateChildElementsVisibility","setRigthLimit","attachPillListEvents","onResize$","updatePillsOnDOM","popularPillFilters","getHtmlPills","updatePillStatus","getActivatedPillsText","requestAnimationFrame","limitRight","pillFilters","activedPills","inactivedPills","getPillsStatus","activePills","inactivePills","pillType","popularSearchesPillType","isChecked","hide","amount","initialScrollLeft","scrollLeft","targetScrollLeft","step","currentTime","elapsedTime","easeInOut","isListScrolledRight","visibility","initialValue","changeValue","transitionDuration","newTime","click$","fetchAction","getPillAction","pillsSection","activatedPillsText","eventCategoty","popularPillsDetails","priceHighLink","urlUpdateInformation","ResultTab","setIsActive","getHTML","activeClass","qaAttribute","defaultTabs","googleAnalyticsTrackingClass","tabCLass","resultTypeChange$","updateUrlSegments","urlConfiguration","tabElement","classesList","googleAnalyticTrackingClass","componentsUrl","customAndBuildOnYourLotTabs","ManufacturedTabs","resultTabConfigurationMapper","productTypeName","customboyltab","resultTypeName","resultTabContainerElement","onTabChanged$","tabs","resultType$","pageLayoutName","types","sibling","resultTabsChanged$","newTabs","removeChild","removeAllTabs","tabConfiguration","tab","observableObserver","infiniteScrollTrigger","fetchNextResults","fetchResultListingStatus","observable$","onReadyToFetchNewResults$","resultPresentationType","complete","listViewContainerSelector","skeletonCustomDataValue","containerSelector","cardCount","create","getCardSkeleton","skeletonElements","getSkeletonCardNodes","destroy","getCardHtml","shouldDisplaySkeleton","shouldCleanUpContainer","displaySkeletonInformation","housingCardConstructor","getCardGoogleAnalyticsEvent","searchResultsContainer","isLeadOpener","isFavoriteIcon","HTMLAnchorElement","isAnchorElement","leadOpenerClick$","onStandardCardHovered","onSelectedMarkerChange","cardPreviousSelected","cardSelected","block","standardCardElement","cardInformation","leadOpener","searchTerm","suggestList","searchInput","selectedOptionIndex","updateOptionsStatus","activeOptionIndex","ariaSelected","setSelectedOptionInTypeahead","optionIndex","optionSelected","setSelectionRange","scrollToOption","scrollIntoViewIfNeeded","searchObserver","keyHandlers","ArrowDown","optionSize","childElementCount","ArrowUp","Enter","currentSearch","suggestedOption","arrowHandler","toggleErrorMessage","shouldDisplayError","form","suggestionsContainer","currentLocationSearchText","searchText","allowCurrentLocation","searchForm","searchInput$","searchFocus$","clearClicked$","searchEvent$","selectedSuggestion$","keyDownHandler","closeOptions","formOutClick$","hidden","searchInputKeyDown$","insertCurrentLocationOption","displaySuggestions","suggestArr","MarketStateAbbr","optionAdditionalAttributes","CityName","SyntheticGeo","State","MarketStateName","suggestion","userInput","trimStart","isCurrentLocationSelected","startsWith","pipedObservable$","locationIconSvgElement","typeahead$","searchResultContent","mapButtonToggle","listButtonToggle","sortButton","sortButtons","toggleSortVisibility","button","displayValue","btn","onListButtonClick$","onMapButtonClick$","UrlSubdirectoryTypes","CondoDevelopment","SingleFamilyHomes","SingleFamilyCommunities","OnYourLot","CustomBuilders","typeaheadInput","modalTypesForModalSubmissionEvent","markerPinClicked$","communityStaticMapClicked$","communityStaticMapDoubleClicked$","communityStaticMapZoomChanged$","communityStaticMapHovered$","markerSummaryCardClicked$","summaryCardLinkClicked$","summaryCardCtaClicked$","nearbyListingsCarouselScrolled$","carouselCloseButtonClicked$","pendingListingSaves$","previousPendingListingSaves","pendingListingSavesFavorites$","newListingSaved$","previousFavorites","currentFavorites","lastFavorited","newListingSaved","pendingListingSaves","onPendingFavoritesChanged$","newItems","removedFavorites$","prevList","newList","newIds","findRemovedItems","removedItems","paidCommunityModalSubmission$","isMasterPlanCommunity","basicCommunityModalSubmission$","paidMasterPlanCommunityModalSubmission$","recommendedCommunitiesSubmitted$","recommendedCommunitiesSubmittedBasic$","recommendedCommunitiesShow$","paidHomeModalSubmission$","basicPlanModalSubmission$","basicSpecModalSubmission$","basicListingModalSubmission$","paidManufacturedLocationModalSubmission$","paidManufacturedPlanModalSubmission$","paidManufacturedSpecModalSubmission$","paidAskAQuestionLocationModalSubmission$","paidAskAQuestionPlanModalSubmission$","paidAskAQuestionSpecModalSubmission$","urlOpened$","markerUrlOpened$","modalCloseButtonClicked$","onQueryStringChanged$","selectCurrentLocationSearchInformation","selectPopularPillFilters","selectPopularSearchesPills","searchCounts","pillsCounts","urlComponentsWithHomeStatusSelector","selectResultsLoadedAndResultsPresentationType","resultStatusAndResultsPresentationType","selectDisplaySkeletonAndResultsPresentationType","selectPagingAndResultPresentationType","selectPageInformationAndFetchResultsStatus","golfcourse","waterFront","mapCoordinates","activeAdult","appendIfValid","primaryBed","getPrimaryBed","appendMapCoordinates","appendSortingOptions","constructQueryString","selectConstructMinimumRequiredFiltersQueryString","selectCountsAndQueryString","minimumRequiredFiltersQueryString","selectNativeAdInformation","selectSelectedMarker","builderSegment","validLocationTypes","newLocationSegments","getUrlLocationSegments","newUrlCoordinatesQueryString","pageLinkDataSelector","pageCount","currentPage","urlChange$","urlInformation","nextPageUrlComponents","pagingInformation","lastPage","previousPageUrlComponents","pagingBar","newPagingSegment","onUpdateQueryString","newSubdirectory","getPageFromCurrentState","mapPageElement","pageElement","Pager","previousButton","optionListElement","getPageFromState","previousButtonClick$","dataArray","nextButtonClick$","optionClickHandler","previousButtonClickHandler","nextButtonClickHandler","pageChange$","Subject","valuesArray","pageSelected","optionCount","setPageNumber","urlReference","initialData","totalResults","TotalResults","optionList","maximumPagesToShow","changePagination","activePageNumber","updatePageCount","updateUrlComponents","getPagesToShow","build","updatePaginationBarVisibility","updateClasses","activeOption","pages","pagesToShow","pageNumberToRight","pageNumberToLeft","firstPage","pageIndex","threeDotsElement","newPaginationNumberLink","contentFacets","appliedContentFacetList","lastItem","moveInDateContentTemplate","getContentTemplateTypeForMoveInDateFilters","builderContentTemplate","getContentTemplateTypeForBrandFilter","pop","getNextPageUrl","nextPageUrlConfig","hasNextPage","shouldHaveNextPage","getPreviousPageUrl","previousPageUrlConfig","hasPreviousPage","shouldHavePreviousPage","getMapCoordinatesQueryString","ip","getUserProfileUrl","housingProductConstructor","combinedUserProfileEpic","getUserProfile","saveInformation","fav","IsLogin","getUserFavorites","epic$","BehaviorSubject","rootEpic","epic","staticReducers","epicMiddleware","getDefaultMiddleware","asyncReducers","injectReducer","asyncReducer","replaceReducer","combineReducers","run","getTrackerClientId","ga","getAll","getPageType","getEventName","getParams","browsertTimeZone","getTimezoneOffset","utc","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","getMarketSession","getLocation","userStatus","user","brandPartnerNamePartnerName","gaUserId","neustarResponse","search_within_map","page_number","getGoogleAnalytics4Event","customParams","isComingSoon","isCloseOut","isGrandOpening","camelCaseObjectKeys","camelCaseObject","camelCaseArray","camelCaseKey","charAt","module","exports","objectToClean","defaultFormats","webp","jpg","createQueryString","formats","acc","formattedSources","breakpoint","objectEquals","isEqual","getRandomLifestyleImage","irsDomain","StringExtensions","stringObject","nameWithoutSpecialCharacters","removeSpecialCharacters","toKebabCase","wordToRemove","startInIndex","existingString","targetValue","valueArray","hasTargetValue","newValueArray","UrlExtensions","firstSegment","urlWithoutQueryString","parameter","hash","separator","query"],"sourceRoot":""}