PageSourceSearch

https://www.realestateagency.com/myportal/reports

html realestateagency.com collected 2026-10-04 06:06:12 UTC 189,809 bytes, 3,772 lines download raw bytes

1<!DOCTYPE html> <html lang="en"> <head><meta name="description" content=""> <meta charset="utf-8"> <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="msvalidate.01" content="52D8CD5F9EA2B1031F2D2472023A5D34"> <title>MyPortal | Market Reports</title> <link rel="preconnect" href="https://www.google.com"> <link rel="preconnect" href="https://www.gstatic.com" crossorigin> <link rel="dns-prefetch" href="https://cdn1.brivityidx.com"> 
1<script>
2            var head = document.getElementsByTagName('head')[0]
3            var insertBefore = head.insertBefore;
4            head.insertBefore = function (newElement, referenceElement) {
5                // intercept style elements for IEs
6                if (newElement.tagName.toLowerCase() === 'style'
7                    && newElement.styleSheet
8                    && newElement.styleSheet.cssText
9                    && newElement.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) {
10                    return;
11                }
12                // intercept style elements for other browsers
13                if (newElement.tagName.toLowerCase() === 'style'
14                    && newElement.innerHTML
15                    && newElement.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) {
16                    return;
17                }
18                insertBefore.call(head, newElement, referenceElement);
19            }; 
20        </script>
20 <link rel="shortcut icon" href="https://cdn1.brivityidx.com/assets/images/uploads/7586/icon-01.png" type="image/x-icon"> <link href="https://cdn1.brivityidx.com/assets/css/build-site.min.css?ck=" rel="stylesheet"> <link href="https://cdn1.brivityidx.com/assets/css/build-chatbot-v1.min.css?ck=" rel="stylesheet" media="print" onload="this.media='all'"><noscript><link href="https://cdn1.brivityidx.com/assets/css/build-chatbot-v1.min.css?ck=" rel="stylesheet"></noscript> <link rel="canonical" href="https://www.realestateagency.com/myportal/reports"> 
20<script>
21            function deferScriptOnLoad(url, sleep = 0) {
22                window.addEventListener('load', function () {
23                    deferScript(url, sleep);
24                });
25            }
26            function deferScript(url, sleep = 0) {
27                if (sleep > 0) {
28                    setTimeout(() => {
29                        deferScript(url);
30                    }, sleep);
31                    return;
32                }
33                let s = document.createElement('script');
34                s.type = 'text/javascript';
35                s.async = true;
36                s.src = url;
37                let x = document.getElementsByTagName('head')[0];
38                x.appendChild(s);
39            }
40
41            /* PLACE_COMPONENTS_LOADER_START */
42            window.sitebuilderPlaceComponents = (function () {
43                var DEFAULT_URL = 'https://mobile-component-services-library-dev.brivity.com/web-components.min.js?ck=1';
44                var BUNDLE_URLS = { default: DEFAULT_URL };
45                var loadPromises = {};
46                var LOAD_TIMEOUT_MS = 10000;
47
48                function urlForTag(tagName) {
49                    return BUNDLE_URLS[tagName] || BUNDLE_URLS.default;
50                }
51
52                function ensureLoaded(tagName) {
53                    var url = urlForTag(tagName);
54                    if (loadPromises[url]) {
55                        return loadPromises[url];
56                    }
57                    loadPromises[url] = new Promise(function (resolve, reject) {
58                        var settled = false;
59                        var timer = setTimeout(function () {
60                            if (settled) return;
61                            settled = true;
62                            reject(new Error('web-components load timeout'));
63                        }, LOAD_TIMEOUT_MS);
64                        var s = document.createElement('script');
65                        s.type = 'text/javascript';
66                        s.async = true;
67                        s.src = url;
68                        s.onerror = function () {
69                            if (settled) return;
70                            settled = true;
71                            clearTimeout(timer);
72                            reject(new Error('web-components script onerror'));
73                        };
74                        document.getElementsByTagName('head')[0].appendChild(s);
75                        if (window.customElements && customElements.whenDefined) {
76                            customElements.whenDefined(tagName).then(function () {
77                                if (settled) return;
78                                settled = true;
79                                clearTimeout(timer);
80                                resolve();
81                            });
82                        }
83                    });
84                    return loadPromises[url];
85                }
86
87                var EAGER_SELECTOR = 'place-propertycard, place-searchpagefilter, place-bedbathfiltermodal, ' +
88                                     'place-listingstatusmodal, place-propertytypemodal, place-savesearchmodal, ' +
89                                     'place-basicmodal, place-details, place-agentbio, place-agentmessaging, ' +
90                                     'place-contactyouragent, place-menu, place-collectionpopup, ' +
91                                     'place-copycollectionmodal, place-removecollectionpopup, place-vs-accumulate';
92
93                function warmIfEagerTagsPresent() {
94                    if (document.querySelector(EAGER_SELECTOR)) {
95                        ensureLoaded('place-propertycard').catch(function () {});
96                    }
97                }
98                if (document.readyState === 'loading') {
99                    document.addEventListener('DOMContentLoaded', warmIfEagerTagsPresent);
100                } else {
101                    warmIfEagerTagsPresent();
102                }
103
104                var INTERACTION_SELECTOR = 'place-getyourhomecta, place-generictoast, ' + EAGER_SELECTOR +
105                                           ', [data-needs-place-components]';
106                function onInteract(e) {
107                    var t = e.target;
108                    if (t && t.closest && t.closest(INTERACTION_SELECTOR)) {
109                        ensureLoaded('place-generictoast').catch(function () {});
110                    }
111                }
112                document.addEventListener('pointerdown', onInteract, true);
113                document.addEventListener('focusin', onInteract, true);
114
115                function idleWarm() {
116                    ensureLoaded('place-generictoast').catch(function () {});
117                }
118                if ('requestIdleCallback' in window) {
119                    requestIdleCallback(idleWarm, { timeout: 5000 });
120                } else {
121                    setTimeout(idleWarm, 3000);
122                }
123
124                return { ensureLoaded: ensureLoaded };
125            })();
126            /* PLACE_COMPONENTS_LOADER_END */
127
128            const googleApiKey = 'AIzaSyAjpuNg6WGCMV5rzoJcIP2QmMTVto6hYmc'
129
130            /* Lazy loader for Google Maps API + turf.js.
131             * The TURF_INLINE / MAPS_API_INLINE placeholders below are emitted by
132             * Sitemodel.php only on pages whose blocks actually consume Maps/turf.
133             * On other pages those tags are stripped, and consumers call
134             * sitebuilderMapsApi.ensureLoaded() to inject them on demand.
135             *
136             * Safari fix vs. the prior reverted attempt (commit 0cef3135e): uses
137             * Google's official &callback= parameter, not setTimeout, to detect
138             * Maps readiness.
139             */
140            window.sitebuilderMapsApi = (function () {
141                var TURF_URL = 'https://cdn.jsdelivr.net/npm/@turf/[email protected]/turf.min.js';
142                var MAPS_URL = 'https://maps.googleapis.com/maps/api/js?libraries=geocoding,places,marker,drawing&key=' +
143                               googleApiKey + '&map_ids=85c127b7bf0255d9&callback=__sitebuilderMapsReady';
144                var LOAD_TIMEOUT_MS = 15000;
145                var loadPromise = null;
146
147                function injectScript(url) {
148                    var s = document.createElement('script');
149                    s.type = 'text/javascript';
150                    s.async = true;
151                    s.src = url;
152                    document.getElementsByTagName('head')[0].appendChild(s);
153                    return s;
154                }
155
156                function loadTurf() {
157                    return new Promise(function (resolve, reject) {
158                        if (window.turf) { resolve(); return; }
159                        var s = injectScript(TURF_URL);
160                        s.onload = function () { resolve(); };
161                        s.onerror = function () { reject(new Error('turf load failed')); };
162                    });
163                }
164
165                function loadMaps() {
166                    return new Promise(function (resolve, reject) {
167                        if (window.google && window.google.maps) { resolve(); return; }
168                        window.__sitebuilderMapsReady = function () { resolve(); };
169                        var s = injectScript(MAPS_URL);
170                        s.onerror = function () { reject(new Error('maps load failed')); };
171                    });
172                }
173
174                function ensureLoaded() {
175                    if (loadPromise) return loadPromise;
176                    if (window.google && window.google.maps && window.turf) {
177                        loadPromise = Promise.resolve();
178                        return loadPromise;
179                    }
180                    loadPromise = new Promise(function (resolve, reject) {
181                        var settled = false;
182                        var timer = setTimeout(function () {
183                            if (settled) return;
184                            settled = true;
185                            reject(new Error('maps/turf load timeout'));
186                        }, LOAD_TIMEOUT_MS);
187                        Promise.all([loadTurf(), loadMaps()]).then(function () {
188                            if (settled) return;
189                            settled = true;
190                            clearTimeout(timer);
191                            resolve();
192                        }, function (err) {
193                            if (settled) return;
194                            settled = true;
195                            clearTimeout(timer);
196                            reject(err);
197                        });
198                    });
199                    return loadPromise;
200                }
201
202                return { ensureLoaded: ensureLoaded };
203            })();
204        </script>
204 <link href="https://cdn1.brivityidx.com/assets/css/style-headers.min.css" rel="stylesheet"><link href="https://cdn1.brivityidx.com/assets/css/style-premium.min.css" rel="stylesheet"><link href="https://cdn1.brivityidx.com/assets/css/library-dd.css" rel="stylesheet"><link href="https://cdn1.brivityidx.com/assets/css/style-footers.css" rel="stylesheet"><link href="https://cdn1.brivityidx.com/idx-sites/9/6/9/9695/site_custom.css?v=1790846336" rel="stylesheet">
204<script type="text/javascript" src="https://cdn1.brivityidx.com/idx-sites/9/6/9/9695/global_js_variables.js?v=1790846336"></script>
204 
204<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=!0;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f)})(window,document,'script','dataLayer','GTM-K2WGMDL')</script>
204 
204<script>$(document).ready(function(){$("ul.seo-anchor-links li:nth-of-type(4) a").attr("href","/search")})</script>
204 
204<script>function loadScript(a){var b=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.src="https://tracker.metricool.com/resources/be.js",c.onreadystatechange=a,c.onload=a,b.appendChild(c)}loadScript(function(){beTracker.t({hash:"f0ad558c6f6b8ff0fb0bc185cc4ca696"})})</script>
vendor: 64 bytes, line 204
204 <script async src="https://www.googletagmanager.com/gtag/js?id=
204G-SE4W6NGRBJ
vendor: 12 bytes, line 204
204"></script> 
204<script>
205  
vendor: 134 bytes, lines 205-209
205window.dataLayer = window.dataLayer || [];
206  function gtag(){dataLayer.push(arguments);}
207  gtag('js', new Date());
208
209  gtag('config', '
209G-SE4W6NGRBJ
vendor: 4 bytes, line 209
209');
210</script>
210 
210<script>
vendor: 395 bytes, lines 210-216
210
211!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
212n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
213n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
214t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
215document,'script','https://connect.facebook.net/en_US/fbevents.js');
216fbq('init', "
216829902774477445
vendor: 30 bytes, lines 216-217
216");
217fbq('track', 'PageView');
218var propDetailsPixelOnReady = function(){
219  let propDetFpst = new FbRealEstatePixelTracker({"eventType": "ViewContent", "content_ids": [""]});
220  propDetFpst.fireEvent();
221};
222if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
223  propDetailsPixelOnReady();
224} else {
225  document.addEventListener("DOMContentLoaded", propDetailsPixelOnReady);
226}
227
228console.log('facebook pixel PageView tracking...');
229</script>
229 <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=829902774477445&ev=PageView&noscript=1"></noscript> 
229<script>
vendor: 327 bytes, lines 229-233
229(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
230new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
231j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
232'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
233})(window,document,'script','dataLayer','
233GTM-NQFTPBXT
vendor: 3 bytes, line 233
233');
233</script>
233 <meta property="og:url" content="https://www.realestateagency.com/myportal/reports"> </head> <body>
vendor: 68 bytes, line 233
233 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
233GTM-NQFTPBXT
vendor: 83 bytes, line 233
233" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 
233<script>
234                  window.fbAsyncInit = function() {
235                    FB.init({
236                      appId      : '1',
237                      cookie     : true,
238                      xfbml      : true,
239                      version    : 'v17.0'
240                    });
241                    FB.AppEvents.logPageView();
242                  };
243
244                  setTimeout(() => {(function(d, s, id){
245                     var js, fjs = d.getElementsByTagName(s)[0];
246                     if (d.getElementById(id)) {return;}
247                     js = d.createElement(s); js.id = id;
248                     js.defer = true;
249                     js.xfbml = false;
250                     js.src = "//connect.facebook.net/en_US/sdk.js";
251                     fjs.parentNode.insertBefore(js, fjs);
252                   }(document, 'script', 'facebook-jssdk'))}, 5000);
253                </script>
253<meta property="fb:app_id" content="1"><meta name="google-signin-client_id" content="1"><meta name="apple-signin-flag" content="1"><meta name="main_sitebuilder_domain" content="https://sitebuilder.brivity.com"> <div id="site-registration-bar" class="collapse"> <input type="hidden" id="huser_id" value=""> <div class="row" style="width: 100%; margin: 0;"> <div class="col-md-12" style="display: none;" id="logged-in"> <div class="topBar flex aiCenter jcBetween"> <div class="topBarLeft flex aiCenter"> <span><topbar_show_agent_name/></span> </div> <div class="topBarRight flex aiCenter"> <a class="topLink flex aiCenter thin favoritesTop" href="/myportal/collections"> <svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_16761_179132)"> <path d="M14.2659 3.57333C13.9254 3.23267 13.5211 2.96243 13.0761 2.77806C12.6312 2.59368 12.1542 2.49878 11.6726 2.49878C11.1909 2.49878 10.714 2.59368 10.269 2.77806C9.82401 2.96243 9.41973 3.23267 9.07922 3.57333L8.37256 4.28L7.66589 3.57333C6.97809 2.88554 6.04524 2.49914 5.07256 2.49914C4.09987 2.49914 3.16702 2.88554 2.47922 3.57333C1.79143 4.26113 1.40503 5.19398 1.40503 6.16667C1.40503 7.13936 1.79143 8.07221 2.47922 8.76L3.18589 9.46667L8.37256 14.6533L13.5592 9.46667L14.2659 8.76C14.6066 8.4195 14.8768 8.01521 15.0612 7.57024C15.2455 7.12526 15.3404 6.64832 15.3404 6.16667C15.3404 5.68501 15.2455 5.20807 15.0612 4.7631C14.8768 4.31812 14.6066 3.91384 14.2659 3.57333V3.57333Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> <clipPath id="clip0_16761_179132"> <rect width="16" height="16" fill="white" transform="translate(0.372559 0.5)"/> </clipPath> </defs> </svg> <span class="ml6 topLabel">Collections&nbsp;</span> </a> <a class="topLink flex aiCenter thin saveSearchTop" href="/myportal/searches"> <svg width="16" height="16" viewBox="0 4 20 17" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19 21L12 16L5 21V5C5 4.46957 5.21071 3.96086 5.58579 3.58579C5.96086 3.21071 6.46957 3 7 3H17C17.5304 3 18.0391 3.21071 18.4142 3.58579C18.7893 3.96086 19 4.46957 19 5V21Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> </svg> <span class="ml6 topLabel">Saved Searches&nbsp;</span> </a> <a class="topLink flex aiCenter thin market-report-top" style="display:none" href="/myportal/reports"> <svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.70589 13.1667C10.6514 13.1667 13.0392 10.7789 13.0392 7.83333C13.0392 4.88781 10.6514 2.5 7.70589 2.5C4.76037 2.5 2.37256 4.88781 2.37256 7.83333C2.37256 10.7789 4.76037 13.1667 7.70589 13.1667Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M14.3725 14.5L11.4725 11.6" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> <span class="ml6 topLabel">My Reports&nbsp;</span> </a> <a class="aiCenter flex topBarProfile thin" href="/myportal/profile"> <span class="profileName"></span> </a> <a style="padding-right: 0px" class="aiCenter flex thin" id="topBarLogout" href="javascript:void()"> <svg width="23" height="23" viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_16761_179186)"> <path d="M16.4003 16.214C19.0038 13.6106 19.0038 9.38945 16.4003 6.78595C13.7968 4.18246 9.57572 4.18246 6.97222 6.78595C4.36873 9.38945 4.36873 13.6105 6.97222 16.214C9.57572 18.8175 13.7968 18.8175 16.4003 16.214Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9.80066 9.61438L13.5719 13.3856" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9.80066 13.3856L13.5719 9.61438" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> <clipPath id="clip0_16761_179186"> <rect width="16" height="16" fill="white" transform="translate(0.372559 11.5) rotate(-45)"/> </clipPath> </defs> </svg> <span class="ml6">Log Out</span> </a> </div> </div> </div> <div id="not-logged-in"> <topbar_agent_info_not_logged_in/> <ul class="list-unstyled list-inline no-margin"> <li class="topBarSignin"><a href="#" onclick="showGoogleOneTap(true);"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle mr10"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line>
253<line x1="8" y1="12" x2="16" y2="12"></line></svg> Sign In</a></li> </ul> </div> </div> </div> <input type="hidden" id="huser_email" value=""> <input type="hidden" id="huser_first_name" value=""> <input type="hidden" id="huser_last_name" value=""> <input type="hidden" id="huser_phone" value=""> <input type="hidden" id="huser_uuid" value=""> <div id="page" class="page"> <header id="premium-navigation" data-selector="#premium-navigation" style=""><div class="main-nav"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" data-selector="a.btn, button.btn, button" style="outline: none; cursor: inherit;"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> <img class="img-responsive site_custom_logo_dynamic" src="https://cdn1.brivityidx.com/assets/images/uploads/7586/logo-011.png" alt="Realvolution" data-selector="img" style=""></a> </div> <div class="collapse navbar-collapse"> <div> <ul class="nav navbar-nav navbar-right adv-nav"><li class="nav-item" data-selector="li" style=""><a id="top-nav-marketing-plan" class="nav-link-color" data-toggle="modal" data-target="#sell-modal">Get Marketing Plan</a></li></ul></div> <div class="basic-nav render-menu"><ul class="nav navbar-nav navbar-right"><li class="nav-item"><a class="sec-nav-link-color" href="/index">Home</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/search">Search Listings</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/home_value">See home value</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/why_list_with_us">Why List with Us?</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/careers">Careers</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/who_we_are">Who We Are</a></li><li class="nav-item"><a class="sec-nav-link-color" href="/instant_offer">Instant Offer</a></li></ul></div> </div> </div> </div> </header><div class="modal fade magic-modal" id="sell-modal" tabindex="-1" role="dialog" aria-labelledby="sell-modal"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-body"> <button type="button" class="close" data-dismiss="modal" aria-label="Close" data-selector="a.btn, button.btn, button" style="outline: none; cursor: inherit;"><span aria-hidden="true">×</span></button> <h4 class="prmry-color" data-selector="h1, h2, h3, h4, h5, h6" style="outline: none; cursor: inherit;">Request property marketing plan</h4> <form class="form-contact" id="form-contact1"> <input type="hidden" name="lead_type" value="seller"><input type="hidden" name="tags" value="Marketing_Plan_Requested"><p data-selector="p" style="outline: none; cursor: inherit;">You’re one step away from getting a free marketing plan that shows how we’ll sell your home for the most amount of money in the least amount of time - hassle free.</p> <div class="row"> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_fname" id="contact1_fname" placeholder="First Name" class="form-control" required="" type="text"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_lname" id="contact1_lname" placeholder="Last Name" class="form-control" required="" type="text"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_email" id="contact1_email" placeholder="Email Address" class="form-control" required="" type="email"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_phone" id="contact1_phone" placeholder="Phone Number" class="form-control" required="" type="tel"></div> </div> <div class="col-sm-12"> <div class="form-group"> <input name="contact1_address" id="contact1_address" placeholder="Address" class="form-control" required="" type="text"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_city" id="contact1_city" placeholder="City" class="form-control" required="" type="text"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_state" id="contact1_state" placeholder="State" class="form-control" required="" type="text"></div> </div> <div class="col-sm-6"> <div class="form-group"> <input name="contact1_zip" id="contact1_zip" placeholder="ZIP" 
253class="form-control" required="" type="text"></div> </div> <div class="col-sm-12"> <div class="form-group"> <select name="contact1_whenareyouselling" id="contact1_whenareyouselling" class="form-control" placeholder="When are you planning to sell?"><option value="" disabled selected>When are you planning to sell?</option><option value="1">Now</option><option value="2">0-6 months</option><option value="3">6+ months</option></select></div> </div> </div> <button data-dismiss="modal" class="btn btn-primary" type="submit" id="cf-submit" name="submit" data-selector="a.btn, button.btn, button" style="outline: none; cursor: inherit;">Send</button> <div id="honeypot-div"> <input name="age_required" id="age_required" value="" type="text" style="display: none;"></div></form> </div> </div> </div> </div> <style>
254    .css-1dbjc4n{
255        z-index: unset;
256    }
257
258    .collection-page {
259        background: #f9f9f9;
260    }
261
262    .center-modal {
263        display:flex;
264        justify-content: center;
265        align-items:center;
266        position:fixed;
267        background-color:rgba(0,0,0,0.4);
268        left:0;
269        top:0;
270        right:0; 
271        bottom:0;
272        z-index: 300;
273    }
274    
275    #report-section{
276        gap: 32px
277    }
278
279    .top-element-container {
280        padding: 24px 0 16px 0;
281    }
282
283    .report {
284        margin: 0 auto;
285        display:flex;
286        flex-direction:column;
287        height:100%;
288        background-color: #F9F9F9; 
289        max-width: 755px;
290    }
291
292    .report-section-container {
293        padding: 16px 0 16px 0;
294    }
295
296    .page-width-parent{
297        margin: 0 auto;
298    }
299
300    #map{
301        background: #fff;
302        padding: 24px 32px 0px;
303        border-radius: 4px;
304        border: #E8E8E8 1px solid;
305        margin-top: 16px;
306        margin-bottom: 16px;
307    }
308
309    @media only screen and (min-width: 1280px) {
310        .collection-page {
311            padding:48px 48px 48px 120px;
312        }
313    }
314
315    @media only screen and (max-width:1279px) {
316        .collection-page {
317            padding:60px 16px 16px 16px;
318        }
319        #map{
320            padding: 24px 12px 0px;
321        }
322    }
323
324    @media only screen and (max-width:893px) { 
325        .collection-page {
326            padding: 60px 32px 16px 32px;
327        }
328        .report {
329            max-width: none;
330        }
331    }
332
333    @media only screen and (max-width:767px) {
334        place-marketreporttile{
335            width: 100%
336        }
337        place-createmarketreport{
338            width: 100%
339        }
340        #report-section{
341            gap: 32px 24px
342        }
343        #map {
344            margin-top: 12px;
345            margin-bottom: 12px;
346        }
347        .collection-page {
348            padding: 60px 16px 16px 16px;
349        }
350        .top-element-container {
351            padding: 24px 0 12px 0;
352        }
353        .report {
354            padding: 0;
355        }
356        .report-section-container {
357            padding: 12px 0 12px 0;
358        }
359    }
360</style> 
360<script>
361
362    let organizationUuid = "7e14a391-6849-4e22-acb5-8bf472637026";
363
364window.addEventListener("load", () => {
365    const key = localStorage.getItem('authorization');
366    const scrollToTop = () => {
367        window.scrollTo({
368            top: 0,
369        });
370    }
371    
372    if( !key) {
373        $("#sign-up-modal").modal('show');
374
375        $("#sign-up-modal").on("hidden.bs.modal", function () {
376            location.reload();
377        });
378    }
379    else{
380
381        let myPortalPage = document.getElementById('myportal-page');
382        myPortalPage.style.display = "block";
383
384        const contact = async (
385        firstName,
386        lastName,
387        email,
388        phone,
389        contactMessage,
390        time_event_type
391        ) => {
392            if (typeof sitebuilderRecaptcha === 'undefined' || !sitebuilderRecaptcha.ready) {
393                throw new Error("Recaptcha not loaded");
394            }
395            let formData = new FormData();
396            formData.append("contact_fname", firstName);
397            formData.append("contact_lname", lastName);
398            formData.append("contact_email", email);
399            formData.append("contact_phone", phone);
400            formData.append("contact_message", contactMessage);
401            formData.append("form_source_url", location.href);
402            formData.append("time_event_type", time_event_type);
403
404            const contact = await fetch("/pages/contact.php", {
405            method: "POST",
406            headers: {
407                'recaptcha-token': await sitebuilderRecaptcha.getToken('contact_form'),
408            },
409            dataType: "json",
410            body: formData,
411            });
412
413            return await contact.json();
414        };
415
416        class Pubsub {
417            static events = {};
418            constructor() {
419                //this.events = {};
420            }
421
422            static subscription (eventName, func) {
423                return {
424                    subscribe: () => {
425                        if (this.events[eventName]) {
426                            this.events[eventName].push(func);
427                        } else {
428                            this.events[eventName] = [func];
429                        }
430                    },
431
432                    unsubscribe: () => {
433                        if(this.events[eventName]){
434                            this.events[eventName] = this.events[eventName].filter((subscriber) => subscriber !== func);
435                        }
436                    }
437                }
438            } 
439
440            static publish(eventName, ...args) {
441                const funcs = this.events[eventName];
442                if (Array.isArray(funcs)) {
443                    funcs.forEach((func) => {
444                        func.apply(null, args);
445                    });
446                }
447            }
448        }
449
450        class MarketHomeValueCard {
451            
452            constructor(report, count) {
453                
454                let _this = this;
455                this.report = report
456                this.menuOpen = false
457                this.count = count
458                this.element = document.createElement('place-marketreporttile');
459                this.dropMenuBackdrop = document.getElementById('drop-menu-backdrop');
460                this.element.setAttribute('market_report', JSON.stringify(report));
461                this.element.setAttribute('z_index', count);
462                this.element.setAttribute('id', report.id);
463                this.element.setAttribute("show_menu", "false");
464                this.element.setAttribute('drop_menu_items', JSON.stringify([ {icon:'edit-3', text: 'Update Report'}, {icon:'trash', text: 'Delete Report'} ]));
465                this.element.setAttribute('google_api_key', 'AIzaSyAjpuNg6WGCMV5rzoJcIP2QmMTVto6hYmc');
466
467
468                this.dropMenuBackdrop.addEventListener('click', (e) => {
469                    
470                    this.element.setAttribute("show_menu", "false");
471                    this.dropMenuBackdrop.style.display = "none";
472                });
473                
474
475                this.element.addEventListener("on_menu_item_pressed", (e) => {
476                    if(e.detail == 'Update Report'){
477                        Pubsub.publish('update_report_menu_pressed', this.report);
478                    }
479                    if(e.detail == 'Delete Report'){
480                        Pubsub.publish('delete_report_menu_pressed', this.report.id);
481                    }
482                });
483
484                this.element.addEventListener("on_card_pressed", (e) => {
485                    window.location = `${window.origin}/myportal/report?market_report_id=${report.id}`
486                });
487
488                this.element.addEventListener(`on_menu_open`, (e) => {    
489                    
490                    this.menuOpen = e.detail;
491                    this.element.setAttribute("show_menu", this.menuOpen);
492
493                    if(this.menuOpen){
494                        this.dropMenuBackdrop.style.display = 'block';
495                        this.element.setAttribute('z_index', 200);
496                    }
497                    else{
498                        this.dropMenuBackdrop.style.display = 'none';
499                        this.element.setAttribute('z_index', count);
500                    }
501                });
502            } 
503            setName(name) {
504                this.element.setAttribute('display_name', name);
505            }
506        }
507
508        class ReportSection {
509            constructor(blueroofMiddlewareApi) {
510                
511                let _this = this;
512                
513                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
514                this.element = document.getElementById('report-section');
515                this.blueroofMiddlewareApi.getMarketReports().then((reports) => {
516
517                    Pubsub.publish('market_reports', reports.length);
518                    
519                    let count = 100;
520                    reports.forEach((report) => {
521                        count--
522                        if(report.lat_lng) {
523                            this.addMarketReport(report,count)
524                        }
525                        else{
526                            report.lat_lng = [0,0];
527                            this.addMarketReport(report,count)
528                        }
529                    })
530                })
531                    
532            }    
533
534            addMarketReport(report, zindex) {
535                    let homeMarketValueCard = new MarketHomeValueCard(report, zindex);
536                    if (report.report_name === report.location) {
537                        let shortName = report?.search_location_name || report.street_address;
538                        homeMarketValueCard.setName(report.report_name.length > 33 ? shortName : report.report_name);
539                    }
540                
541                this.element.append(homeMarketValueCard.element);
542            }        
543        }
544
545        class CreateMarketReport {
546                
547            constructor(blueroofMiddlewareApi) {
548                
549                 
550                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
551                this.element = document.querySelector('place-createmarketreport');
552                
553                this.element.addEventListener("on_change_text", (e) => {
554                    if(e.detail.length > 0){
555                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
556
557                            let suggestions = page.structureAddressSuggestions(suggest.predictions)
558                            this.element.setAttribute('data', JSON.stringify(suggestions));
559                        })
560                    }
561                    
562                });
563
564                this.element.addEventListener("on_selected_location", (e) => {
565                    Pubsub.publish('create_market_report_selected_location', {selectedLocation: e.detail});
566                });
567
568                document.querySelector("place-createmarketreport input").setAttribute("autocomplete","do-not-autofill");
569            }      
570
571            show() {
572                
573                this.element.setAttribute('style', 'display:flex;z-index:100')
574            }
575
576            hide() {
577                this.element.setAttribute('style', 'display:none');
578            }
579        }
580
581        class DeleteMarketReportModal {
582            constructor(blueroofMiddlewareApi) {
583                    
584                this.element = document.getElementById('delete-market-report-modal');
585                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
586                this.reportId = 0
587
588                this.element.addEventListener("on_primary_press", (e) => {
589                    Pubsub.publish('delete_market_report', this.reportId);
590                });
591
592                this.element.addEventListener("on_tertiary_press", (e) => {
593                    this.hide();
594                });
595
596                this.element.addEventListener("on_close_press", (e) => {
597                    this.hide();
598                });
599
600            }
601
602            show(reportId) {
603                this.reportId = reportId
604                this.element.setAttribute('style', 'display:flex')
605            }
606
607            hide() {
608                this.element.setAttribute('style', 'display:none');
609            }
610        }
611
612        class MLSErrorModal {
613            constructor() {
614                    
615                this.element = document.getElementById('mls-error-modal');
616                this.element.setAttribute('sub_title', `It looks like that address is outside of your agent's MLS range. \n\nPlease contact your agent to find out more about your home value.`)
617
618                this.element.addEventListener("on_primary_press", (e) => {
619                    window.location.href = '/myportal/agent'
620                });
621
622                this.element.addEventListener("on_tertiary_press", (e) => {
623                    this.hide();
624                });
625
626                this.element.addEventListener("on_close_press", (e) => {
627                    this.hide();
628                });
629
630            }
631
632            show() {
633                this.element.setAttribute('style', 'display:flex')
634            }
635
636            hide() {
637                this.element.setAttribute('style', 'display:none');
638            }
639        }
640
641        class MLSErrorMarketReportModal {
642            constructor() {
643                    
644                this.element = document.getElementById('mls-error-market-report-modal');
645                this.element.setAttribute('sub_title', `Looks like we’ve encountered a small hiccup, but don’t worry, you’re not stuck! Try searching in your agent’s service area.`)
646
647                this.element.addEventListener("on_primary_press", (e) => {
648                    this.hide();
649                });
650
651                this.element.addEventListener("on_close_press", (e) => {
652                    this.hide();
653                });
654            }
655
656            show() {
657                this.element.setAttribute('style', 'display:flex')
658            }
659
660            hide() {
661                this.element.setAttribute('style', 'display:none');
662            }
663        }
664
665        class VerifyHomeEstimateModal {
666            constructor() {
667                    
668                this.element = document.getElementById('verify-home-estimate-modal');
669                this.element.setAttribute('sub_title', `Your agent will be notified and will reach out shortly to verify your home estimate!`)
670
671                this.element.addEventListener("on_primary_press", (e) => {
672                    Pubsub.publish('verifyMyHomeModalClicked')
673                });
674
675                this.element.addEventListener("on_tertiary_press", (e) => {
676                    this.hide();
677                });
678
679                this.element.addEventListener("on_close_press", (e) => {
680                    this.hide();
681                });
682
683            }
684
685            show() {
686                this.element.setAttribute('style', 'display:flex')
687            }
688
689            hide() {
690                this.element.setAttribute('style', 'display:none');
691            }
692        }
693
694        class BlueroofMiddlewareApi {
695            constructor() {
696                this.baseUrl = "https://brivity-home-middleware.production.brivity.com";
697                this.apiKey = localStorage.getItem('authorization');
698            }
699
700            getMLSIds = async () => {
701                const response = await fetch(`${this.baseUrl}/autocomplete/mlsids`, {
702                    method: 'GET',
703                    headers: {
704                        'Content-Type': 'application/json',
705                        'Authorization': `${this.apiKey}`
706                    }
707                });
708
709                const data = await response.json();
710                return data;
711            }
712
713            googlePlaceSuggestions = async(text) => {
714                const response = await fetch(`${this.baseUrl}/googleAutocomplete/PlaceSuggestions`, {
715                    method: 'POST',
716                    headers: {
717                        'Content-Type': 'application/json',
718                        'Authorization': `${this.apiKey}`
719                    },
720                    body: JSON.stringify({
721                        input: text
722                    })
723                });
724
725                const data = await response.json();
726                return data;
727            }
728
729            getBrivityHomeAppInvite = async (number) => {
730                const response = await fetch(`${this.baseUrl}/brivityLeads/sendHomeAppInvite`, {
731                    method: 'POST',
732                    headers: {
733                        'Content-Type': 'application/json',
734                        'Authorization': `${this.apiKey}`
735                    },
736                    body: JSON.stringify({
737                        "phoneNumber": number
738                    })
739                });
740
741                if(!response.ok){
742                    throw new Error();
743                }
744
745                const data = await response.json();
746                return data;
747            }
748
749            getMarketReports = async () => {
750                const response = await fetch(`${this.baseUrl}/cma/marketReports`, {
751                    method: 'GET',
752                    headers: {
753                        'Content-Type': 'application/json',
754                        'Authorization': `${this.apiKey}`
755                    } 
756                });
757
758                const data = await response.json();
759                return data;
760            }
761
762            getMarketReport = async (id) => {
763                const response = await fetch(`${this.baseUrl}/cma/marketReport/${id}`, {
764                    method: 'GET',
765                    headers: {
766                        'Content-Type': 'application/json',
767                        'Authorization': `${this.apiKey}`
768                    } 
769                });
770
771                const data = await response.json();
772                return data;
773            }
774
775            updateMarketReport = async (id, reportData) => {
776                const response = await fetch(`${this.baseUrl}/cma/marketReport/${id}`, {
777                    method: 'PATCH',
778                    headers: {
779                        'Content-Type': 'application/json',
780                        'Authorization': `${this.apiKey}`
781                    },
782                    body: JSON.stringify(reportData)
783                });
784
785                if(!response.ok){
786                    throw new Error();
787                }
788
789                const data = await response;
790                return data;
791            }
792
793            deleteMarketReport = async (id) => {
794                const response = await fetch(`${this.baseUrl}/cma/marketReport/${id}`, {
795                    method: 'DELETE',
796                    headers: {
797                        'Content-Type': 'application/json',
798                        'Authorization': `${this.apiKey}`
799                    }
800                });
801
802                if(!response.ok){
803                    throw new Error();
804                }
805
806                const data = await response
807                return data;
808            }
809
810            createMarketReport = async (reportData) => {
811                const response = await fetch(`${this.baseUrl}/cma/marketReport`, {
812                    method: 'POST',
813                    headers: {
814                        'Content-Type': 'application/json',
815                        'Authorization': `${this.apiKey}`
816                    },
817                    body: JSON.stringify(reportData)
818                });
819
820                if(!response.ok){
821                    throw new Error();
822                }
823
824                const data = await response.json();
825                return data;
826            }
827
828            homeValueReport = async (reportData) => {
829                const response = await fetch(`${this.baseUrl}/cma/homeValueReport`, {
830                    method: 'POST',
831                    headers: {
832                        'Content-Type': 'application/json',
833                        'Authorization': `${this.apiKey}`
834                    },
835                    body: JSON.stringify(reportData)
836                });
837
838                if(!response.ok){
839                    throw new Error('Error creating market report');
840                }
841
842                const data = await response.json();
843                return data;
844            }
845
846            previewMarketReport = async (reportData) => {
847                const response = await fetch(`${this.baseUrl}/cma/marketReport/preview`, {
848                    method: 'POST',
849                    headers: {
850                        'Content-Type': 'application/json',
851                        'Authorization': `${this.apiKey}`
852                    },
853                    body: JSON.stringify(reportData)
854                });
855
856                if(!response.ok){
857                   Pubsub.publish('previewError', response.status);
858                    throw new Error();
859                }
860
861                const data = await response.json();
862                return data;
863            }
864
865            getGeocodeAddress = async (addressData) => {
866                const response = await fetch(`${this.baseUrl}/address/geocode`, {
867                    method: 'POST',
868                    headers: {
869                        'Content-Type': 'application/json',
870                        'Authorization': `${this.apiKey}`
871                    },
872                    body: JSON.stringify(addressData)
873                });
874
875                const data = await response.json();
876                return data;
877            }
878
879            getGeoJson = async(addressData) => {
880                const response = await fetch(`${this.baseUrl}/geoJson/areas/censusplaces/search`, {
881                    method: 'POST',
882                    headers: {
883                        'Content-Type': 'application/json',
884                        'Authorization': `${this.apiKey}`
885                    },
886                    body: JSON.stringify(addressData)
887                });
888
889                const data = await response.json();
890                return data;
891            }
892
893            getSlipStreamAVM = async (addressData) => {
894                const response = await fetch(`${this.baseUrl}/slipstream/avm`, {
895                    method: 'POST',
896                    headers: {
897                        'Content-Type': 'application/json',
898                        'Authorization': `${this.apiKey}`
899                    },
900                    body: JSON.stringify(addressData)
901                });
902
903                const data = await response.json();
904                return data;
905            }
906
907            getLandVoiceAvm = async (addressData) => {
908                const response = await fetch(`${this.baseUrl}/landVoice/avm`, {
909                    method: 'POST',
910                    headers: {
911                        'Content-Type': 'application/json',
912                        'Authorization': `${this.apiKey}`
913                    },
914                    body: JSON.stringify(addressData)
915                });
916
917                const data = await response.json();
918                return data;
919            }
920
921            getZestimate = async (addressData) => {
922                const response = await fetch(`${this.baseUrl}/zillow/zestimate`, {
923                    method: 'POST',
924                    headers: {
925                        'Content-Type': 'application/json',
926                        'Authorization': `${this.apiKey}`
927                    },
928                    body: JSON.stringify(addressData)
929                });
930
931                const data = await response.json();
932                return data;
933            }
934
935            getMlsValue = async (mlsData) => {
936                const response = await fetch(`${this.baseUrl}/listings/stats/value`, {
937                    method: 'POST',
938                    headers: {
939                        'Content-Type': 'application/json',
940                        'Authorization': `${this.apiKey}`
941                    },
942                    body:JSON.stringify(mlsData)
943                });
944
945                const data = await response.json();
946                return data;
947            }
948
949            getLeadBasicInfo = async () => {
950                const response = await fetch(`${this.baseUrl}/blueroofleads/basicinfo`, {
951                    method: 'GET',
952                    headers: {
953                        'Content-Type': 'application/json',
954                        'Authorization': `${this.apiKey}`
955                    },
956                    
957                });
958
959                const data = await response.json();
960                return data;
961            }
962
963            getAgentProfile = async (brivityUserId) => {
964                const response = await fetch(`${this.baseUrl}/blueroofagents/profile`, {
965                    method: 'POST',
966                    headers: {
967                        'Content-Type': 'application/json',
968                        'Authorization': `${this.apiKey}`
969                    },
970                    body: `{"brivityUserId": ${brivityUserId}}`
971                    
972                });
973
974                const data = await response.json();
975                return data;
976            }
977
978            getStreetViewImage = a
978sync (addressData) => {
979                const response = await fetch(`${this.baseUrl}/googlestreetview/getstreetviewimage`, {
980                    method: 'POST',
981                    headers: {
982                        'Content-Type': 'application/json',
983                        'Authorization': `${this.apiKey}`
984                    },
985                    body: JSON.stringify(addressData)
986                });
987
988                const imageBlob = await response.blob();
989                const imageObjectURL = URL.createObjectURL(imageBlob);
990                return imageObjectURL;
991            }
992
993            addMarketReportFrequencyUpdatedTimelineEvent = async (event) => {
994                const response = await fetch(`${this.baseUrl}/timeline/marketReportFrequencyUpdated`, {
995                    method: 'Post',
996                    headers: {
997                        'Content-Type': 'application/json',
998                        'Authorization': `${this.apiKey}`
999                    },
1000                    body: JSON.stringify(event)
1001                })
1002
1003                if(!response.ok){
1004                    throw new Error();
1005                }
1006
1007                const data = await response.text();
1008                return data; 
1009            }
1010
1011            addTag = async (organizationUuid, tag) => {
1012                const response = await fetch(`${this.baseUrl}/cma/person/tag`, {
1013                    method: 'POST',
1014                    headers: {
1015                        'Content-Type': 'application/json',
1016                        'Authorization': `${this.apiKey}`
1017                    },
1018                    body: JSON.stringify({ organizationUuid, tag })
1019                });
1020
1021                if (!response.ok) {
1022                    throw new Error();
1023                }
1024            }
1025        }
1026
1027        class ReportListingBrivityHomeApp {
1028            constructor() {
1029                this.element = document.getElementById('reportListingViewGetHomeApp');
1030
1031                this.element.addEventListener('on_button_pressed', (e) => {
1032                    Pubsub.publish('sendBrivityHomeAppInvite', e.detail);
1033                })
1034            }
1035        }
1036
1037        class ReportViewBrivityHomeApp {
1038            constructor() {
1039                this.element = document.getElementById('reportViewGetHomeApp');
1040
1041                this.element.addEventListener('on_button_pressed', (e) => {
1042                    Pubsub.publish('sendBrivityHomeAppInvite', e.detail, e.target.id);
1043                })
1044            }
1045            setIsLoading(value) {
1046                this.element.setAttribute('loading', value);
1047            }
1048        }
1049
1050        class MarketReportModal {
1051            constructor(blueroofMiddlewareApi, page) {
1052                this.element = document.getElementById('market-report-modal');
1053                this.menuBackdrop = document.getElementById('menu-backdrop');
1054                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
1055                this.marketReport = null;
1056                this.element.setAttribute('visible', 'false');
1057
1058                this.blueroofMiddlewareApi.getMLSIds().then((data) => {
1059                    this.mlsIds = data
1060                })
1061
1062                this.element.addEventListener('set_visible', (e) => {
1063                    this.hide();
1064                })
1065
1066                this.menuBackdrop.addEventListener('click', (e) => {
1067                    this.hide();
1068                })
1069
1070                this.element.addEventListener('on_change', (e) => {
1071                    if(e.detail.length > 0){
1072                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
1073                            
1074                            let suggestions = page.structureAddressSuggestions(suggest.predictions)
1075                            this.element.setAttribute('data', JSON.stringify(suggestions));
1076                        })
1077                    }
1078                })
1079
1080                this.element.addEventListener('on_selected_location', (e) => {
1081                    Pubsub.publish('create_market_report_selected_location', {selectedLocation: e.detail});
1082                })
1083
1084                this.element.addEventListener('on_save_button_press', (e) => {
1085                    Pubsub.publish('update_report_details', {'changes':e.detail, "marketReport" : this.marketReport});
1086                })
1087
1088                document.querySelectorAll("#market-report-modal input")[1].setAttribute("autocomplete","do-not-autofill");
1089            }
1090
1091            show() {
1092                
1093                this.element.setAttribute('visible', 'true')
1094                this.menuBackdrop.style.display = 'flex'
1095            }
1096
1097            hide() {
1098                this.element.setAttribute('visible', 'false');
1099                    this.menuBackdrop.style.display = 'none'
1100            }
1101
1102            showReportName(value){
1103                this.element.setAttribute('show_report_name', value);
1104            }
1105
1106            setMarketReportData(data) {
1107                this.marketReport = data
1108                this.element.setAttribute('market_report', JSON.stringify(data));
1109            }
1110
1111        }
1112
1113        class LoadingModal {
1114            constructor() {
1115                this.element = document.querySelector('place-loadingmodal');
1116
1117                this.element.addEventListener('on_press', (e) => {
1118                    this.hide();
1119                })
1120            }
1121
1122            show() {
1123                this.element.setAttribute('style', 'display:flex')
1124            }
1125
1126            hide() {
1127                scrollToTop();
1128                this.element.setAttribute('style', 'display:none');
1129            }
1130        }
1131
1132        class EmptyMarketReport {
1133
1134            constructor(blueroofMiddlewareApi, mlsIds) {
1135                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
1136                this.element = document.querySelector('place-emptymarketreport')
1137                this.mlsIds = mlsIds;
1138
1139                this.element.addEventListener("on_change", (e) => {
1140                    if(e.detail.length > 0){
1141                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
1142                            
1143                            let suggestions = page.structureAddressSuggestions(suggest.predictions)
1144                            this.element.setAttribute('data', JSON.stringify(suggestions));
1145                        })
1146                    }
1147                    
1148                });
1149
1150                this.element.addEventListener("on_selected_location", (e) => {
1151                    Pubsub.publish('create_market_report_selected_location', {selectedLocation: e.detail});
1152                    
1153                });
1154
1155                document.querySelector("place-emptymarketreport input").setAttribute("autocomplete","do-not-autofill");
1156            }
1157
1158            show() {
1159                this.element.setAttribute('style', 'display:flex')
1160            }
1161
1162            hide() {
1163                this.element.setAttribute('style', 'display:none');
1164            }
1165        }
1166
1167        class SavedReportSection {
1168            constructor() {
1169                this.element = document.getElementById('saved-report-section');
1170            }
1171
1172            show() {
1173                this.element.setAttribute('style', 'display:block')
1174            }
1175
1176            hide() {
1177                this.element.setAttribute('style', 'display:none');
1178            }
1179        }
1180
1181        class ViewReportSection{
1182            constructor() {
1183                this.element = document.getElementById('view-report-section');
1184            }
1185
1186            show() {
1187                this.element.setAttribute('style', 'display:flex')
1188            }
1189
1190            hide() {
1191                this.element.setAttribute('style', 'display:none');
1192            }
1193        }
1194
1195        class Maps {
1196            constructor() {
1197
1198                let _this = this;
1199                this.element = document.querySelector('place-mapblock');
1200
1201                this.element.addEventListener('on_link_press', (e) => {
1202                    Pubsub.publish('mapLinkPressed', e.detail)
1203                });
1204
1205                this.element.addEventListener('on_search_for_homes', (e) => {
1206                    Pubsub.publish('mapLinkPressed', e.detail)
1207                });
1208
1209                this.element.addEventListener('on_property_pressed', (e) => {
1210                    let property = e.detail;
1211                    let url = this.getPropertyUrl(property);
1212                    property.searchUrl = url;
1213                    window.open('../../' + url, '_blank');
1214                });
1215            }
1216
1217            getPropertyUrl = (property) => {
1218                let state = property.state;
1219                let city = this.slugify(property.city);
1220                let zip = this.slugify(property.postal_code);
1221                let address = this.slugify(property.address);
1222                let blossorId = property.blossor_id;
1223                return `homes-for-sale/${state}/${city}/${zip}/${address}/bid-${blossorId}`;
1224            }
1225
1226            slugify(text) {
1227                // replace non letter or digits by -
1228                text = text.replace(/[^\pL\d]+~u/g, '_');
1229                // transliterate
1230                text = text.normalize('NFKD').replace(/[\u0300-\u036F]/g,'')
1231                // remove unwanted characters
1232                text = text.replace(/[^_\w]+/g, '_');
1233                // trim
1234                text = text.trim();
1235                // remove duplicate -
1236                text = text.replace(/_+/g, '-');
1237                // lowercase
1238                text = text.toLowerCase();
1239                if (!text) {
1240                    return 'n-a';
1241                }
1242                return text
1243            }
1244        }
1245
1246        class MarketReport {
1247            constructor(blueroofMiddlewareApi){
1248                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
1249
1250                this.realtorContactCTA = document.querySelector('place-realtorcontactcta');
1251                this.homeDetails = document.querySelector('place-homedetails');
1252                this.estimatedHomeValue = document.querySelector("place-estimatedhomevalue");
1253                this.temperature = document.querySelector('place-markettemperatureblock');
1254                this.marketTrends = document.querySelector('place-markettrends');
1255                this.map = document.querySelector('place-mapblock');
1256                this.sendMessage = document.querySelector('place-sendmessage');
1257                this.doesMyHomeCompare = document.querySelector('place-doesmyhomecompare');
1258                this.ownAnotherHome = document.querySelector('place-ownanotherhome');
1259
1260                this.realtorContactCTA.addEventListener('on_press', (e) => {
1261                    Pubsub.publish('contact_us')
1262                });
1263                this.homeDetails.addEventListener('home_details_edit_button', (e) => {
1264                    Pubsub.publish('editHomeFactsClicked')
1265                });
1266            }
1267        }
1268
1269        class InstantOfferCard {
1270            constructor() {
1271                let _this = this;
1272                this.elements = document.querySelectorAll("place-instantoffercard");
1273                this.elements.forEach((element) => {
1274                    const id = element.id;
1275                    element.addEventListener('on_press', (e) => {
1276                        switch (id) {
1277                            case "useEquityCTA" :
1278                                Pubsub.publish("unlockMyEquity");
1279                                break;
1280                            case "competitiveSellCTA" :
1281                                Pubsub.publish("contact_us");
1282                                break;
1283                            default:
1284                                throw new Error("CTA with that ID doesn't exist");
1285                        }
1286                    });
1287                });
1288            }
1289
1290            hide() {
1291                this.elements.forEach((element) => {
1292                    element.parentElement.setAttribute('style', 'display:none')
1293                });
1294            }
1295
1296            show() {
1297                this.elements.forEach((element) => {
1298                    element.parentElement.setAttribute('style', 'display:block')
1299                });
1300            }
1301        }
1302
1303        class OtherEstimatesModal {
1304            constructor() {
1305                let _this = this;
1306                this.element = document.querySelector('place-otherestimates');
1307
1308                this.element.addEventListener("close_button", (e) => {
1309                    _this.hide();
1310                });
1311            }
1312
1313            show() {
1314                this.element.setAttribute('style', 'display:flex')
1315            }
1316
1317            hide() {
1318                this.element.setAttribute('style', 'display:none')
1319            }
1320
1321            
1322            setZillowEstimate(zillowEstimate) {
1323                this.element.setAttribute('zillow', zillowEstimate)
1324            }
1325
1326            setSlipstreamEstimate(slipstreamEstimate) {
1327                this.element.setAttribute('home_junction', slipstreamEstimate)
1328            }
1329
1330            setMlsEstimate(mlsEstimate) {
1331                this.element.setAttribute('mls', mlsEstimate)
1332            }
1333
1334            setAttomEstimate(attomEstimate) {
1335                this.element.setAttribute('attom', attomEstimate)
1336            }
1337        }
1338
1339        class EstimatedHomeValue  {
1340            constructor() {
1341                
1342                let _this = this;
1343                this.element = document.querySelector("place-estimatedhomevalue");
1344
1345                this.element.addEventListener('other_estimates_btn', (e) => {
1346                    Pubsub.publish('seeOtherEstimatesClicked')
1347                });
1348
1349                this.element.addEventListener('on_press_btn', (e) => {             
1350                    Pubsub.publish('verifyMyHomeModalClicked')
1351                });
1352                
1353            }
1354
1355            setEstimatedHomeEquity(estimatedHomeEquity) {
1356                this.element.setAttribute('estimated_home_equity', estimatedHomeEquity)
1357            }
1358
1359            setAddress(address) {
1360                this.element.setAttribute('address', address)
1361            }
1362
1363            setLowEndPrice(lowEndPrice) {
1364                this.element.setAttribute('low_end_price', lowEndPrice)
1365            }
1366
1367            setHighEndPrice(highEndPrice) {
1368                this.element.setAttribute('high_end_price', highEndPrice)
1369            }
1370
1371            setSquareFeet(sqft) {
1372                this.element.setAttribute('sqft', sqft)
1373            }
1374
1375            setPricePerSquareFoot(pricePerSquareFoot) {
1376                this.element.setAttribute('price_per_sqft', pricePerSquareFoot)
1377            }
1378
1379            setTemperature(temperature) {
1380                this.element.setAttribute('temperature', temperature)
1381            }
1382
1383            hide() {
1384                this.element.parentElement.setAttribute('style', 'display:none')
1385            }
1386
1387        }
1388
1389        class SendMessage {
1390            constructor() {
1391                
1392                let _this = this;
1393                this.element = document.querySelector('place-sendmessage');
1394
1395                this.element.addEventListener('send_msg', (e) => {
1396                    this.element.setAttribute('loading', true);   
1397
1398                    contact(
1399                        page?.lead?.fname, page?.lead?.lname, page?.lead?.email, page?.lead?.phone, `${e.detail?.subject} <br/> ${e.detail?.message}`,'contact_form_get_prequalified'
1400                    )
1401                        .then((response) => {
1402                            this.element.setAttribute('loading', false);   
1403                            toast.show("Inquiry sent successfully. Your agent will be in touch shortly.");
1404                        })
1405                        .catch((error) => {
1406                            this.element.setAttribute('loading', false);
1407                            toast.show("Error sending message", true);
1408                        });
1409                });
1410            }
1411        }
1412
1413        class PageSubHeader  {
1414            constructor() {
1415                
1416                this.element = document.querySelector('place-pagesubheader')
1417                this.buttonDisplay = [false, false, false, false, false, false]
1418
1419                this.getHomeValueButtonIndex = 0;
1420                this.sellMyHomeButtonIndex = 1;
1421                this.contactUsButtonIndex = 2;
1422                this.EditCriteriaIndex = 3;
1423                this.SaveReportButtonIndex = 4;
1424                this.MoreMenuButtonIndex = 5;
1425                this.MobileMoreMenuButtonIndex = 6;
1426
1427                this.defaultButtonStyle = {
1428                    icon_stroke : "black",
1429                    type : "none",
1430                    text_styles : "text-[#000] font-medium",
1431                    button_prop_styles : "border-[#000] border-2 py-2 px-4"
1432                };
1433
1434                this.invertedButtonStyle = {
1435                    icon_stroke : "#FFFFFF",
1436                    type : "black",
1437                    text_styles : "text-[#FFFFFF] font-medium",
1438                    button_prop_styles : "border-2 border-[#000] py-2 px-4"
1439                };
1440
1441                this.buttons = [
1442
1443                    {
1444                        name:"GetHomeValue",
1445                        title : "Get Home Value",
1446                        icon : "activity",
1447                        icon_size : 16,
1448                        icon_fill : "none",
1449                        icon_stroke : this.defaultButtonStyle.icon_stroke,
1450                        icon_stroke_width : 3,
1451                        type : this.defaultButtonStyle.type,
1452                        outline : true,
1453                        ghost : false,
1454                        text_styles : this.defaultButtonStyle.text_styles,
1455                        button_prop_styles : this.defaultButtonStyle.button_prop_styles
1456                    },
1457                    {
1458                        name:"SellMyHome",
1459                        title : "Sell My Home",
1460                        icon : "home",
1461                        icon_size : 16,
1462                        icon_fill : "none",
1463                        icon_stroke : this.defaultButtonStyle.icon_stroke,
1464                        icon_stroke_width : 3,
1465                        type : this.defaultButtonStyle.type,
1466                        outline : true,
1467                        ghost : false,
1468                        text_styles : this.defaultButtonStyle.text_styles,
1469                        button_prop_styles : this.defaultButtonStyle.button_prop_styles
1470                    },
1471                    {
1472                        name:"ContactUs",
1473                        title : "Contact Us",
1474                        icon : "mail",
1475                        icon_size : 16,
1476                        icon_fill : "none",
1477                        icon_stroke : this.defaultButtonStyle.icon_stroke,
1478                        icon_stroke_width : 3,
1479                        type : this.defaultButtonStyle.type,
1480                        outline : true,
1481                        ghost : false,
1482                        text_styles : this.defaultButtonStyle.text_styles,
1483                        button_prop_styles : this.defaultButtonStyle.button_prop_styles
1484                    },
1485                    {
1486                        name:"EditCriteria",
1487                        title : "Edit Criteria",
1488                        icon : "",
1489                        icon_size : 16,
1490                        icon_fill : "none",
1491                        icon_stroke : this.defaultButtonStyle.icon_stroke,
1492                        icon_stroke_width : 3,
1493                        type : this.defaultButtonStyle.type,
1494                        outline : true,
1495                        ghost : false,
1496                        text_styles : this.defaultButtonStyle.text_styles,
1497                        button_prop_styles : this.defaultButtonStyle.button_prop_styles
1498                    },
1499                    {
1500                        name:"SaveReport",
1501                        title : "Save Report",
1502                        icon : "",
1503                        icon_size : 16,
1504                        icon_fill : "none",
1505                        icon_stroke : this.invertedButtonStyle.icon_stroke,
1506                        icon_stroke_width : 3,
1507                        type : this.invertedButtonStyle.type,
1508                        outline : true,
1509                        ghost : false,
1510                        text_styles :  `${this.invertedButtonStyle.text_styles} ml-1`,
1511                        button_prop_styles : `${this.invertedButtonStyle.button_prop_styles} mr-0`
1512                    },
1513                    {
1514                        name:"MoreMenuButton",
1515                        title : "More",
1516                        type: this.invertedButtonStyle.type,
1517                        is_menu_button : true,
1518                        icon_size : 25,
1519                        icon_stroke : this.invertedButtonStyle.icon_stroke,
1520                        icon_stroke_width : 1.5,
1521                        text_styles : `${this.invertedButtonStyle.text_styles} ml-1`,
1522                        button_prop_styles : `${this.invertedButtonStyle.button_prop_styles} mr-0`,
1523                        menu_button_items : [
1524                            {icon:'edit-3', text: 'Update Report'},
1525                            {icon:'trash', text: 'Delete Report'}
1526                        ]
1527                    },
1528                    {
1529                        name:"MobileMoreMenuButton",
1530                        title : "More",
1531                        type: this.invertedButtonStyle.type,
1532                        is_menu_button : true,
1533                        icon_size : 25,
1534                        icon_stroke : this.invertedButtonStyle.icon_stroke,
1535                        icon_stroke_width : 1.5,
1536                        text_styles : `${this.invertedButtonStyle.text_styles} ml-1`,
1537                        button_prop_styles : `${this.invertedButtonStyle.button_prop_styles} mr-0`,
1538                        menu_button_items : [
1539                            {icon:'activity', text: 'Get Home Value'},
1540                            {icon:'home', text: 'Sell My Home'},
1541                            {icon:'mail', text: 'Contact Us'},
1542                            {icon:'edit-3', text: 'Update Report'}
1543                        ]
1544                    }  
1545                ]
1546
1547                this.element.setAttribute('buttons', JSON.stringify(this.buttons))
1548                this.element.setAttribute('dynamic_buttons_display', JSON.stringify(this.buttonDisplay))
1549                this.element.setAttribute('title_styles', 'uppercase')
1550
1551                this.element.addEventListener('dynamic_button_on_press', (event) => {
1552                    let buttonName = event.detail
1553
1554                    switch(buttonName){
1555                        case 'GetHomeValue':
1556                            Pubsub.publish('get_home_value')
1557                            break;
1558                        case 'SellMyHome':
1559                            Pubsub.publish('sell_my_home')
1560                            break;
1561                        case 'ContactUs':
1562                            Pubsub.publish('contact_us')
1563                            break;
1564                        case 'SaveReport':
1565                            Pubsub.publish('save_report');
1566                            break;
1567                    }
1568
1569                })
1570
1571                this.element.addEventListener('dynamic_on_menu_item_pressed', (e) => {
1572                    Pubsub.publish('top_header_menu_item_pressed', e.detail)
1573                })
1574
1575                this.element.addEventListener('top_header_on_press', (e) => {
1576                    Pubsub.publish('top_header_back_pressed', e)
1577                })
1578            }
1579
1580            invertButtonStyles(name, invert){
1581                this.buttons.forEach(button => {
1582                    if (button.name === name) {
1583                        button.icon_stroke = invert ? this.invertedButtonStyle.icon_stroke : this.defaultButtonStyle.icon_stroke;
1584                        button.type = invert ? this.invertedButtonStyle.type : this.defaultButtonStyle.type;
1585                        button.text_styles = invert ? this.invertedButtonStyle.text_styles : this.defaultButtonStyle.text_styles;
1586                        button.button_prop_styles = invert ? this.invertedButtonStyle.button_prop_styles : this.defaultButtonStyle.button_prop_styles;
1587                    }
1588                });
1589                this.updateButtonStyles();
1590            }
1591
1592            updateButtonStyles(){
1593                const buttonData = this.buttons.map(button => ({
1594                    ...button,
1595                    name: button.name,
1596                    icon_stroke: button.icon_stroke,
1597                    type: button.type,
1598                    text_styles: button.text_styles,
1599                    button_prop_styles: button.button_prop_styles
1600                }));
1601                this.element.setAttribute('buttons', JSON.stringify(buttonData));
1602            }
1603
1604            setMenuItemStyles(twStyles) {
1605                this.element.setAttribute('dynamic_button_menu_styles', twStyles)
1606            }
1607
1608            setTitle(title) {
1609                this.element.setAttribute('title', title)
1610            }
1611
1612            setTopHeaderTitle(title){
1613                this.element.setAttribute('top_header_title', title)
1614            }
1615
1616            setCriteria(criteria){
1617                this.element.setAttribute('criteria', criteria)
1618            }
1619
1620            showTopHeader(){
1621                this.element.setAttribute('show_top_header', true)
1622            }
1623
1624            hideTopHeader(){
1625                this.element.setAttribute('show_top_header', false)
1626            } 
1627
1628            showGetHomeValueButton() {
1629                this.buttonDisplay[this.getHomeValueButtonIndex] = true
1630                this.setDynamicButtonDisplay()
1631            }
1632
1633            hideGetHomeValueButton() {
1634                this.buttonDisplay[this.getHomeValueButtonIndex] = false
1635                this.setDynamicButtonDisplay()
1636            }
1637            
1638            showSellMyHomeButton() {
1639                this.buttonDisplay[this.sellMyHomeButtonIndex] = true
1640                this.setDynamicButtonDisplay()
1641            }
1642
1643            hideSellMyHomeButton() {
1644                this.buttonDisplay[this.sellMyHomeButtonIndex] = false
1645                this.setDynamicButtonDisplay()
1646            }
1647
1648            showContactUsButton() {
1649                this.buttonDisplay[this.contactUsButtonIndex] = true
1650                this.setDynamicButtonDisplay()
1651            }
1652
1653            hideContactUsButton() {
1654                this.buttonDisplay[this.contactUsButtonIndex] = false
1655                this.setDynamicButtonDisplay()
1656            }
1657
1658            showEditCriteriaButton() {
1659                this.buttonDisplay[this.EditCriteriaIndex] = true
1660                this.setDynamicButtonDisplay()
1661            }
1662
1663            hideEditCriteriaButton() {
1664                this.buttonDisplay[this.EditCriteriaIndex] = false
1665                this.setDynamicButtonDisplay()
1666            }
1667
1668            showSaveReportButton() {
1669                this.buttonDisplay[this.SaveReportButtonIndex] = true
1670                this.setDynamicButtonDisplay()
1671            }
1672
1673            hideSaveReportButton() {
1674                this.buttonDisplay[this.SaveReportButtonIndex] = false
1675                this.setDynamicButtonDisplay()
1676            }
1677
1678            showMoreMenuButton() {
1679                this.buttonDisplay[this.MoreMenuButtonIndex] = true
1680                this.setDynamicButtonDisplay()
1681            }
1682
1683            hideMoreMenuButton() {
1684                this.buttonDisplay[this.MoreMenuButtonIndex] = false
1685                this.setDynamicButtonDisplay()
1686            }
1687
1688            showMobileMoreMenuButton(marketReport) {
1689                if(marketReport){
1690                    this.buttons[this.MobileMoreMenuButtonIndex].menu_button_items =[
1691                        {icon:'home', text: 'Sell My Home'},
1692                        {icon:'mail', text: 'Contact Us'},
1693                        {icon:'bell', text: 'Manage Alerts'},
1694                        {icon:'trash', text: 'Delete Report'}
1695                    ]
1696                    this.element.setAttribute('buttons', JSON.stringify(this.buttons))
1697                }
1698                this.buttonDisplay[this.MobileMoreMenuButtonIndex] = true
1699                this.setDynamicButtonDisplay()
1700            }
1701
1702            hideMobileMoreMenuButton() {
1703                this.buttonDisplay[this.MobileMoreMenuButtonIndex] = false
1704                this.setDynamicButtonDisplay()
1705            }
1706
1707            setDynamicButtonDisplay(){
1708                this.element.setAttribute('dynamic_buttons_display', `[${this.buttonDisplay}]`)
1709            }
1710        }
1711
1712        class HomeEquityCalculator {
1713            constructor(lead) {
1714                this.equityCalculator = document.querySelector('place-homeequitycalculator')
1715                this.equityModal = document.querySelector('place-useyourequitymodal')
1716
1717                this.equityCalculator.addEventListener("refine_sell_your_home_calculation", (e) => {
1718                    this.setEquityModalAttributes()
1719                    this.equityModal.setAttribute('selected_tab', 0)
1720                    this.equityModal.setAttribute('style', 'display:flex;');
1721                })
1722
1723                this.equityCalculator.addEventListener("refine_cash_out_refinance_calculation", (e) => {
1724                    this.setEquityModalAttributes()
1725                    this.equityModal.setAttribute('selected_tab', 1)
1726                    this.equityModal.setAttribute('style', 'display:flex;');
1727                })
1728
1729                this.equityCalculator.addEventListener("refine_pull_out_equity_calculation", (e) => {
1730                    this.setEquityModalAttributes()
1731                    this.equityModal.setAttribute('selected_tab', 2)
1732                    this.equityModal.setAttribute('style', 'display:flex;');
1733                })
1734
1735                this.equityCalculator.addEventListener("refine_purchase_new_home_calculation", (e) => {
1736                    this.setEquityModalAttributes()
1737                    this.equityModal.setAttribute('selected_tab', 3)
1738                    this.equityModal.setAttribute('style', 'display:flex;');
1739                })
1740
1741                this.equityCalculator.addEventListener("inputs_changed", (e) => {
1742                    this.homeSalePrice = e.detail.homeSalePrice;
1743                    this.remainingLoanBalance = e.detail.remainingLoanBalance
1744
1745                    this.setEquityModalAttributes()
1746                })
1747
1748                this.equityModal.addEventListener('on_close', () => {
1749                    this.equityModal.setAttribute('style', 'display:none;');
1750                })
1751
1752                this.equityModal.addEventListener('get_your_free_offer_clicked', () => {
1753                    this.disableButtons()
1754
1755                    contact(
1756                        lead?.data?.fname, lead?.data?.lname, lead?.data?.email, lead?.data?.phone, "I'd like to discu
1756ss a cash offer for my home.",
1757                    )
1758                    .then((response) => {
1759                        if (response.status == false) {
1760                            toast.show("Error sending message", true);
1761                        }
1762                        else {
1763                            toast.show("Discuss cash offer request sent! Your agent will be in touch shortly.");
1764                        }
1765                    })
1766                    .catch((error) => {
1767                        toast.show("Error sending message", true);
1768                    })
1769                    .finally(() => {
1770                        Pubsub.publish('verifyMyHomeModalClickedCompleted')
1771                    })
1772                })
1773
1774                this.equityModal.addEventListener('unlock_my_equity_clicked', () => {
1775                    this.disableButtons()
1776                    Pubsub.publish("verifyMyHomeModalClicked");
1777                })
1778
1779                this.equityModal.addEventListener('debt_calculator_clicked', () => {
1780                })
1781
1782                this.equityModal.addEventListener('refine_equity_estimate_clicked', () => {
1783                })
1784
1785                Pubsub.subscription('verifyMyHomeModalClickedCompleted' , () => {
1786                    this.enableButtons()
1787                }).subscribe();
1788                 
1789            }
1790
1791            disableButtons() {
1792                this.equityModal.setAttribute('disable_buttons', true)
1793            }
1794
1795            enableButtons() {
1796                this.equityModal.setAttribute('disable_buttons', false)
1797            }
1798
1799            setEquityModalAttributes() {
1800                this.equityModal.setAttribute('home_sale_price', this.homeSalePrice)
1801                this.equityModal.setAttribute('remaining_loan_balance',this.remainingLoanBalance)
1802            }
1803
1804            setAttributes(sellPrice) {
1805                this.homeSalePrice = sellPrice
1806                this.remainingLoanBalance = 0;
1807                this.equityCalculator.setAttribute('home_sale_price', sellPrice)
1808                this.equityModal.setAttribute('home_sale_price', sellPrice)
1809            }
1810
1811            show() {
1812                this.equityCalculator.setAttribute('style', 'display:block');
1813                this.equityCalculator.parentElement.setAttribute('style', 'display:block');
1814            }
1815
1816            hide() {
1817                this.equityCalculator.setAttribute('style', 'display:none');
1818                this.equityCalculator.parentElement.setAttribute('style', 'display:none');
1819            }
1820
1821                
1822        }
1823
1824        class Page {
1825            constructor(blueroofMiddlewareApi){
1826                this.isNewReport = false
1827                this.isEditingReport = false
1828                this.isReportSaved = false
1829                this.reportId = ''
1830                this.isViewingReport = false
1831                this.isReportLoaded = false
1832                this.lead = {}
1833                this.agent = {}
1834                this.mlsIds = []
1835                this.marketReport = {}
1836
1837                this.bedOffset = 1
1838                this.bathOffset = 1
1839                this.sqftOffset = 500
1840                this.yearBuiltOffset = 1
1841
1842                this.authorizationData = JSON.parse(atob(blueroofMiddlewareApi.apiKey.split('.')[1]));
1843                this.is_blueroof_person = this.authorizationData?.is_blueroof_person;
1844
1845                window.onresize = function(event) {
1846                    Pubsub.publish('window_resize')
1847                };
1848            }
1849
1850            structureAddressSuggestions(suggestedLocations) {
1851                let suggestions = [];
1852                suggestedLocations.forEach((suggestion) => {
1853                    let splitLocation =  suggestion.description.split(', ')
1854                    let address = ''
1855                    let city = ''
1856                    let state = ''
1857                    let postalCode = ''
1858                    if(suggestion.types[0] == 'locality'){
1859                        city = splitLocation[0];
1860                        state = splitLocation[1];
1861                    }
1862                    else if(suggestion.types[0] == 'street_address' || suggestion.types[0] == 'route' || suggestion.types[0] == 'premise'){
1863                        
1864                        if(splitLocation.length == 4){
1865                             address = splitLocation[0];
1866                             city = splitLocation[1];
1867                             state = splitLocation[2];  }
1868                        else{
1869                             address = splitLocation[1];
1870                             city = splitLocation[2];
1871                             state = splitLocation[3];
1872                        }
1873
1874                        // if zip code is included in the address split it from state
1875                        if(state.length > 2) {
1876                            postalCode = state.split(' ').slice(1).join(' ')
1877                            state = state.split(' ')[0];
1878                        }
1879                    }
1880                    else if(suggestion.types[0] == 'postal_code'){
1881                        
1882                         city = splitLocation[0];
1883                         state = splitLocation[1].split(' ')[0];
1884                         postalCode = splitLocation[1].split(' ')[1];
1885                    }
1886
1887                    suggestions.push({text:suggestion.description,address:address,city:city,state:state,postalCode:postalCode, suggestType: suggestion.types[0] });
1888                    
1889                })
1890
1891                return suggestions;
1892            }
1893        }
1894
1895        class Estimates {
1896            constructor(blueroofMiddlewareApi) {
1897                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
1898            }
1899
1900            getSlipstreamEstimate = async (state, city, address, zipCode) => {
1901
1902                const slipstreamData = {
1903                    deliveryLine: address || "",
1904                    city: city || "",
1905                    state: state || "",
1906                    zip: zipCode || ""
1907                }
1908
1909                let response = await this.blueroofMiddlewareApi.get
1909SlipStreamAVM(slipstreamData)
1910                this.slipstreamEstimate = response?.result?.valuations?.general?.EMV || 0
1911                this.lotSize = response?.result?.attributes?.size || 0
1912                this.beds = response?.result?.attributes?.beds || 0
1913                this.baths = response?.result?.attributes?.baths || 0
1914                this.sqft = response?.result?.attributes?.size || 0
1915                this.yearBuilt = response?.result?.attributes?.yearBuilt || 0
1916
1917                return this.slipstreamEstimate
1918            }
1919
1920            getLandVoiceEstimate = async(state, city, address, zipCode) => {
1921                const landVoiceData = {
1922                    streetAddress: address || "",
1923                    city: city || "",
1924                    state: state || "",
1925                    postalCode :zipCode || ""
1926                }
1927
1928                let response = await this.blueroofMiddlewareApi.getLandVoiceAvm(landVoiceData)
1929                this.landVoiceEstimate = response?.avm_records?.slice(-1)[0].estimated_value || 0
1930                this.address = response?.property_info?.address_full
1931                this.lotSize = response?.property_info?.acreage || 0
1932                this.beds = response?.property_info?.bedrooms || 0
1933                this.baths = response?.property_info?.bathrooms || 0
1934                this.sqft = response?.property_info?.square_footage || 0
1935
1936                return this.landVoiceEstimate
1937
1938            }
1939
1940            getZillowEstimate = async (state, city, address, zipCode) => {
1941                const zillowData = {
1942                    address: address || "",
1943                    city: city || "",
1944                    state: state || "",
1945                    postalCode: zipCode || ""
1946                }
1947
1948                let response = await this.blueroofMiddlewareApi.getZestimate(zillowData)
1949                this.zillowEstimate = response?.bundle[0]?.zestimate || 0
1950
1951                return this.zillowEstimate
1952            }
1953
1954            getMlsEstimate = async (beds, baths, sqft, streetAddress, city, state, zipCode) => {
1955
1956                const mlsData = {
1957                    maxBeds : beds,
1958                    maxBaths : baths,
1959                    maxSqft : sqft,
1960                    streetAddress : `${streetAddress}, ${city}, ${state} ${zipCode}`
1961                }
1962
1963                let response = await this.blueroofMiddlewareApi.getMlsValue(mlsData)
1964                this.mlsEstimate = response?.averagePrice;
1965                
1966                return this.mlsEstimate
1967 
1968            }
1969        }
1970
1971        class EditHomeFactsModal {
1972            constructor(blueroofMiddlewareApi, page) {
1973                let _this = this;
1974                this.element = document.querySelector('place-edithomefactsmodal');
1975                this.page = page;
1976                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
1977                this.reportData = null;
1978
1979                this.blueroofMiddlewareApi.getMLSIds().then((data) => {
1980                    this.mlsIds = data
1981                })
1982
1983                this.element.addEventListener('close_button', (e) => {
1984                    _this.hide();
1985                });
1986
1987                this.element.addEventListener("cancel_button", (e) => {
1988                    _this.hide();
1989                });
1990
1991                this.element.addEventListener('save_facts', (e) => {
1992                    const { beds, baths, sqft, year_built } = e.detail;
1993
1994                    let yearBuiltValue = year_built ? parseInt(year_built) : null;
1995                    let changes = {
1996                        ...e.detail,
1997                        year_built: yearBuiltValue
1998                    };
1999
2000                    let reportData = this.reportData;
2001                    let slipStreamData = {
2002                        min_beds: parseInt(beds) - (page?.bedOffset || 1), 
2003                        max_beds: parseInt(beds) + (page?.bedOffset || 1),
2004                        min_baths: parseInt(baths) - (page?.bathOffset || 1), 
2005                        max_baths: parseInt(baths) + (page?.bathOffset || 1),
2006                        min_area: parseInt(typeof sqft == "string" ? sqft.replace(/,/g,'') : sqft) - (page?.sqftOffset || 500), 
2007                        max_area: parseInt(typeof sqft == "string" ? sqft.replace(/,/g,'') : sqft) + (page?.sqftOffset || 500),
2008                        min_year_built: parseInt(year_built) - (page?.yearBuiltOffset || 1),
2009                        max_year_built: parseInt(year_built) + (page?.yearBuiltOffset || 1)
2010                    };
2011
2012                    Pubsub.publish('editHomeFactsModalSaved', {reportData, slipStreamData, changes});
2013                    _this.hide();
2014                });
2015            }
2016
2017            setHomeFacts(data) {
2018               let page = this.page;
2019                this.reportData = data;
2020                const { min_beds, min_baths, min_area, min_year_built } = data;
2021                this.element.setAttribute('home_facts', JSON.stringify({beds: min_beds + (page?.bedOffset || 1), baths: min_baths + (page?.bathOffset || 1), sqft: min_area + (page?.sqftOffset || 500), year_built: min_year_built + page.yearBuiltOffset > 1 ? min_year_built + (page?.yearBuiltOffset || 1) : null}));
2022            }
2023
2024            show() {
2025                this.element.setAttribute('style', 'display:flex')
2026            }
2027
2028            hide() {
2029                this.element.setAttribute('style', 'display:none')
2030            }
2031        }
2032
2033        class IsThisYourHomeModal {
2034            constructor(blueroofMiddlewareApi) {
2035                this.element = document.querySelector('place-isthisyourhome');
2036                
2037                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
2038
2039                this.element.addEventListener('set_bed', (e) => {
2040                    this.bed = e.detail 
2041                })
2042
2043                this.element.addEventListener('set_bath', (e) => {
2044                    this.bath = e.detail 
2045                })
2046
2047                this.element.addEventListener('set_sqft', (e) => {
2048                    this.sqft = e.detail
2049                })
2050
2051                this.element.addEventListener('set_year_built', (e) => {
2052                    this.yearBuilt = e.detail
2053                })
2054
2055                this.element.addEventListener('on_close', (e) => {
2056                    this.hide()
2057                })
2058
2059                this.element.addEventListener('save_inputs', (e) => {
2060                    this.bed = e.detail.beds;
2061                    this.bath = e.detail.baths;
2062                    this.sqft = e.detail.sqft;
2063                    let slipStreamData = e.detail
2064                    let reportData = this.reportData
2065
2066                    this.hide();
2067                    Pubsub.publish('slipstream_is_this_your_home_create',{ slipStreamData, reportData}) 
2068                })
2069                
2070            }
2071
2072            setImage(imageUrl){
2073                this.element.setAttribute('image_url', imageUrl);
2074            }
2075
2076            setAddress(address){
2077                this.element.setAttribute('address', address);
2078            }
2079            
2080            setIsThisYourHome(beds,baths,sqft){
2081                this.element.setAttribute('is_this_your_home', JSON.stringify({beds,baths,sqft}))
2082            }
2083
2084            setYearBuilt(yearBuilt){
2085                this.element.setAttribute('year_built', yearBuilt)
2086            }
2087
2088            setPrice(price){
2089                this.element.setAttribute('price', price)
2090            }
2091
2092            show(reportData) {
2093                this.reportData = reportData;
2094                this.element.setAttribute('style', 'display:flex')
2095            }
2096
2097            hide() {
2098                this.element.setAttribute('style', 'display:none');
2099            }
2100        }
2101
2102        class SaveReportModal {
2103            constructor(){
2104                this.nextReportData = null;
2105
2106                this.element = document.querySelector('place-savereportpopup');
2107                
2108                this.element.addEventListener('close_button', (e) => {
2109                    this.hide()
2110                })
2111
2112                this.element.addEventListener('cancel_button', (e) => {
2113                    this.hide()
2114                })
2115
2116                this.element.addEventListener('save_info', (e) => {
2117                    Pubsub.publish('save_report_modal_save_clicked', e.detail, this.nextReportData);
2118                    this.nextReportData = null;
2119                })
2120            }
2121
2122            clearValues(value) {
2123                this.element.setAttribute('reset_values', value);
2124            }
2125
2126            isLoading(value){
2127                this.element.setAttribute('loading', value)
2128            }
2129
2130            show(reportData) {
2131                if (reportData) {
2132                    this.nextReportData = reportData;
2133                }
2134                this.element.setAttribute('style', 'display:flex')
2135                this.clearValues(false);
2136            }
2137
2138            hide() {
2139                this.element.setAttribute('style', 'display:none');
2140                this.clearValues(true);
2141            }
2142        }
2143
2144        class UpdateReportModal {
2145            constructor(){
2146                this.reportData = null;
2147                this.element = document.querySelector('place-updatereportpopup');
2148                
2149                this.element.addEventListener('close_button', (e) => {
2150                    this.hide()
2151                })
2152
2153                this.element.addEventListener('cancel_button', (e) => {
2154                    this.hide()
2155                })
2156
2157                this.element.addEventListener('save_info', (e) => {
2158                    const { report_title, report_frequency } = e.detail;
2159
2160                    let changes = e.detail;
2161                    let reportData = this.reportData;
2162                    let frequency = '';
2163
2164                    switch(report_frequency){
2165                        case 'Never':
2166                            frequency = 'never';
2167                            break;
2168                        case 'Every Week':
2169                            frequency = 'every_week';
2170                            break;
2171                        case 'Every 2 Weeks':
2172                            frequency = 'every_2_weeks';
2173                            break;
2174                        case 'Every Month':
2175                            frequency = 'every_month';
2176                            break;
2177                        case 'Quarterly':
2178                            frequency = 'quarterly';
2179                            break;
2180                        case 'Annually':
2181                            frequency = 'annually';
2182                            break;
2183                    }
2184
2185                    let inputData = {
2186                        name: report_title,
2187                        report_name: report_title,
2188                        recurring_frequency: frequency
2189                    };
2190
2191                    Pubsub.publish('editNameAndFrequencySaved', {reportData, inputData, changes});
2192                    this.hide();
2193                })
2194
2195                this.element.setAttribute('report_name', 'Market Report');
2196            }
2197
2198            setReportName(reportName) {
2199                this.element.setAttribute('report_name', reportName);
2200            }
2201
2202            setReportFrequency(recurringFrequency) {
2203                this.element.setAttribute('email_frequency', recurringFrequency);
2204            }
2205
2206            isLoading(value){
2207                this.element.setAttribute('loading', value)
2208            }
2209
2210            show(reportData) {
2211                if (reportData) {
2212                    this.reportData = reportData;
2213                    let recurringFrequency = reportData.recurring_frequency;
2214                    recurringFrequency = recurringFrequency.replace(/_/g, ' ');
2215                    recurringFrequency = toTitleCase(recurringFrequency);
2216
2217                    this.setReportName(reportData.report_name);
2218                    this.setReportFrequency(recurringFrequency);
2219                }
2220
2221                this.element.setAttribute('style', 'display:flex');
2222
2223                function toTitleCase(str) {
2224                    return str.replace(/\w\S*/g, function(txt){
2225                        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
2226                    });
2227                }
2228            }
2229
2230            hide() {
2231                this.element.setAttribute('style', 'display:none');
2232            }
2233        }
2234
2235        class FrequencyModal {
2236            constructor() {
2237                this.element = document.querySelector('place-frequencymodal');
2238
2239                this.element.addEventListener('on_close_press', (e) => {
2240                    this.hide()
2241                })
2242
2243                this.element.addEventListener('on_save_press', (e) => {
2244                    Pubsub.publish('report_frequency_modal_save_clicked', e.detail)
2245                }) 
2246            }
2247
2248            show(reportData) {
2249                let description = `How often would you like to receive email updates on the ${reportData.name} report?`
2250                this.element.setAttribute('description', description);
2251                this.element.setAttribute('style', 'display:flex')
2252            }
2253
2254            hide() {
2255                this.element.setAttribute('style', 'display:none');
2256            }
2257        }
2258
2259        class DoesMyHomeCompare {
2260            constructor(blueroofMiddlewareApi){
2261                this.element = document.querySelector('place-doesmyhomecompare');
2262                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
2263                this.address = ''
2264
2265                this.element.addEventListener('on_selected_location', (e) => {
2266                    this.address =  e.detail
2267                })
2268
2269                this.element.addEventListener('on_change', (e) => {
2270                    if(e.detail.length > 0){
2271                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
2272                            
2273                            let suggestions = page.structureAddressSuggestions(suggest.predictions)
2274                            this.element.setAttribute('data', JSON.stringify(suggestions));
2275                        })
2276                    }
2277                })
2278
2279                this.element.addEventListener('on_search', () => {
2280                    if (page.isNewReport) {
2281                        Pubsub.publish("save_report", this.address);
2282                    } else {
2283                        Pubsub.publish('create_market_report_selected_location', {selectedLocation: this.address});
2284                    }
2285                })
2286            }
2287
2288            clearInput(value) {
2289                this.element.setAttribute('reset_values', value);
2290            }
2291        }
2292
2293        class OwnAnotherHome {
2294                
2295            constructor(blueroofMiddlewareApi) {
2296                
2297                    
2298                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
2299                this.element = document.querySelector('place-ownanotherhome');
2300                
2301                this.element.addEventListener("on_change_text", (e) => {
2302                    if(e.detail.length > 0){
2303                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
2304
2305                            let suggestions = page.structureAddressSuggestions(suggest.predictions)
2306                            this.element.setAttribute('data', JSON.stringify(suggestions));
2307                        })
2308                    }
2309                    
2310                });
2311
2312                this.element.addEventListener("on_selected_location", (e) => {
2313                    if (page.isNewReport) {
2314                        Pubsub.publish("save_report", e.detail);
2315                    } else {
2316                        Pubsub.publish('create_market_report_selected_location', {selectedLocation: e.detail});
2317                    }
2318                });
2319
2320                document.querySelector("place-createmarketreport input")?.setAttribute("autocomplete","do-not-autofill");
2321            } 
2322            
2323            clearInput(value) {
2324                this.element.setAttribute('reset_values', value);
2325            }
2326
2327            show() {
2328                this.element.setAttribute('style', 'display:flex;z-index:100')
2329            }
2330
2331            hide() {
2332                this.element.setAttribute('style', 'display:none');
2333            }
2334        }
2335
2336        class GetYourHo
2336meCTA {
2337            constructor(blueroofMiddlewareApi, page) {
2338
2339                this.element = document.querySelector('place-getyourhomecta');
2340                this.blueroofMiddlewareApi = blueroofMiddlewareApi;
2341                this.page = page
2342                this.address = ''
2343                this.currentCTAType = ''
2344
2345                this.element.addEventListener('on_selected_location', (e) => {
2346                    this.address =  e.detail
2347                })
2348
2349                this.element.addEventListener('save_inputs', (e) => {
2350
2351                    if(this.currentCTAType == 'sell_my_home'){
2352                        Pubsub.publish('contact_my_agent_sell_my_home', e.detail);
2353                    }else if(this.currentCTAType == 'contact_us'){
2354                        Pubsub.publish('contact_my_agent_contact_us', e.detail);
2355                    }
2356                })
2357
2358                this.element.addEventListener('on_close', () => {
2359                    this.hide()
2360                })
2361
2362                this.element.addEventListener('on_change', (e) => {
2363                    if(e.detail.length > 0){
2364                        this.blueroofMiddlewareApi.googlePlaceSuggestions(e.detail).then((suggest) => {
2365                            
2366                            let suggestions = this.page.structureAddressSuggestions(suggest.predictions)
2367                            this.element.setAttribute('data', JSON.stringify(suggestions));
2368                        })
2369                    }
2370                })
2371
2372                this.element.addEventListener('on_search', (e) => {
2373                    this.hide()
2374                    Pubsub.publish('create_market_report_selected_location', {selectedLocation: this.address});
2375                })
2376            }
2377            
2378            setData(data) {
2379                this.element.setAttribute('get_home_value', JSON.stringify(data))
2380            }
2381
2382            showGetHomeValueCTA() {
2383                this.element.setAttribute('is_get_home_value_form', true)
2384                this.element.setAttribute('is_sell_my_home_form', false)
2385                this.element.setAttribute('is_contact_us_form', false)
2386
2387                this.element.setAttribute('style', 'display:flex')
2388            }
2389
2390            showSellMyHomeCTA() {
2391
2392                this.currentCTAType = 'sell_my_home'
2393
2394                this.element.setAttribute('is_get_home_value_form', false)
2395                this.element.setAttribute('is_sell_my_home_form', true)
2396                this.element.setAttribute('is_contact_us_form', false)
2397
2398                this.element.setAttribute('style', 'display:flex')
2399            }
2400
2401            showContactUsCTA() {
2402
2403                this.currentCTAType = 'contact_us'
2404
2405                this.element.setAttribute('is_get_home_value_form', false)
2406                this.element.setAttribute('is_sell_my_home_form', false)
2407                this.element.setAttribute('is_contact_us_form', true)
2408
2409                this.element.setAttribute('style', 'display:flex')
2410            }
2411
2412            hide() {
2413                this.element.setAttribute('style', 'display:none');
2414            }
2415
2416             
2417        }
2418
2419        class messagingEmitter extends Messaging.BaseEmitter {
2420                
2421            newMessage(message) {
2422                Pubsub.publish('messaging_emitter_new_message', message);
2423            }
2424        }
2425
2426        const blueroofMiddlewareApi = new BlueroofMiddlewareApi();
2427        const page = new Page(blueroofMiddlewareApi);
2428
2429        let url = 'https://messaging.brivity.com'
2430        const messaging = new Messaging.Service(url, blueroofMiddlewareApi.apiKey, new messagingEmitter());
2431
2432        (async () => {
2433            let lead =  await blueroofMiddlewareApi.getLeadBasicInfo();
2434            let agent = await blueroofMiddlewareApi.getAgentProfile(lead.data?.brivity_agent_id);
2435            let mlsIds = await blueroofMiddlewareApi.getMLSIds(lead.data?.brivity_agent_id);
2436            
2437
2438            page.lead = lead.data;
2439            page.agent = agent.data;
2440            page.mlsIds = mlsIds
2441
2442            const menu = new Menu(page?.is_blueroof_person || false, page?.agent, blueroofMiddlewareApi.baseUrl, blueroofMiddlewareApi.apiKey);
2443            const createMarketReport = new CreateMarketReport(blueroofMiddlewareApi, page);
2444            const pageSubHeader = new PageSubHeader();
2445            const reportSection = new ReportSection(blueroofMiddlewareApi);
2446            const reportListingBrivityHomeApp = new ReportListingBrivityHomeApp();
2447            const reportViewBrivityHomeApp = new ReportViewBrivityHomeApp();
2448            const deleteMarketReportModal = new DeleteMarketReportModal(blueroofMiddlewareApi);
2449            const marketReportModal = new MarketReportModal(blueroofMiddlewareApi, page);
2450            const loadingModal = new LoadingModal();
2451            const savedReportSection = new SavedReportSection();
2452            const viewReportSection = new ViewReportSection();
2453            const marketReport = new MarketReport(blueroofMiddlewareApi);
2454            const estimatedHomeValue = new EstimatedHomeValue();
2455            const emptyMarketReport = new EmptyMarketReport(blueroofMiddlewareApi, page);
2456            const estimates = new Estimates(blueroofMiddlewareApi);
2457            const saveReportModal = new SaveReportModal();
2458            const updateReportModal = new UpdateReportModal();
2459            const isThisYourHomeModal = new IsThisYourHomeModal(blueroofMiddlewareApi);
2460            const frequencyModal = new FrequencyModal();
2461            const editHomeFactsModal = new EditHomeFactsModal(blueroofMiddlewareApi, page);
2462            const verifyHomeEstimateModal = new VerifyHomeEstimateModal();
2463            const otherEstimatesModal = new OtherEstimatesModal();
2464            const mlsErrorModal = new MLSErrorModal();
2465            const mlsErrorMarketReportModal = new MLSErrorMarketReportModal();
2466            const sendMessage = new SendMessage(); 
2467            const instantOfferCard = new InstantOfferCard();
2468            const maps = new Maps();
2469            const getYourHomeCTA = new GetYourHomeCTA(blueroofMiddlewareApi,page);
2470            const homeEquityCalculator = new HomeEquityCalculator(lead)
2471            const doesMyHomeCompare = new DoesMyHomeCompare(blueroofMiddlewareApi);
2472            const ownAnotherHome = new OwnAnotherHome(blueroofMiddlewareApi);
2473
2474            function loadReport (value, showLoading) {
2475                doesMyHomeCompare.clearInput(value);
2476                ownAnotherHome.clearInput(value);
2477                if (showLoading) {
2478                    loadingModal.show();
2479                } else {
2480                    loadingModal.hide();
2481                }
2482            };
2483
2484            function handleScreenWidthSubHeaderButtons (pageSubHeader, condition, mobileMenuButtonParam) {
2485                if (screen.width < 768) {
2486                    if (condition) {
2487                        pageSubHeader.hideGetHomeValueButton();
2488                        pageSubHeader.showMobileMoreMenuButton(mobileMenuButtonParam);
2489                    }
2490                    pageSubHeader.hideContactUsButton();
2491                    pageSubHeader.hideSellMyHomeButton();
2492                    pageSubHeader.hideMoreMenuButton();
2493                    pageSubHeader.showMobileMoreMenuButton(mobileMenuButtonParam);
2494                } else {
2495                    pageSubHeader.showContactUsButton();
2496                    pageSubHeader.showSellMyHomeButton();
2497                    pageSubHeader.showMoreMenuButton();
2498                    pageSubHeader.hideMobileMoreMenuButton();
2499                }
2500            }
2501
2502            function handleMenuItemStyles () {
2503                if (screen.width < 768) {
2504                    pageSubHeader.setMenuItemStyles('w-[160px] right--16');
2505                } else {
2506                    pageSubHeader.setMenuItemStyles('w-[216px] right--15');
2507                }
2508            }
2509
2510
2511            Pubsub.subscription('window_resize', () => {
2512
2513                if(window.screen.width < 600){
2514                    pageSubHeader.element.setAttribute('dynamic_button_menu_styles', 'w-[160px] right--16')
2515                }
2516                else if(window.screen.width < 768) {
2517                    pageSubHeader.element.setAttribute('inner_container_styles', 'flex-row')
2518                    pageSubHeader.element.setAttribute('dynamic_button_menu_styles', 'w-[160px] right--16')
2519                }
2520                else {
2521                    pageSubHeader.element.setAttribute('button_container_styles', 'flex-row')
2522                    pageSubHeader.element.setAttribute('button_styles', '')
2523                    pageSubHeader.element.setAttribute('inner_container_styles', 'flex-row')
2524                    pageSubHeader.element.setAttribute('dynamic_button_menu_styles', 'w-[216px] right--15')
2525                }
2526
2527                if (page.isViewingReport && !page.isNewReport){
2528                    if (page.marketReport.street_address == null && screen.width > 768) {
2529                        pageSubHeader.invertButtonStyles("SellMyHome", false);
2530                        pageSubHeader.invertButtonStyles("MoreMenuButton", true);
2531                        pageSubHeader.showGetHomeValueButton();
2532                    }  else {
2533                        pageSubHeader.invertButtonStyles("SellMyHome", true);
2534                        pageSubHeader.hideGetHomeValueButton();
2535                    }
2536
2537                    handleScreenWidthSubHeaderButtons(pageSubHeader, page.marketReport.street_address != null, page.marketReport.street_address != null);
2538                }
2539
2540            }).subscribe();
2541
2542            Pubsub.subscription('contact_my_agent_sell_my_home', (data) =>{
2543                getYourHomeCTA.hide();
2544                const message = `
2545                    <p>
2546                    <br/>Street Address: ${data?.street_address}
2547                    <br/>City: ${data?.city}
2548                    <br/>State: ${data?.state}
2549                    <br/>Beds: ${data?.beds}
2550                    <br/>Baths: ${data?.baths}
2551                    <br/>Square Feet: ${data?.square_feet}
2552                    <br/>Year Built: ${data?.year_built}
2553                    <br/>Additional Comments: ${data?.message}
2554                    </p>
2555                `
2556
2557                contact(
2558                    data?.first_name, data?.last_name, data?.email_address, data?.phone_number, message, 'contact_form'
2559                )
2560                .then((response) => {
2561                    toast.show("Contact information sent. Your agent will be in touch shortly. ");
2562                })
2563                .catch((error) => {
2564                    toast.show("Error sending email", true);
2565                });
2566
2567            }).subscribe();
2568
2569            Pubsub.subscription('contact_my_agent_contact_us', (data) =>{
2570                getYourHomeCTA.hide();
2571                const message = `
2572                    <p>
2573                    <br/>Additional Comments: ${data?.message}
2574                    </p>
2575                `
2576                contact(
2577                    data?.first_name, data?.last_name, data?.email_address, data?.phone_number, message, 'contact_form'
2578                )
2579                .then((response) => {
2580                    toast.show("Contact information sent. Your agent will be in touch shortly. ");
2581                })
2582                .catch((error) => {
2583                    toast.show("Error sending email", true);
2584                });
2585
2586                
2587            }).subscribe();
2588
2589            Pubsub.subscription('mapLinkPressed', (e) => {
2590                const url = `/search#?q_limit=36&mlsId=${page.mls
2590Ids}&multi_search=${page.marketReport.city}, ${page.marketReport.state_abbreviation}&multi_cat=CityState&status=1|3&q_sort=createdAt-&q_offset=0`
2591                window.open(url , '_blank');
2592            }).subscribe();
2593
2594            Pubsub.subscription('seeOtherEstimatesClicked', (e) => {
2595                otherEstimatesModal.show();
2596            }).subscribe();
2597
2598            Pubsub.subscription('verifyMyHomeEstimateClicked' , (e) => {
2599                verifyHomeEstimateModal.show();
2600            }).subscribe();
2601
2602            Pubsub.subscription('verifyMyHomeModalClicked' , (e) => {
2603                verifyHomeEstimateModal.hide();
2604                contact(
2605                        lead?.data?.fname, lead?.data?.lname, lead?.data?.email, lead?.data?.phone, "I'd like to verify my home's estimate.",
2606                    )
2607                    .then((response) => {
2608                        if (response.status == false) {
2609                            toast.show("Error sending message", true);
2610                        }
2611                        else {
2612                            toast.show("Professional home valuation request sent! Your agent will be in touch shortly.");
2613                        }
2614                    })
2615                    .catch((error) => {
2616                        toast.show("Error sending message", true);
2617                    })
2618                    .finally(() => {
2619                        Pubsub.publish('verifyMyHomeModalClickedCompleted')
2620                    })
2621            }).subscribe();
2622
2623            Pubsub.subscription('getComparativeAnalysis' , (e) => {
2624                contact(
2625                        lead?.data?.fname, lead?.data?.lname, lead?.data?.email, lead?.data?.phone, "I’d like a Comparative Market Analysis report.",
2626                    )
2627                    .then((response) => {
2628                        if (response.status == false) {
2629                            toast.show("Error sending message", true);
2630                        }
2631                        else {
2632                            toast.show("Comparative market analysis request sent! Your agent will be in touch shortly. ");
2633                        }            
2634                    })
2635                    .catch((error) => {
2636                        toast.show("Error sending message", true);
2637                    });  
2638            }).subscribe();
2639
2640            Pubsub.subscription('unlockMyEquity' , (e) => {
2641                contact(
2642                        lead?.data?.fname, lead?.data?.lname, lead?.data?.email, lead?.data?.phone, "I’d like to discuss using my equity.",
2643                    )
2644                    .then((response) => {
2645                        if (response.status == false) {
2646                            toast.show("Error sending message", true);
2647                        }
2648                        else {
2649                            toast.show("Equity request sent! Your agent will be in touch shortly. ");
2650                        }            
2651                    })
2652                    .catch((error) => {
2653                        toast.show("Error sending message", true);
2654                    });  
2655            }).subscribe();
2656
2657            Pubsub.subscription('messaging_emitter_new_message', (message) => {
2658                toast.show('New message from ' + message.createdByAlias)
2659            }).subscribe();
2660
2661            Pubsub.subscription('sendBrivityHomeAppInvite', (info, id = null) => {
2662                if (id && id == "reportViewGetHomeApp") {
2663                    reportViewBrivityHomeApp.setIsLoading(true);
2664                    blueroofMiddlewareApi.getBrivityHomeAppInvite(info).then((data) => {
2665                        reportViewBrivityHomeApp.setIsLoading(false);
2666                        if (data.error) {
2667                            toast.show('Error sending invite', true)
2668                        } else {
2669                            toast.show('Invite has been sent!')
2670                            if (organizationUuid) {
2671                                blueroofMiddlewareApi.addTag(organizationUuid, "HomeAppfromMR");  
2672                            } 
2673                        }
2674                    }).catch((error) => {
2675                        reportViewBrivityHomeApp.setIsLoading(false);
2676                        toast.show('Error sending invite', true)
2677                    })  
2678                } else {
2679                    blueroofMiddlewareApi.getBrivityHomeAppInvite(info).then((data) => {
2680                        if (data.error) {
2681                            toast.show('Error sending invite', true)
2682                        } else {
2683                            toast.show('Invite has been sent!')
2684                            if (organizationUuid) {
2685                               blueroofMiddlewareApi.addTag(organizationUuid, "HomeAppfromMR");
2686                            }
2687                        }
2688                    }).catch((error) => {
2689                        toast.show('Error sending invite', true)
2690                    })
2691                }
2692            }).subscribe()
2693                
2694            Pubsub.subscription('edit_criteria', (report) => {
2695                marketReportModal.setMarketReportData(report || page.marketReport);
2696                marketReportModal.show();
2697            }).subscribe()
2698
2699            Pubsub.subscription("update_report_menu_pressed",(report) => { updateReportModal.show(report) }).subscribe()
2700
2701            Pubsub.subscription("delete_report_menu_pressed",(e) => { deleteMarketReportModal.show(e) }).subscribe()
2702           
2703            Pubsub.subscription("market_reports", (saved_report_length) => { 
2704                if(saved_report_length == 0){
2705                    emptyMarketReport.show();
2706                }
2707                else{
2708                    createMarketReport.show();
2709                    $("#gethomeapp-parent").css('margin', '70px 0 32px');
2710                }
2711            }).subscribe()
2712
2713            Pubsub.subscription('top_header_back_pressed', (e) => {
2714                this.location.href=`./reports`
2715            }).subscribe();
2716
2717            Pubsub.subscription('top_header_menu_item_pressed', (menuItem) => {
2718                if(menuItem == 'Delete Report') {
2719                    deleteMarketReportModal.show(page.reportId)
2720                }
2721                if(menuItem == 'Manage Alerts') {
2722                    frequencyModal.show(page.marketReport);
2723                }
2724                if(menuItem == 'Sell My Home') {
2725                    Pubsub.publish('sell_my_home')
2726                }
2727                if(menuItem == 'Contact Us') {
2728                    Pubsub.publish('contact_us')
2729                }
2730                if(menuItem == 'Get Home Value') {
2731                    Pubsub.publish('get_home_value')
2732                }
2733            }).subscribe();
2734        
2735            Pubsub.subscription('open_market_report', (newReportData) => {
2736                (async () => {
2737
2738                    loadingModal.show();
2739                    savedReportSection.hide();
2740                    pageSubHeader.showTopHeader();
2741                    
2742                    viewReportSection.show();
2743                    doesMyHomeCompare.clearInput(true);
2744
2745                    let data  = {}
2746
2747                    if(newReportData.isNewReport){
2748                        page.isNewReport = true;
2749                        lifecycle.removeUnsavedChanges('unsavedChanges');
2750                        lifecycle.addUnsavedChanges('unsavedChanges');
2751                        data = newReportData.reportData;
2752
2753                        pageSubHeader.showSaveReportButton();
2754
2755                        marketReportModal.showReportName(false)
2756
2757                        pageSubHeader.hideGetHomeValueButton();
2758                        pageSubHeader.hideSellMyHomeButton();
2759                        pageSubHeader.hideContactUsButton();
2760                        pageSubHeader.hideMoreMenuButton();
2761                        pageSubHeader.hideMobileMoreMenuButton();
2762                    } else {
2763                        
2764                        if(!page.isReportLoaded){
2765                            data = await blueroofMiddlewareApi.getMarketReport(newReportData.reportId);
2766                            page.isReportLoaded = true;
2767                        }
2768                        else{
2769                            data = newReportData.reportData
2770                        }
2771
2772                        if(data?.search_type == 'area'){
2773                            pageSubHeader.hideEditCriteriaButton();
2774                            pageSubHeader.showGetHomeValueButton();
2775                            pageSubHeader.invertButtonStyles("MoreMenuButton", true);
2776                            pageSubHeader.invertButtonStyles("SellMyHome", false);
2777                        } else {
2778                            pageSubHeader.invertButtonStyles("MoreMenuButton", false);
2779                            pageSubHeader.invertButtonStyles("SellMyHome", true);
2780                        }
2781                        
2782                        handleMenuItemStyles();
2783                        handleScreenWidthSubHeaderButtons(pageSubHeader, data?.search_type == 'area', data?.search_type != 'area');
2784
2785                        marketReportModal.showReportName(true)
2786                    }
2787
2788                    page.reportId = data.id
2789                    page.marketReport = data;
2790
2791
2792                    data?.listings?.forEach(function (listing) {
2793                        let image = []
2794
2795                        listing.images.forEach(function (listingImage) {
2796                            image.push ({uri: listingImage}) 
2797                        })
2798
2799                        listing.image = image
2800                        listing.address = listing.street_address
2801                        listing.sqft = listing.area
2802                        
2803                    });
2804
2805
2806                    let reportData = {
2807                        "report_name" : data.name,
2808                        "city" : data.city,
2809                        "property_type" : data.property_type,
2810                        "min_price": parseInt(data.min_price),
2811                        "max_price": parseInt(data.max_price),
2812                        "min_beds": parseInt(data.min_beds),
2813                        "max_beds": parseInt(data.max_beds),
2814                        "min_baths": parseInt(data.min_baths),
2815                        "max_baths": parseInt(data.max_baths),
2816                        "min_area": parseInt(data.min_area),
2817                        "max_area": parseInt(data.max_area),
2818                        "min_lot": parseInt(data.min_lot),
2819                        "max_lot": parseInt(data.max_lot),
2820                        "min_year_built": parseInt(data.min_year_built),
2821                        "max_year_built": parseInt(data.max_year_built),
2822                    }
2823
2824                    marketReportModal.setMarketReportData(reportData)
2825
2826
2827                    let isMarketReport = true
2828
2829                    if(data.street_address != null ) {
2830                        isMarketReport = false
2831                    }
2832
2833                    pageSubHeader.setTopHeaderTitle('Market Reports')
2834                    if(!isMarketReport){
2835
2836                        let title = ''
2837                        if(data?.street_address && data?.city){
2838                            title = `${data?.street_address ?? ""} ${data?.city ?? ""}, ${data?.state_abbreviation ?? ""} ${data?.postal_code ?? ""}`
2839                        }
2840                        else{
2841                            title = data?.name
2842                        }
2843
2844                        pageSubHeader.setTitle(data?.search_location_name || title) 
2845                        pageSubHeader.setCriteria(`${data?.property_type}${data.radius ?  ` - ${parseInt(data.radius)} mile radius` : ''}`)
2846
2847 
2848                        let beds =  isThisYourHomeModal?.bed  || data?.min_beds + page.bedOffset || estimates?.beds || 0
2849                        let baths = isThisYourHomeModal?.bath  || data?.min_baths + page.bathOffset || estimates?.baths || 0
2850                        let sqft = isThisYourHomeModal?.sqft  || data?.min_area + page.sqftOffset || estimates?.sqft || 0
2851                        let address = estimates?.address || data?.street_address
2852                        let yearBuilt = data?.min_year_built + page.yearBuiltOffset > 1 && data?.min_year_built + page.yearBuiltOffset || estimates?.yearBuilt || 0
2853
2854                        let landVoiceEstimate = estimates.getLandVoiceEstimate(data?.state_abbreviation, data?.city, data?.street_address, data?.postal_code)
2855                        let zillowEstimate = estimates.getZillowEstimate(data?.state_abbreviation, data?.city, address, data?.postal_code)
2856
2857                        if (data && data.street_address) {
2858                            data.street_address = data.street_address.toLowerCase().replace(/\b\w/g, function (char) {
2859                                return char.toUpperCase();
2860                            });
2861                        }
2862
2863                        if (data && data.city) {
2864                            data.city = data.city.toLowerCase().replace(/\b\w/g, function (char) {
2865                                return char.toUpperCase();
2866                            });
2867                        }
2868
2869                        if (data && data.state_abbreviation) {
2870                            data.state_abbreviation = data.state_abbreviation.toUpperCase();
2871                        }
2872
2873                        Promise.allSettled([landVoiceEstimate, zillowEstimate]).then( async (values) => {
2874                            divisorCount = 0
2875                            if(values[0].value > 0)
2876                            {
2877                                divisorCount++
2878                            }
2879                            if(values[1].value > 0)
2880                            {
2881                                divisorCount++
2882                            }
2883                            
2884
2885                            let averageEstimate 
2886                            if(divisorCount > 0){
2887                                averageEstimate = parseInt((parseInt(values[0]?.value || 0
2887) + parseInt(values[1]?.value || 0)) / divisorCount)
2888                                otherEstimatesModal.setAttomEstimate(parseInt(values[0].value))
2889                                otherEstimatesModal.setZillowEstimate(parseInt(values[1].value))
2890                            }
2891                            else{
2892                                let mlsEstimate = 0
2893                                try {
2894                                    mlsEstimate = await estimates.getMlsEstimate(
2895                                        beds,
2896                                        baths,
2897                                        sqft,
2898                                        data?.street_address,
2899                                        data?.city,
2900                                        data?.state_abbreviation,
2901                                        data?.postal_code
2902                                    )
2903                                } catch (e) {
2904
2905                                }
2906
2907                                if( mlsEstimate > 0)
2908                                {
2909                                    averageEstimate = mlsEstimate
2910                                    otherEstimatesModal.setMlsEstimate(parseInt(mlsEstimate))
2911                                }
2912                                else{
2913                                    averageEstimate = 350000
2914                                }
2915                            }
2916
2917                            let equityLow = parseInt(averageEstimate * 0.2 )
2918                            let equityHigh = parseInt(averageEstimate * 0.3)
2919                            let estimatedHomeSellPrice = averageEstimate
2920                            let remainingBalance = 50000
2921                            let estimatedHomeValueOffset = Math.round(averageEstimate * 0.10)
2922                            let homeAddress = `${data?.street_address ?? ""} ${data?.city ?? ""}, ${data?.state_abbreviation ?? ""} ${data?.postal_code ?? ""}`
2923
2924                            marketReport.homeDetails.setAttribute('beds', beds);
2925                            marketReport.homeDetails.setAttribute('baths', baths);
2926                            marketReport.homeDetails.setAttribute('sqft', sqft);
2927                            marketReport.homeDetails.setAttribute('build_year', yearBuilt);
2928
2929                            if (estimates?.sqft) {
2930                                estimatedHomeValue.setSquareFeet(estimates?.sqft);
2931                            } else {
2932                                estimatedHomeValue.setPricePerSquareFoot(Math.trunc(averageEstimate / sqft) || 0);
2933                            }
2934
2935                            estimatedHomeValue.setEstimatedHomeEquity(averageEstimate)
2936                            estimatedHomeValue.setAddress(homeAddress || "")
2937                            estimatedHomeValue.setLowEndPrice(averageEstimate - estimatedHomeValueOffset)
2938                            estimatedHomeValue.setHighEndPrice(averageEstimate + estimatedHomeValueOffset)
2939                            estimatedHomeValue.setTemperature(50 || 0)
2940
2941                            homeEquityCalculator.setAttributes(estimatedHomeSellPrice) 
2942
2943                            marketReport.estimatedHomeValue.parentElement.setAttribute('style', 'display:block')
2944
2945                            pageSubHeader.hideGetHomeValueButton();
2946
2947                            marketReport.doesMyHomeCompare.parentElement.setAttribute('style', 'display:none')
2948                            marketReport.ownAnotherHome.parentElement.setAttribute('style', 'display:block')
2949
2950                            instantOfferCard.show();
2951                            homeEquityCalculator.show();
2952
2953                            pageSubHeader.hideGetHomeValueButton();
2954
2955                            loadReport(false, false);
2956
2957                        });
2958                    }
2959                    else {
2960                        marketReport.homeDetails.parentElement.setAttribute('style', 'display:none')
2961
2962                        let title = ''
2963                        if(data?.city){
2964                            title = `${data?.city}, ${data?.state_abbreviation} ${data?.postal_code}`
2965                        }
2966                        else{
2967                            title = data?.name
2968                        }
2969
2970                        pageSubHeader.setTitle(data?.search_location_name || title)
2971                        pageSubHeader.setCriteria(`${data?.property_type}${data.radius ?  ` - ${parseInt(data.radius)} mile radius` : ''}`)
2972
2973
2974                        marketReport.estimatedHomeValue.parentElement.setAttribute('style', 'display:none')
2975                        marketReport.ownAnotherHome.parentElement.setAttribute('style', 'display:none')
2976                        marketReport.doesMyHomeCompare.parentElement.setAttribute('style', 'display:block')
2977                        
2978                        instantOfferCard.hide();
2979
2980
2981                        homeEquityCalculator.hide()
2982
2983                        loadReport(false, false)
2984                    }
2985
2986                    if(data?.city && data?.state_abbreviation){
2987                        marketReport.marketTrends.setAttribute('area', `${data?.city}, ${data?.state_abbreviation}`);
2988                    }
2989                    
2990                    marketReport.marketTrends.setAttribute('items',`[
2991                        { "icon": "dollar-sign", "label": "Average Price", "value": ${data?.trends?.trend_average_price || 0}},
2992                        { "icon": "zap", "label": "New Homes", "value":${data?.trends?.trend_new_listings || 0}},
2993                        { "icon": "tag", "label": "Sold Homes", "value": ${data?.trends?.trend_sold_listings || 0}},
2994                        { "icon": "calendar", "label": "Days On Market", "value": ${data?.trends?.trend_average_dom || 0}}
2995                    ]`)
2996
2997                    if (data?.hide_market_temp){
2998                        marketReport.temperature.parentElement.setAttribute('style', 'display:none')
2999                    } else {
3000                        marketReport.temperature.setAttribute('temperature', data?.market_temp || 50)
3001                        marketReport.temperature.setAttribute('city', data?.city || '')
3002                        marketReport.temperature.setAttribute('state', data?.state_abbreviation || '')
3003                    };
3004
3005                    if(data?.geo_json){    
3006                        let geo = JSON.parse(data?.geo_json)?.coordinates[0] || [];
3007                        let geoArray = []
3008
3009                        for(let i = 0; i < geo.length; i++){
3010                            geoArray.push({lat: geo[i][1], lng: geo[i][0]})
3011                        }
3012
3013                        marketReport.map.setAttribute('polygon_points', JSON.stringify(geoArray))
3014                    }
3015
3016                    marketReport.map.setAttribute('default_zoom', 
301612)
3017                    marketReport.map.setAttribute('area', data.city || '')
3018                    marketReport.map.setAttribute('state', data.state_abbreviation || '')
3019                    
3020                    const mlsData = data.listings.map(listing => ({
3021                    ...listing,
3022                    creator: `Listed with ${listing.listing_office}`, // Map listing_office to creator
3023                    }));
3024
3025                    marketReport.map.setAttribute('mls_data', JSON.stringify(mlsData));
3026
3027                    page.isViewingReport = true;
3028                     
3029                })();  
3030
3031            }).subscribe();
3032
3033            Pubsub.subscription('create_market_report_selected_location', async (data) => {
3034
3035                loadReport(true, true);
3036                const selectedLocation = data.selectedLocation;
3037                const city = selectedLocation?.city;
3038                const state = selectedLocation?.state;
3039                const postalCode = selectedLocation?.postalCode;
3040                const address = selectedLocation?.address;
3041
3042                let reportData = {
3043                    property_type: 'Residential',
3044                    city: city,
3045                    postal_code: postalCode,
3046                    state_abbreviation: state,
3047                    street_address: address,
3048                    search_location_name: selectedLocation?.text
3049                }
3050
3051                let addressData = {
3052                    streetAddress: address,
3053                    city: city,
3054                    state: state
3055                } 
3056
3057                if (reportData.city === '' && reportData.state_abbreviation === '' && reportData.postal_code === '') {
3058                    const suggestedLocation = selectedLocation?.text;
3059                    const locationArr = suggestedLocation.split(', ');
3060
3061                    let streetAddress, city, statePostal, stateAbbr, postalCode;
3062
3063                    if (locationArr.length < 4) {
3064                        [ city, statePostal ] = selectedLocation?.text.split(', ');
3065                        [ stateAbbr, postalCode ] = statePostal.split(' ');
3066                    } else {
3067                        [ streetAddress, city, statePostal ] = selectedLocation?.text.split(', ');
3068                        [ stateAbbr, postalCode ] = statePostal.split(' ');
3069                    }
3070
3071                    reportData = {
3072                        ...reportData,
3073                        street_address: streetAddress?.trim() || '',
3074                        city: city?.trim() || '',
3075                        state_abbreviation: stateAbbr?.trim() || '',
3076                        postal_code: postalCode?.trim() || ''
3077                    }
3078
3079                    addressData = {
3080                        streetAddress: streetAddress?.trim() || '',
3081                        city: city?.trim() || '',
3082                        state: stateAbbr?.trim() || ''
3083                    }
3084                }
3085
3086                const geoCodeAddress = await blueroofMiddlewareApi.getGeocodeAddress(addressData);
3087                reportData.postal_code = geoCodeAddress?.postalCode;
3088
3089                let getAvmData = false;
3090                const allowedTypes = [
3091                    'street_address',
3092                    'route',
3093                    'premise',
3094                    'subpremise',
3095                    'geocode'
3096                ];
3097
3098                if (allowedTypes.includes(selectedLocation.suggestType) && reportData.street_address) {
3099                    getAvmData = true;
3100                }
3101                
3102                if(getAvmData) {
3103
3104                    const landVoiceData = {
3105                        streetAddress: reportData?.street_address || address,
3106                        city: reportData?.city || city,
3107                        state: reportData?.state_abbreviation || state,
3108                        postalCode: reportData?.postal_code || postalCode
3109                    }
3110
3111                    const avm = await blueroofMiddlewareApi.getLandVoiceAvm(landVoiceData)
3112
3113                    const beds = avm?.property_info?.bedrooms
3114                    const baths = avm?.property_info?.bathrooms
3115                    const sqft = avm?.property_info?.square_footage
3116                    const yearBuilt = avm?.property_info?.year_built
3117                    const avmAddress = avm?.property_info?.address_full
3118                    const latitude = avm?.property_info?.latitude
3119                    const longitude = avm?.property_info?.longitude
3120                    const price =  avm?.avm_records?.length > 0 ? avm?.avm_records?.slice(-1)[0].estimated_value : 350000
3121
3122
3123                    estimates.beds = beds;
3124                    estimates.baths = baths;
3125                    estimates.sqft = sqft;
3126                    estimates.address = avmAddress
3127                    estimates.yearBuilt = yearBuilt;
3128
3129                    reportData.min_beds = beds - page.bedOffset;
3130                    reportData.max_beds = beds + page.bedOffset;
3131                    reportData.min_baths = baths - page.bathOffset;
3132                    reportData.max_baths = baths + page.bathOffset;
3133                    reportData.min_area = sqft - page.sqftOffset;
3134                    reportData.max_area = sqft + page.sqftOffset;
3135                      
3136                    reportData.recurring_frequency = "every_2_weeks",
3137                        
3138                    blueroofMiddlewareApi.homeValueReport(reportData).then((report) => {
3139                        localStorage.setItem('marketReportData', JSON.stringify(report));
3140                        window.location = `${window.origin}/myportal/report?market_report_id=${report.id}`
3141                    }).catch((error) => {
3142                        loadReport(false, false);
3143                    })
3144                        
3145                }
3146                else{
3147                    blueroofMiddlewareApi.previewMarketReport(reportData).then((data) => {
3148                        data.recurring_frequency = "every_2_weeks",
3149                        data.name = data?.location,
3150                        blueroofMiddlewareApi.createMarketReport(data).then((report) => {
3151                            localStorage.setItem('marketReportData', JSON.stringify(report));
3152                            window.location = `${window.origin}/myportal/report?market_report_id=${report.id}`
3153                        }).catch((error) => {
3154                            loadReport(false, false);
3155                        })
3156                    }).catch((error) => {
3157                        loadReport(false, false);
3158                    })
3159                }
3160
3161            }).subscribe()
3162
3163            Pubsub.subscription('delete_market_report', (reportId) => {
3164                
3165                blueroofMiddlewareApi.deleteMarketReport(reportId).then((data) => {
3166                    document.getElementById(reportId).remove();
3167                    deleteMarketReportModal.hide()
3168
3169                    savedReportSection.show();
3170                    viewReportSection.hide();
3171                    pageSubHeader.hideTopHeader();
3172                    pageSubHeader.hideEditCriteriaButton();
3173                    pageSubHeader.hideSaveReportButton();
3174                    pageSubHeader.hideMoreMenuButton();
3175                    marketReportModal.hide();
3176                    pageSubHeader.setTitle('Market Reports');
3177
3178                    page.isNewReport = false;
3179                    page.isEditingReport = false;
3180                    page.isReportSaved = false;
3181                    page.reportId = '';
3182                    page.isViewingReport = false;
3183                    page.isReportLoaded = false
3184                    
3185                    toast.show('Market Report Deleted')
3186                })
3187            }).subscribe()
3188
3189            Pubsub.subscription('update_report_details', (reportData) => {
3190
3191                loadReport(true, true);
3192                const changes = reportData.changes;
3193                const marketReport = reportData.marketReport;
3194                let updatedReportData = {};
3195
3196                updatedReportData.id = changes?.id || marketReport?.id;
3197                updatedReportData.name = changes?.report_name || marketReport?.report_name || 'Preview Market Report';
3198                updatedReportData.report_name = changes?.report_name || marketReport?.report_name || '';
3199                updatedReportData.mls_data_source_id = marketReport.mls_data_source_id;
3200                updatedReportData.recurring_frequency = changes?.recurring_frequency || marketReport?.recurring_frequency || 'every_2_weeks';
3201                updatedReportData.property_type = changes?.property_type || marketReport?.property_type;
3202                updatedReportData.radius = parseInt(changes.radius) || parseInt(marketReport.radius);
3203                updatedReportData.search_type = changes?.search_type || marketReport?.search_type;
3204                updatedReportData.city = changes?.city || marketReport?.city;
3205                updatedReportData.state_abbreviation = changes?.state_abbreviation || marketReport?.state_abbreviation;
3206                updatedReportData.street_address = changes?.street_address || marketReport?.street_address;
3207                updatedReportData.postal_code = changes?.postal_code || marketReport?.postal_code;
3208                // these are broken out into if statements because
3209                // parseInt("0") return false and parseInt("1") returns true
3210                // so parseInt(changes.min_bath) || parseInt(marketReport.min_bath) will always
3211                // use the marketReport.min_bath value 
3212                if( changes?.min_baths || changes?.min_baths == 0){
3213                    updatedReportData.min_baths = parseInt(changes.min_baths || 0)
3214                }
3215                else{
3216                    updatedReportData.min_baths = parseInt(marketReport.min_baths)
3217                }
3218
3219                if( changes?.max_baths ){
3220                    updatedReportData.max_baths = parseInt(changes.max_baths)
3221                }
3222                else{
3223                    updatedReportData.max_baths = parseInt(marketReport.max_baths)
3224                }
3225
3226                if( changes?.min_beds || changes?.min_beds == 0){
3227                    updatedReportData.min_beds = parseInt(changes.min_beds || 0)
3228                }
3229                else{
3230                    updatedReportData.min_beds = parseInt(marketReport.min_beds)
3231                }
3232
3233                if( changes?.max_beds ){
3234                    updatedReportData.max_beds = parseInt(changes.max_beds)
3235                }
3236                else{
3237                    updatedReportData.max_beds = parseInt(marketReport.max_beds)
3238                }
3239
3240                if( changes?.min_price ){
3241                    updatedReportData.min_price = parseInt(changes.min_price)
3242                }
3243                else{
3244                    updatedReportData.min_price = parseInt(marketReport.min_price)
3245                }
3246
3247                if( changes?.max_price ){
3248                    updatedReportData.max_price = parseInt(changes.max_price)
3249                }
3250                else{
3251                    updatedReportData.max_price = parseInt(marketReport.max_price)
3252                }
3253
3254                if( changes?.min_area || changes?.min_area == 0 ){
3255                    updatedReportData.min_area = parseInt(changes.min_area || 0)
3256                }
3257                else{
3258                    updatedReportData.min_area = parseInt(marketReport.min_area)
3259                }
3260
3261                if( changes?.max_area ){
3262                    updatedReportData.max_area = parseInt(changes.max_area)
3263                }
3264                else{
3265                    updatedReportData.max_area = parseInt(marketReport.max_area)
3266                }
3267
3268                if( changes?.min_lot ){
3269                    updatedReportData.min_lot = parseInt(changes.min_lot)
3270                }
3271                else{
3272                    updatedReportData.min_lot = parseInt(marketReport.min_lot)
3273                }
3274
3275                if( changes?.max_lot ){
3276                    updatedReportData.max_lot = parseInt(changes.max_lot)
3277                }
3278                else{
3279                    updatedReportData.max_lot = parseInt(marketReport.max_lot)
3280                }
3281
3282                if(marketReport.search_type == 'area'){
3283                    updatedReportData.geo_json = changes?.geo_json || marketReport?.geo_json;
3284                            
3285                }
3286                else {
3287                    updatedReportData.lat_lng = changes?.lat_lng || marketReport?.lat_lng;
3288                }
3289
3290                let currentMarketReportTile = document.getElementById(updatedReportData.id);
3291
3292                blueroofMiddlewareApi.updateMarketReport(updatedReportData.id, updatedReportData).then((data) => {
3293                    page.marketReport = {
3294                        ...page.marketReport,
3295                        ...updatedReportData
3296                    };
3297                    
3298                    let displayData = {
3299                        ...reportData.marketReport,
3300                        "report_name" : updatedReportData.name,
3301                    };
3302
3303                    currentMarketReportTile?.setAttribute('market_report', JSON.stringify(displayData));
3304                    toast.show('Market Report Saved')
3305
3306                    if(updatedReportData.recurring_frequency != marketReport.recurring_frequency){
3307                        let data = {reportName: updatedReportData.name, dripSchedule:updatedReportData.recurring_frequency}
3308                        blueroofMiddlewareApi.addMarketReportFrequencyUpdatedTimelineEvent(data )
3309                    }
3310                }).catch((e) => {
3311                    toast.show('Error saving market report', true)
3312                })
3313
3314                loadReport(false, false);
3315
3316            }).subscribe()
3317
3318            Pubsub.subscription('save_report_modal_save_clicked', (data, nextReportData) => {
3319
3320
3321                let name = data.report_title
3322                let frequency;
3323
3324                    //valid options for frequency  { never, every_week, every_2_weeks, every_month, quarterly, annually }
3325                switch(data.report_frequency){
3326                    case 'Never':
3327                        frequency = 'never';
3328                        break;
3329                    case 'Every Week':
3330                        frequency = 'every_week';
3331                        break;
3332                    case 'Every 2 Weeks':
3333                        frequency = 'every_2_weeks';
3334                        break;
3335                    case 'Every Month':
3336                        frequency = 'every_month';
3337                        break;
3338                    case 'Quarterly':
3339                        frequency = 'quarterly';
3340                        break;
3341                    case 'Annually':
3342                        frequency = 'annually';
3343                        break;
3344                }
3345                
3346                let newSavedMarketReport = {
3347                    mls_data_source_id : page?.marketReport?.mls_data_source_id,
3348                    property_type: page?.marketReport?.property_type,
3349                    radius: parseInt(page?.marketReport?.radius),
3350                    search_type: page?.marketReport?.search_type,
3351                    recurring_frequency : frequency,
3352                    geo_json: page?.marketReport?.geo_json,
3353                    city: page?.marketReport?.city,
3354                    lat_lng: page?.marketReport?.lat_lng,
3355                    min_area: parseInt(page?.marketReport?.min_area ),
3356                    min_baths: parseInt(page?.marketReport?.min_baths ),
3357                    min_beds: parseInt(page?.marketReport?.min_beds ),
3358                    min_lot: parseInt(page?.marketReport?.min_lot ),
3359                    min_price: parseInt(page?.marketReport?.min_price ),
3360                    min_year_built: parseInt(page?.marketReport?.min_year_built),
3361                    max_area: parseInt(page?.marketReport?.max_area),
3362                    max_baths: parseInt(page?.marketReport?.max_baths),
3363                    max_beds: parseInt(page?.marketReport?.max_beds),
3364                    max_lot: parseInt(page?.marketReport?.max_lot),
3365                    max_price: parseInt(page?.marketReport?.max_price),
3366                    max_year_built: parseInt(page?.marketReport?.max_year_built),
3367                    name : name,
3368                    postal_code: page?.marketReport?.postal_code,
3369                    state_abbreviation: page?.marketReport?.state_abbreviation,
3370                    street_address: page?.marketReport?.street_address
3371
3372                }
3373
3374                  
3375
3376                if(page.isNewReport){
3377                    blueroofMiddlewareApi.createMarketReport(newSavedMarketReport).then((data) => {
3378                        lifecycle.removeUnsavedChanges('unsavedChanges');
3379                        saveReportModal.hide();
3380                        toast.show('Market Report Saved')
3381
3382                        pageSubHeader.hideEditCriteriaButton();
3383                        pageSubHeader.hideSaveReportButton();
3384
3385                        if(data?.search_type == 'area'){
3386                            pageSubHeader.showGetHomeValueButton();
3387                            pageSubHeader.invertButtonStyles("SellMyHome", false);
3388                            pageSubHeader.invertButtonStyles("MoreMenuButton", true);
3389                        } else {
3390                            pageSubHeader.invertButtonStyles("SellMyHome", true);
3391                            pageSubHeader.invertButtonStyles("MoreMenuButton", false);
3392                        }
3393
3394                        handleMenuItemStyles();
3395                        handleScreenWidthSubHeaderButtons(pageSubHeader, data?.search_type == 'area', data?.search_type != 'area');
3396
3397                        page.isReportLoaded = true;
3398                        page.isNewReport = false;
3399                        page.marketReport = data;
3400                        page.reportId = data.id;
3401
3402                    }).catch((e) => {
3403                        saveReportModal.hide();
3404                        toast.show('Error saving market report', true)
3405                    })
3406                    if (nextReportData) {
3407                        Pubsub.publish('create_market_report_selected_location', {selectedLocation: nextReportData});
3408                    }
3409                }
3410                else{
3411                    blueroofMiddlewareApi.updateMarketReport(page.reportId, newSavedMarketReport).then((data) => {
3412                        lifecycle.removeUnsavedChanges('unsavedChanges');
3413                        saveReportModal.hide();
3414                        toast.show('Market Report Saved')
3415                    }).catch((e) => {
3416                        saveReportModal.hide();
3417                        toast.show('Error saving market report', true)
3418                    })
3419                }
3420            }).subscribe()
3421
3422            Pubsub.subscription('save_report', (data) => {
3423                Pubsub.publish('save_report_modal_save_clicked', {report_title:  page.marketReport.location, report_frequency:'Every 2 Weeks'}, data)
3424            }).subscribe()
3425
3426            Pubsub.subscription('report_frequency_modal_save_clicked', (reportFrequency) => {
3427
3428                let frequency;
3429
3430                //valid options for frequency  { never, every_week, every_2_weeks, every_month, quarterly, annually }
3431                switch(reportFrequency){
3432                    case 'Never':
3433                        frequency = 'never';
3434                        break;
3435                    case 'Every Week':
3436                        frequency = 'every_week';
3437                        break;
3438                    case 'Every 2 Weeks':
3439                        frequency = 'every_2_weeks';
3440                        break;
3441                    case 'Every Month':
3442                        frequency = 'every_month';
3443                        break;
3444                    case 'Quarterly':
3445                        frequency = 'quarterly';
3446                        break;
3447                    case 'Annually':
3448                        frequency = 'annually';
3449                        break;
3450                }
3451
3452                page.marketReport.recurring_frequency = frequency
3453
3454                blueroofMiddlewareApi.updateMarketReport(page.reportId, page.marketReport).then((data) => {
3455                    lifecycle.removeUnsavedChanges('unsavedChanges');
3456                    toast.show('Market Report Saved')
3457                    frequencyModal.hide();
3458                }).catch((e) => {
3459                    toast.show('Error saving market report', true)
3460                })
3461                
3462            }).subscribe()
3463
3464            Pubsub.subscription('slipstream_is_this_your_home_create', (data) => {
3465
3466                const beds = parseInt(data?.slipStreamData?.beds || 0);
3467                const baths = parseInt(data?.slipStreamData?.baths || 0);
3468                const sqft = parseInt(data?.slipStreamData?.sqft?.toString().replaceAll(',','') || 0);
3469                const yearBuilt = parseInt(data?.slipStreamData?.year_built || 0);
3470                
3471                let reportData = data.reportData
3472
3473                if(beds > 0){
3474                    reportData.min_beds = beds - page.bedOffset;
3475                    reportData.max_beds = beds + page.bedOffset;
3476                }
3477                if(baths > 0){
3478                    reportData.min_baths = baths - page.bathOffset;
3479                    reportData.max_baths = baths + page.bathOffset;
3480                }
3481                if(sqft > 0){
3482                    reportData.min_area = sqft - page.sqftOffset;
3483                    reportData.max_area = sqft + page.sqftOffset;
3484                }
3485                
3486                loadingModal.show(); 
3487
3488                blueroofMiddlewareApi.homeValueReport(reportData).then(report => {
3489                    localStorage.setItem('marketReportData', JSON.stringify(report));
3490                    window.location = `${window.origin}/myportal/report?market_report_id=${report.id}`
3491                }).catch((error) => {
3492                    loadReport(false, false);
3493                })
3494
3495            }).subscribe()
3496
3497            Pubsub.subscription('editHomeFactsClicked', (report) => {                
3498                if(page.marketReport.search_type == 'area'){
3499                    marketReportModal.show();
3500                }   
3501                else{
3502                    editHomeFactsModal.setHomeFacts(report || page.marketReport);
3503                    editHomeFactsModal.show();
3504                }  
3505            }).subscribe();
3506
3507            Pubsub.subscription('editHomeFactsModalSaved', (data) => {
3508                const { beds, baths, sqft, year_built } = data.changes;
3509
3510                marketReport.homeDetails.setAttribute('beds', parseInt(beds));
3511                marketReport.homeDetails.setAttribute('baths', parseInt(baths));
3512                marketReport.homeDetails.setAttribute('sqft', sqft);
3513                marketReport.homeDetails.setAttribute('build_year', parseInt(year_built));
3514
3515                Pubsub.publish('update_report_details', {'changes':data.slipStreamData, "marketReport" : data.reportData});
3516            }).subscribe();
3517
3518            Pubsub.subscription('editNameAndFrequencySaved', (data) => {
3519                Pubsub.publish('update_report_details', {'changes':data.inputData, "marketReport" : data.reportData});
3520            }).subscribe();
3521
3522            Pubsub.subscription('previewError', (statusCode) => {
3523                if(statusCode == 410){
3524                    mlsErrorModal.show()
3525                } else if (statusCode == 422){
3526                    mlsErrorMarketReportModal.show()
3527                }
3528                else{
3529                    toast.show('Error building market report preview', true)
3530                }
3531            }).subscribe();
3532
3533
3534            Pubsub.subscription('get_home_value', () => {
3535                getYourHomeCTA.showGetHomeValueCTA();
3536            }).subscribe()
3537
3538            Pubsub.subscription('sell_my_home', () => {
3539                let ctaProps = {
3540                    first_name : page.lead?.fname || '',
3541                    last_name : page.lead?.lname || '',
3542                    email_address : page.lead?.email || '',
3543                    phone_number : page.lead?.phone || '',
3544                    street_address : page.marketReport?.street_address || '',
3545                    city : page.marketReport?.city || '',
3546                    state : page.marketReport?.state_abbreviation || '',
3547                    beds : page.marketReport?.beds || 0,
3548                    baths : page.marketReport?.baths || 0,
3549                    sqft : page.marketReport?.sqft || 0,
3550                    year_built : ''
3551                }
3552                
3553                getYourHomeCTA.setData(ctaProps)
3554                getYourHomeCTA.showSellMyHomeCTA();
3555                 
3556            }).subscribe()
3557
3558            Pubsub.subscription('contact_us', () => {
3559                let ctaProps = {
3560                    first_name : page.lead?.fname || '',
3561                    last_name : page.lead?.lname || '',
3562                    email_address : page.lead?.email || '',
3563                    phone_number : page.lead?.phone || '',
3564                }
3565               
3566                getYourHomeCTA.setData(ctaProps)
3567                getYourHomeCTA.showContactUsCTA();
3568            }).subscribe()
3569
3570            Pubsub.publish('window_resize')
3571
3572            let modalBackdrop = document.getElementsByClassName('center-modal');
3573            for(let i = 0; i < modalBackdrop.length; i++){
3574                modalBackdrop[i].addEventListener('click', (e) => {
3575                    if(e.target == modalBackdrop[i]){
3576                        modalBackdrop[i].style.display = 'none';
3577                    }
3578                });
3579            }
3580
3581            document.addEventListener("click", (e) => {
3582                if(emptyMarketReport.element.getAttribute('data') != '[]') {
3583                    emptyMarketReport.element.setAttribute('data', '[]');
3584                }
3585            });
3586        })();
3587    }
3588});
3589
3590
3591</script>
3591 <div id="myportal-page" style="display:none"> <div style=" position:relative; width:100%;";> <div id="drop-menu-backdrop" style="position:absolute; display:none; top:0; bottom:0; right:0; width:100%; height:100%; display:none;z-index:200"></div> <div style="position:absolute;z-index:110; top:0; bottom:0; "> <place-menu></place-menu> </div> <div id="menu-backdrop" style="position:absolute; display:none; top:0; bottom:0; right:0; width:100%; height:100%; display:none;z-index:205"></div> <div style="position:absolute;z-index:210; top:0; bottom:0; right:0"> <place-marketreportmodal id="market-report-modal"> </place-marketreportmodal> </div> <div class="collection-page" style="flex:1;"> <div class="page-width-parent"> <place-pagesubheader title="MARKET REPORTS" top_header_title="Market Reports" show_top_header="false" show_button="false" ></place-pagesubheader> <div id="saved-report-section"> <place-emptymarketreport image="https://images.brivityidx.com/assets/images/mobile-library-images/empty_house.png" style="display:none" data="[]"></place-emptymarketreport> <div id="report-section" style="display:flex; flex-wrap:wrap; margin-top:24px;" > <place-createmarketreport style="display:none;z-index:100;" data="[]"> </place-createmarketreport> </div> <place-pagination id="reports-pagination" style="display:none"></place-pagination> <div id="gethomeapp-parent" style="margin:0 0 32px"> <place-gethomeappreports id="reportListingViewGetHomeApp" container_styles="bg-[#F9F9F9]"></place-gethomeappreports> </div> </div> <div id="view-report-section" class="report" style="display:none"> <div class="top-element-container"> <place-realtorcontactcta container_styles="border-[#E8E8E8] border-1 rounded-[4px]" image_url="" name="" phone="" email="" > </place-realtorcontactcta> </div> <div id="estimatedHomeValue" class="report-section-container"> <place-estimatedhomevalue v2="true" content_styles="self-center" container_styles="w-full flex flex-col"></place-estimatedhomevalue> </div> <div id="homeDetails" class="report-section-container"> <place-homedetails></place-homedetails> </div> <div id="homeequitycalculator" class="report-section-container"> <place-homeequitycalculator></place-homeequitycalculator> </div> <div class="report-section-container"> <place-instantoffercard id="useEquityCTA" title="Ready to Use Your Equity?" description="Whether you are in the market for a sale, an upgrade, or a refinance, let's talk about your next steps." button_text="Contact Agent" > </place-instantoffercard> </div> <div class="report-section-container"> <place-markettemperatureblock v2="true" container_styles="px-6 border-[#E8E8E8] border-1 rounded-[4px]"> </place-markettemperatureblock> </div> <div class="report-section-container"> <place-doesmyhomecompare v2="true" container_styles="border-[#E8E8E8] border-1 rounded-[4px]" ></place-doesmyhomecompare> </div> <div class="report-section-container"> <place-markettrends container_styles="rounded-[4px] border-[#E8E8E8] border-1" items='[{ "icon": "zap", "label": "New Homes", "value": "0"},{ "icon": "tag", "label": "Sold", "value": "1"}, { "icon": "dollar-sign", "label": "Average", "value": ""}, { "icon": "calendar", "label": "Days On Market", "value": "3"}]'> </place-markettrends> </div> <div class="report-section-container"> <place-instantoffercard id="competitiveSellCTA" title="Want to Be More Competitive When You Sell?" description="Minor home improvements can make a big difference for a buyer. Connect with our team to explore impactful improvements designed to highlight your home's unique features." button_text="Learn More" > </place-instantoffercard> </div> <div class="report-section-container" id="map"> <place-mapblock google_api_key=AIzaSyAjpuNg6WGCMV5rzoJcIP2QmMTVto6hYmc show_sold_price="true" > </place-mapblock> </div> <div id="sendMessage" class="report-section-container"> <place-sendmessage v2="true" container_styles="border-[#E8E8E8] border-1 rounded-[4px]" ></place-sendmessage> </div> <div id="ownAnotherHome" class="report-section-container"> <place-ownanotherhome container_styles="border-[#E8E8E8] border-1 rounded-[4px]"></place-ownanotherhome> </div> <div id="getHomeApp" class="report-section-container"> <place-gethomeapp id="reportViewGetHomeApp" container_styles="rounded-[3px]" column_view="true" v2="true" long_text="true"></place-gethomeapp> </div> </div> </div> </div> </div> <place-getyourhomecta class="center-modal" style="display:none" interest_items='[{"text":"Looking to sell ASAP"},{"text":"Looking to sell (1-3 months)"},{"text":"Looking to sell (3-6 months)"}, {"text":"Looking to sell (6-12 months)"},{"text":"Looking to sell (12+ months)"}, {"text":"Just curious"}]' > </place-getyourhomecta> <place-basicmodal id="delete-market-report-modal" class="center-modal" style="display:none" title="Delete Market Report" sub_title="Deleting this market report will permanently remove it from your account. Are you sure you would like to delete this report?" title_icon="trash" primary_button_text="Delete" tertiary_button_text="Cancel" ></place-basicmodal> <place-basicmodal id="mls-error-modal" class="center-modal" style="display:none" title="Home Value Estimate" sub_title="" title_icon="" primary_button_text="Contact Agent" tertiary_button_text="Close" ></place-basicmodal> <place-basicmodal id="mls-error-market-report-modal" class="center-modal" style="display:none" title="Market Report Unavailable" sub_title="" title_icon="" primary_button_text="Try Again" ></place-basicmodal> <place-basicmodal container_style="w-[412px] h-[292px] rounded-[1px]" id="verify-home-estimate-modal" class="center-modal" style="display:none" title="Verify My Home Estimate" sub_title="Your agent will be notified and will reach out shortly to verify your home estimate!" title_icon="" primary_button_text="Verify My Home Estimate" tertiary_button_text="Cancel" stacked_buttons="true" ></place-basicmodal> <place-loadingmodal title="Hang tight while we build your report" image="https://cdn1.brivityidx.com/assets/images/mobile-library-images/loadinghouse.gif" sub_title="" class="center-modal" style="display:none"> </place-loadingmodal> <place-useyourequitymodal class="center-modal" style="display:none" ></place-useyourequitymodal> <place-isthisyourhome class="center-modal" style="display:none"></place-isthisyourhome> <place-savereportpopup loading="false" report_name="" class="center-modal" style="display:none" > </place-savereportpopup> <place-updatereportpopup loading="false" report_name="" class="center-modal" style="display:none;" > </place-updatereportpopup> <place-frequencymodal class="center-modal" style="display:none" title="Market Report Frequency" title_icon="clock" menu_items='[{ "text": "Every Week" },{ "text": "Every 2 Weeks" },{ "text": "Every Month" },{ "text": "Quarterly" },{ "text": "Annually" },{ "text": "Never" }]' selected_menu_item="Never" > </place-frequencymodal> <place-edithomefactsmodal class="center-modal" style="display:none" home_facts='{"beds": 3, "baths": 2, "sqft": 1500}' v2="true" ></place-edithomefactsmodal> <place-otherestimates class="center-modal" style="display:none" ></place-otherestimates> </div> <footer id="footer-8n" style="padding: 100px 0px; background-color: rgb(255, 255, 255) !important; outline: none; cursor: inherit;" data-selector="footer"><div class="container"> <div class="row"> <div class="col-sm-4"> <div class="footer-logo-container"> <img class="img-responsive" src="https://images.brivityidx.com/assets/images/uploads/7586/logo-01.png" alt="" data-selector="img" style="border-radius: 0px !important; border-color: rgb(128, 128, 128) !important; border-style: none !important; border-width: 0px !important; height: 70px !important; width: 200px !important; outline: none; cursor: inherit;"></div> <div> <p data-selector="p" style="outline: none; cursor: inherit;"><span class="agent_address_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading">7455 McVay Station Ct</span><br><span class="agent_city_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading">Germantown</span>, <span class="agent_state_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading">TN</span> <span class="agent_zip_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading">38138</span></p> <p data-selector="p" style="outline: none; cursor: inherit;"><a class="agent_phone_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading" href="tel:9016255200" src="tel:" style="outline: none; cursor: inherit;">(901) 625-5200</a><br> </p></div> </div> <div class="col-sm-3"> <hr data-selector="hr" style="outline: none; cursor: inherit;"><h3 class="ediContent" data-selector="h1, h2, h3, h4, h5, h6" style="">Quick Links</h3> <ul class="list-unstyled editContent" style="" data-selector=".editContent"><li data-selector="li" style="outline: none; cursor: inherit;"><a href="/home_value" style="outline: none; cursor: inherit;">See Home Value</a></li> <li data-selector="li" style="outline: none; cursor: inherit;"><a id="top-nav-marketing-plan" data-toggle="modal" data-target="#sell-modal" style="outline: none; cursor: inherit;">Get Marketing Plan</a></li> </ul></div> <div class="col-sm-5"> <hr data-selector="hr" style="outline: none; cursor: inherit;"><h3 class="editContent" data-selector=".editContent" style="outline: none; cursor: inherit;">More</h3> <ul class="list-unstyled" style="outline: none; cursor: inherit;"><li data-selector="li" style="outline: none; cursor: inherit;"><a href="/index" style="outline: none; cursor: inherit;">Home </a></li> <li data-selector="li" style="outline: none; cursor: inherit;"><a href="/why_list_with_us" style="outline: none; cursor: inherit;">Why List with Us?</a></li> </ul></div> <div class="col-sm-5"> <hr data-selector="hr" style="outline: none; cursor: inherit;"><h3 class="editContent" data-selector=".editContent" style="">OUR LOCATIONS</h3> <ul class="list-unstyled" style=""><li data-selector="li" style="outline: none; cursor: inherit;"><a href="/index" style="">Germantown, Collierville, Arlington, Lakeland, Cordova, Bartlett, Memphis </a></li> </ul></div> </div> <div class="row margin-top-40"> <div class="col-sm-4 anchor-col"> <ul class="list-inline social" style="outline: none; cursor: inherit;"><li data-selector="li" style="outline: none; cursor: inherit;"> <a class="agent_facebook_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading" href="https://www.facebook.com/livelovememphis/" target="_blank" style="outline: none; cursor: inherit;"> <svg viewbox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg></a> </li> <li data-selector="li" style="outline: none; cursor: inherit;"> <a class="agent_twitter_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading" href="https://twitter.com/livelovememphis?lang=en" target="_blank" style="outline: none; cursor: inherit;"> <svg viewbox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg></a> </li> <li data-selector="li" style="outline: none; cursor: inherit;"> <a class="agent_instagram_dynamic dynamic_loading dynamic_loading dynamic_loading dynamic_loading dynamic_loading" href="https://www.instagram.com/livelovememphis/?hl=en" target="_blank" style="outline: none; cursor: inherit;"> <svg viewbox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.5" y2="6.5"></line></svg></a> </li> </ul></div> <div class="col-sm-8 anchor-col"> <p class="margin-bottom-0" data-selector="p" style="outline: none; cursor: inherit;"><span class="get_this_year"></span> © The Live Love Memphis Group | Real Estate Agency. <span>All rights reserved.</span></p> <p style="margin: 10px 0px; outline: none; cursor: inherit;" data-selector="p"> <img src="https://images.brivityidx.com/assets/images/uploads/1428/Equal-Housing-Realtor_gray50.png" alt="Equal Housing | Realtor" style="width: 50px; outline: none; cursor: inherit;" data-selector="img">   Each office is independently owned and operated. </p> </div> </div> </div> </footer> </div> <section id="seo-anchor"> <div class="container"> <ul class="powered-by"> <li>Powered by <a class="pb-vendor" href="https://www.brivity.com/"> Brivity</a></li> <li class="pb-admin-login"><a href="https://login.brivityidx.com/login"><span class='pb-admin-login-text'>Admin Log In</span></a></li> </ul> <ul class="seo-anchor-links"> <li><a href="/privacy_policy">Privacy Policy</a></li> <li><a href="/tos">DMCA &amp; Terms of Service</a></li> <li><a id='sitemapUrl' href='/sitemap' style='display: inline;'>Sitemap</a></li> </ul> </div> </section> <input type="hidden" id="hchatbot_settings" data-chatbot-version="1" value="{&quot;chat_position&quot;:&quot;right&quot;,&quot;call_to_action_text&quot;:&quot;Hi there! Please let us know if you have any questions and an agent will reach out to you as soon as possible.&quot;,&quot;initial_message&quot;:&quot;Enter your question below and an agent will be in touch with you.&quot;,&quot;tags&quot;:&quot;IDX Chat&quot;,&quot;version&quot;:&quot;1&quot;}">
3592<!-- chatbot v1 -->
3593<!-- Chatbot drawer container -->
3594<div class="chatbot-drawer-container loading">
3595    <div class="chatbot-content-wrapper">
3596        <div class="chatbot-outside-content">
3597            <div class="chatbot-bubble-message-container cb-hide">
3598                <img src="https://cdn.brivity.com/images/people/16717093/54cd6c6a08d4cae8e13641572de36ac9f72adcfa-original.jpg?1755537591" class="chatbot-agent-img" alt="Agent profile image in chat bubble"/>
3599                <div id="call-to-action" class="bubble-message"></div>
3600                <button type="button" class="chatbox-bubble-close" data-dismiss="modal" aria-label="Close">
3601                    <span aria-hidden="true">&times;</span>
3602                </button>
3603            </div>
3604            <button id="chatbot-open-btn" class="chatbot-open-btn bg-prmry" aria-label="Chatbot Open Button">
3605                <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
3606                    <path d="M20.8 6.35501V16C20.8 17.765 19.365 19.195 17.6 19.195L11.2 19.2L5.755 22.28C5.645 22.365 5.52 22.4 5.4 22.4C5.09 22.4 4.8 22.155 4.8 21.8V19.2H3.2C1.4375 19.2 0 17.765 0 16V6.35501C0 4.63751 1.4375 3.20001 3.2 3.20001H17.6C19.365 3.20001 20.8 4.63751 20.8 6.35501ZM7.2 18.705L10.57 16.8H17.6C18.035 16.8 18.4 16.44 18.4 16V6.40001C18.4 5.96251 18.035 5.60001 17.6 5.60001H3.2C2.7625 5.60001 2.4 5.96251 2.4 6.40001V16C2.4 16.44 2.7625 16.8 3.2 16.8H7.2V18.705ZM12.8 22.4V20.8H15.2V22.4C15.2 22.835 15.56 23.2 16 23.2H21.43L24.8 25.105V23.2H28.8C29.235 23.2 29.6 22.835 29.6 22.4V12.8C29.6 12.365 29.235 12 28.8 12H22.4V9.60001H28.8C30.565 9.60001 32 11.035 32 12.755V22.4C32 24.165 30.565 25.6 28.8 25.6H27.2V28.2C27.2 28.555 26.91 28.8 26.6 28.8C26.48 28.8 26.355 28.765 26.245 28.68L20.8 25.6L16 25.595C14.24 25.595 12.8 24.165 12.8 22.4Z" fill="white"/>
3607                </svg>
3608            </button>
3609        </div>
3610        <div class="chatbot-drawer">
3611            <div class="chatbot-header bg-prmry">
3612                <div class="chatbot-agent-info">
3613                    <img src="https://cdn.brivity.com/images/people/16717093/54cd6c6a08d4cae8e13641572de36ac9f72adcfa-original.jpg?1755537591" class="chatbot-agent-img" alt="Agent profile image in chat header"/>
3614                    <div class="chatbot-agent">
3615                        <h3 class="chatbot-agent-name">Jen Carstensen</h3>
3616                        <h4><span class="chatbot-agent-title">Broker/Owner</span> | <span class="chatbot-agent-company">Real Estate Agency</span></h4>
3617                    </div>
3618                    <a id="chatbot-agent-phone" style="display: none;">(901) 201-0280</a>
3619                </div>
3620                <button id="close-chatbot-drawer" type="button" class="chatbox-modal-close" data-dismiss="modal" aria-label="Close">
3621                    <span aria-hidden="true">&times;</span>
3622                </button>
3623            </div>
3624            <div class="chatbot-body">
3625                <div class="chatbot-message-container">
3626                    <img src="https://cdn.brivity.com/images/people/16717093/54cd6c6a08d4cae8e13641572de36ac9f72adcfa-original.jpg?1755537591" class="chatbot-agent-img" alt="Agent profile image in message"/>
3627                    <h4 id="initial_message" class="chatbot-chat-messages not-loaded"></h4>
3628                    <div class="chatbot-chat-messages loading">
3629                        <span class="typing-indicator">
3630                            <span></span>
3631                            <span></span>
3632                            <span></span>
3633                        </span>
3634                    </div>
3635                </div>
3636                <form id="chatbotForm" class="chatbot-form">
3637                    <input type="name" id="chatbot_fullname" class="chatbox-form-control no-native-focus" placeholder="Full Name"
3638                        pattern="^[A-Za-z'\- ]+ [A-Za-z'\- ]+$"
3639                        required />
3640                    <input type="tel" id="chatbot_phone" class="chatbox-form-control no-native-focus" placeholder="Phone" required />
3641                    <input type="email" id="chatbot_email" class="chatbox-form-control no-native-focus" placeholder="Email"
3642                        pattern="^[^@\s]+@[^@\s]+\.[^@\s]+$"
3643                        required />
3644                    <textarea id="chatbot_message" class="chatbox-form-control chatbot-message" rows="5" name="notes" placeholder="Any Comments or Questions"></textarea>
3645                    <div class="chatbot-consent-container">
3646                        <div class="chatbot-toggle">
3647                                                            By proceeding and clicking the sign up button, you consent to receive calls and texts (SMS/MMS) including marketing and promotional communications, from <span class="agent_name_dynamic"></span>, its affiliates, and agents or vendors acting on their behalf. These 
3647communications may be delivered using an automatic telephone dialing system or by using an artificial or prerecorded voice. Message and data rates may apply. To opt out of text messages, reply STOP. Your consent is not required as a condition of any purchase. By continuing, you also agree to our <a class="opt-out-href" href="/tos">Terms of Use</a> and <a class="opt-out-href" href="/privacy_policy">Privacy Policy</a>.
3648                            </div>
3649                    </div>
3650                    <input type="hidden" id="chatbot_tags">
3651                                    </form>
3652            </div>
3653            <div class="chatbot-footer">
3654                <button type="submit" form="chatbotForm" class="chatbot-send bg-prmry chatbot-btn-disabled" data-dismiss="modal" aria-label="Close" disabled>
3655                    Send 
3656                    <span aria-hidden="true"> 
3657                        <svg class="chatbot-btn-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
3658                            <g clip-path="url(#clip0_2435_997)">
3659                                <path d="M14.6667 1.33331L7.33337 8.66665" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3660                                <path d="M14.6667 1.33331L10 14.6666L7.33337 8.66665L1.33337 5.99998L14.6667 1.33331Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3661                            </g>
3662                            <defs>
3663                                <clipPath id="clip0_2435_997">
3664                                    <rect width="16" height="16" fill="white"/>
3665                                </clipPath>
3666                            </defs>
3667                        </svg>
3668                    </span>
3669                </button>
3670            </div>
3671        </div>
3672    </div>
3673</div> <style>
3674                                .signup-consent-checkbox-section {
3675                                    display: none;
3676                                    flex-direction:column;
3677                                    align-items:flex-start;
3678                                    padding: 6px 0;
3679                                }
3680
3681                                .signup-consent-checkbox-section .checkbox {
3682                                    display:flex; 
3683                                    align-items:flex-start; 
3684                                    justify-content:center; 
3685                                    gap:8px; 
3686                                    padding:0 !important;
3687                                }
3688
3689                                .signup-consent-checkbox-section .checkbox input {
3690                                    position:unset;
3691                                    margin:2px 0 0 0 !important;
3692                                }
3693
3694                                .signup-consent-checkbox-section .checkbox span {
3695                                    color: #666666;
3696                                    font-size: 14px;
3697                                    font-weight: 400;
3698                                    line-height:16px;
3699                                }
3700
3701                                .signup-verbage {
3702                                    text-align:center;
3703                                    font-size:10px;
3704                                    line-height:16px;
3705                                }
3706
3707                                .signup-verbage span {
3708                                   color: #8C8C8C; 
3709                                   font-weight:600; 
3710                                }
3711
3712                                .signup-verbage a {
3713                                    color:#5386E4 !important;
3714                                    font-weight:400;
3715                                }
3716
3717                                .signup-verbage .twilio-enabled-verbage {
3718                                    display:none;
3719                                }
3720
3721                                
3722                                
3723                            </style> <div id="modal-mount" data-modal-bundle="https://cdn1.brivityidx.com/assets/modals/v1/all.html?ck=1790798866"></div>
3723 <div id="credential_picker_container_centered"> <div id="credential_picker_header_bar"> <p><button class="signOrLogBtn" onclick="showSignupModal();">Sign up</button> or <button class="signOrLogBtn" onclick="showLoginModal();">Login</button> another way</p> </div> <div id="credential_picker_header_bar_separator"></div> </div> <place-getyourhomecta id="contact_modal" style="display:none; justify-content: center; align-items: center; position:fixed; background-color:rgba(0,0,0,0.4); left:0; top:0; right:0; bottom:0; z-index: 100;" interest_items='[{"text":"Looking to sell ASAP"},{"text":"Looking to sell (1-3 months)"},{"text":"Looking to sell (3-6 months)"}, {"text":"Looking to sell (6-12 months)"},{"text":"Looking to sell (12+ months)"}, {"text":"Just curious"}]' > </place-getyourhomecta> <place-generictoast appear_from_both="true" container_style="right-1/2 z-200"></place-generictoast> 
3723<script>
3724            document.addEventListener("DOMContentLoaded", () => {
3725                class Toast {
3726                    constructor() {
3727                        this.element = document.querySelector('place-generictoast');
3728                    }
3729
3730                    show(message, error = false, link) {
3731                        var dispatch = function () {
3732                            window.dispatchEvent(
3733                                new CustomEvent("ShowToast", {
3734                                    detail: {
3735                                        text: message,
3736                                        error: error,
3737                                        link: link,
3738                                    },
3739                                })
3740                            );
3741                        };
3742                        if (window.sitebuilderPlaceComponents && window.sitebuilderPlaceComponents.ensureLoaded) {
3743                            window.sitebuilderPlaceComponents
3744                                .ensureLoaded('place-generictoast')
3745                                .then(dispatch)
3746                                .catch(function (err) {
3747                                    console.warn('toast.show fallback (web-components unavailable):', message, err);
3748                                });
3749                        } else {
3750                            dispatch();
3751                        }
3752                    }
3753                }
3754
3755                window.toast = new Toast();
3756            });
3757        </script>
3757 
3757<script src="https://cdn.jsdelivr.net/npm/@turf/[email protected]/turf.min.js"></script>
3757 
3757<script src="https://maps.googleapis.com/maps/api/js?libraries=geocoding,places,marker,drawing&key=AIzaSyAjpuNg6WGCMV5rzoJcIP2QmMTVto6hYmc&map_ids=85c127b7bf0255d9"></script>
3757 
3757<script src="https://cdn1.brivityidx.com/assets/js/build.min.js?ck="></script>
3757 
3757<script src="https://cdn1.brivityidx.com/assets/js/top_bar_v2.min.js?ck="></script>
3757 
3757<script src="https://cdn1.brivityidx.com/assets/js/global_js.min.js?ck=1790798865"></script>
3757 
3757<script>deferScript("https://cdn1.brivityidx.com/assets/js/global_js_defer.min.js?ck=1790798865", 5000);</script>
3757 
3757<script>
3758            function shouldLoadChatbotImmediately() {
3759                const settingsEl = document.getElementById('hchatbot_settings');
3760                if (!settingsEl) return false;
3761
3762                const version = Number(settingsEl.dataset.chatbotVersion);
3763                let isInitialized = false;
3764
3765                try {
3766                    const session = JSON.parse(sessionStorage.getItem('cbSession') || '{}');
3767                    isInitialized = session.chatbotInitialized === true;
3768                } catch (e) {}
3769
3770                return version > 1 && isInitialized;
3771            }
3772        </script>
3772 
3772<script>document.getElementById('hchatbot_settings') && Number(document.getElementById('hchatbot_settings').dataset.chatbotVersion) > 1 && deferScript("https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/9.0.6/signalr.min.js", 0);</script>
3772 
3772<script>document.getElementById('hchatbot_settings') && deferScript(Number(document.getElementById('hchatbot_settings').dataset.chatbotVersion) > 1 ? "https://cdn1.brivityidx.com/assets/js/chatbot_v2.min.js?ck=1790798864" : "https://cdn1.brivityidx.com/assets/js/chatbot.min.js?ck=1790798864", shouldLoadChatbotImmediately() ? 50 : 5000);</script>
3772 
3772<script type="text/javascript" src="https://cdn1.brivityidx.com/assets/js/jquery.geocomplete.min.js"></script>
3772<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.3/js/bootstrapValidator.min.js"></script>
3772<script type="text/javascript" src="https://cdn1.brivityidx.com/assets/js/member_area_components.js"></script>
3772<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/GoogleChromeLabs/[email protected]/dist/lifecycle.es5.js"></script>
3772<script type="text/javascript" src="https://cdn1.brivityidx.com/assets/js/update_agent_info.js"></script>
3772 
3772<script src="https://mobile-component-services-library.s3.amazonaws.com/messaging_service.min.js?ck=1"></script>
vendor: 68 bytes, line 3772
3772 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
3772GTM-K2WGMDL
vendor: 83 bytes, line 3772
3772" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 
3772<script>$(document).ready(function(){$("ul.seo-anchor-links li:nth-of-type(4) a").attr("href","/search")})</script>
3772 
3772<script>$(document).ready(function(){$("#sitemap-listings > div.container > div > div.col-xs-12.col-md-12.col-lg-4.col-lg-push-8.seo-intro > a").attr("href","/search")})</script>
3772</body> </html> 

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.