const obj404 = { template: `

404

Looks like you are lost. Please check your URL again.

` , } app.component('404', obj404); const objAgentprofile = { template: `
Agent Photo

{{ agent.firstName }} {{ agent.lastName }}

{{ agent.title }}

{{ agent.mlsLicense }}

{{ agent.shortBio }}

For Sale marker For Sale
Sold marker Sold
Map
List
{{ property.soldDate ? 'Sold' : 'For Sale' }}
Property Image
{{ property.photos.length }}
{{ property.propertyType }}
Listing Price:
${{ property.price.toLocaleString() }}
{{ property.bedrooms }} bd {{ property.bathrooms }} ba {{ property.sqft.toLocaleString() }} sq ft
{{ property.address }}
{{ property.city }}, {{ property.state }} {{ property.zip }}

Cities

` , name: 'agentprofile', data() { return { agent: { firstName: '', lastName: '', company: '', title: '', phoneNumber: '', emailAddress: '', bio: '', yearsExperience: 0, mlsLicense: '', areasServed: '', photoUrl: '' }, s3BaseUrl: 'https://lptprint.s3.amazonaws.com/', cities: [], properties: [], viewMode: 'map', searchQuery: '', loading: false, propertiesFetched: false, allPropertiesStr: 'All Properties', mapKey: 0 } }, computed: { agentPhoto() { if (this.$root.user.imgurl && this.$root.user.imgurl !== '') { return this.$root.user.imgurl; } return '/images/default-agent-photo.svg'; }, filteredProperties() { if (!this.searchQuery) return this.properties; const query = this.searchQuery.toLowerCase(); return this.properties.filter(property => { const address = `${property.address} ${property.city} ${property.state} ${property.zip}`.toLowerCase(); return address.includes(query); }); } }, watch: { '$route.query.q': { immediate: true, handler(newVal) { this.searchQuery = newVal || ''; this.mapKey++ } } }, async created() { await this.$root.getUserById(this.$root.userId); await this.$root.getAllProperties(this.$root.userId); this.agent = this.$root.user; this.properties = this.$root.properties; this.propertiesFetched = true this.cities = [this.allPropertiesStr,...new Set(this.properties.map(property => property.city))]; // Check for search query in URL const urlParams = new URLSearchParams(window.location.search); this.searchQuery = urlParams.get('q') || ''; this.mapKey++ }, methods: { setSearch(str) { if (str == this.allPropertiesStr) this.searchQuery = '' else this.searchQuery = str this.mapKey++ } } } app.component('agentprofile', objAgentprofile); const objHome = { template: `

` , data() { return { } }, async created() { if (this.$root.vanity?.marketingPropertyId) { this.$root.getAllProperties(this.$root.vanity.appUserId) await Promise.all([ this.$root.getProperty(this.$root.vanity.marketingPropertyId), this.$root.getNhrData(this.$root.vanity.marketingPropertyId) ]) } } } app.component('home', objHome); const objProperty = { template: `

` , data() { return { } }, async created() { this.$root.getAllProperties(this.$root.userId) await Promise.all([ this.$root.getProperty(this.$root.propertyId), this.$root.getNhrData(this.$root.propertyId) ]) } } app.component('property', objProperty); const objAgentContact = { template: `

Request Your Homebuyer Consultation Today

* By submitting this form you opt-in to receive text messages and emails.

Success!

Your information has been submitted. An agent will contact you shortly.

` , data() { return { form: { firstName: '', lastName: '', phone: '', email: '' }, success: false } }, methods: { async submitForm(e) { e.preventDefault() let data; if(this.validateForm()) { try { const response = await fetch(`/api/backend.cfc?method=contactConnectAgent&userId=${this.$root.userId}${this.$root.isDevelopment?'&development=1':''}`, { method: 'POST', body: JSON.stringify(this.form) }); data = await response.json(); if (data.success) { this.clearForm(); this.success = true; this.$root.showToast({ message: 'Thank you! An agent will contact you shortly.', color: 'success' }); } else { this.$root.showToast({ message: 'Failed to send message. Please try again.', color: 'danger' }); } } catch (error) { console.error('Error submitting form:', error); this.$root.showToast({ message: 'An error occurred. Please try again.', color: 'danger' }); } } }, validateForm() { if ( this.form.firstName !== '' && this.form.lastName !== '' && this.form.phone !== '' && this.form.email !== '' ) { return true } else return false }, clearForm() { this.form.firstName = ''; this.form.lastName = ''; this.form.phone = ''; this.form.email = ''; } } } app.component('agent-contact', objAgentContact); const objFooterMain = { template: ` ` , } app.component('footer-main', objFooterMain); const objGlobalMap = { template: `
` , props: { properties: { type: Array, required: true, default: [] }, property: { type: Object, required: false, default: {} }, width: { type: String, required: false, default: '100%' }, height: { type: String, required: false, default: '480px' }, zoomOutToShowAllProperties: { type: Boolean, required: false, default: false }, showPopups: { type: Boolean, required: false, default: false } }, data() { return { accessToken: this.$root.MAPBOX_ACCESS_TOKEN, propertyLng: 0, propertyLat: 0, map: null, nav: null, popup: null }; }, computed: { renderMap: function() { return this.createMap(this.map, this.nav, this.popup) } }, methods: { createMap(map, nav, popup) { let vm = this let layer = { id: '', // set dynamically below type: 'symbol', source: { type: 'geojson', data: { type: 'FeatureCollection', features: [] } }, layout: { 'icon-image': '', // set dynamically below 'icon-allow-overlap': true, 'icon-size': 0.5 }, paint: { 'icon-color': '#1469ab' } } let homeLayer = JSON.parse(JSON.stringify(layer)) // deep clone homeLayer.id = 'home' homeLayer.layout['icon-image'] = 'listedHomeMarker' let pointsLayer = JSON.parse(JSON.stringify(layer)) // deep clone pointsLayer.id = 'points' pointsLayer.layout['icon-image'] = 'listedMarker' const bounds = new mapboxgl.LngLatBounds(); for (var i = 0; i < this.properties.length; i++) { let path = `${this.properties[i].isLc ? '' : 'https://property.listinginfo.com/'}${this.$root.user.appUserId}/property/${this.properties[i].propertyId}${this.$root.isDevelopment?'?development=1':''}` let htmlTemplate = `
$${this.$root.numberWithCommas(this.properties[i].price)}
${this.properties[i].bedrooms} bd, ${this.properties[i].bathrooms} ba
${this.properties[i].sqft} sqft ${this.properties[i].soldDate?'
SOLD':''}
${this.properties[i].address}
` let feature = { type: 'Feature', properties: { description: htmlTemplate, url: `${this.properties[i].isLc ? this.$root.localUrlHrefBase : 'https://property.listinginfo.com/'}${this.$root.user.userId}/property/${this.properties[i].propertyId}`, icon: '' // set dynamically below }, geometry: { type: 'Point', coordinates: [parseFloat(this.properties[i].lng), parseFloat(this.properties[i].lat)] } } // Add coordinates to bounds bounds.extend([parseFloat(this.properties[i].lng), parseFloat(this.properties[i].lat)]); if (this.property?.propertyId) { if ((this.properties[i].propertyId == this.property.propertyId)) { feature.properties.icon = 'listedHomeMarker' homeLayer.source.data.features.push(feature) } else { feature.properties.icon = 'listedMarker' pointsLayer.source.data.features.push(feature) } } else { if (this.properties[i].soldDate == '') { feature.properties.icon = 'listedHomeMarker' homeLayer.source.data.features.push(feature) } else { feature.properties.icon = 'listedMarker' pointsLayer.source.data.features.push(feature) } } } map.on('load', function() { map.addControl(nav, "top-left"); map.loadImage('/images/map-marker.png', (error, image) => { if (error) throw error; map.addImage('listedMarker', image); map.addLayer(pointsLayer); }); map.loadImage('/images/map-marker-house.png', (error, image) => { if (error) throw error; // Add the loaded image to the style's sprite with the ID 'kitten'. map.addImage('listedHomeMarker', image); map.addLayer(homeLayer); // Fit bounds if property is not set and bounds is not empty if (vm.zoomOutToShowAllProperties && !bounds.isEmpty()) { map.fitBounds(bounds, { padding: 50, maxZoom: 14, duration: 1000 }); } }); if (vm.showPopups) { map.on('mouseenter', 'points', (e) => { map.getCanvas().style.cursor = 'pointer' var features = map.queryRenderedFeatures(e.point, { layers: ['points'] }) if (!features.length) { return } var coordinates = e.features[0].geometry.coordinates.slice(); var description = e.features[0].properties.description; while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) { coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360; } popup.setLngLat(coordinates) .setHTML(description) .addTo(map); }); map.on('mouseleave', 'points', function() { map.getCanvas().style.cursor = '' }); map.on('mouseenter', 'home', (e) => { map.getCanvas().style.cursor = 'pointer' var features = map.queryRenderedFeatures(e.point, { layers: ['home'] }) if (!features.length) { return } var coordinates = e.features[0].geometry.coordinates.slice(); var description = e.features[0].properties.description; while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) { coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360; } popup.setLngLat(coordinates) .setHTML(description) .addTo(map); }); map.on('mouseleave', 'home', function() { map.getCanvas().style.cursor = '' }); } }); } }, created() { if (!this.property.propertyId) { this.propertyLng = this.properties[0] && this.properties[0].lng ? this.properties[0].lng : 0 this.propertyLat = this.properties[0] && this.properties[0].lat ? this.properties[0].lat : 0 } else { this.propertyLng = this.property.lng ? this.property.lng : 0 this.propertyLat = this.property.lat ? this.property.lat : 0 } }, mounted() { mapboxgl.accessToken = this.accessToken // Initialize map components this.map = new mapboxgl.Map({ container: 'mapContainer', style: 'mapbox://styles/mapbox/light-v9', center: [this.propertyLng, this.propertyLat], zoom: 10 }); this.nav = new mapboxgl.NavigationControl(); this.popup = new mapboxgl.Popup({ closeButton: true, closeOnClick: false }); // Wait for next tick to ensure DOM is ready this.$nextTick(() => { if (this.properties && this.properties.length > 0) { this.renderMap; } }); }, watch: { properties: { handler(newVal) { if (newVal && newVal.length > 0 && this.map) { // Clear existing layers if (this.map.getLayer('home')) this.map.removeLayer('home'); if (this.map.getLayer('points')) this.map.removeLayer('points'); if (this.map.getSource('home')) this.map.removeSource('home'); if (this.map.getSource('points')) this.map.removeSource('points'); // Re-render the map this.$nextTick(() => { this.renderMap; }); } }, immediate: true, deep: true } } } app.component('global-map', objGlobalMap); const objGlobalToastAlert = { template: ` ` , data(){ return { colors: [ 'primary', 'success', 'danger' ] } } } app.component('global-toast-alert', objGlobalToastAlert); const objGlobalToastContainer = { template: `
` , } app.component('global-toast-container', objGlobalToastContainer); const objNavigationMain = { template: ` ` , name: 'NavigationMain', data() { return { searchQuery: '' } }, methods: { performSearch() { if (this.searchQuery.trim()) { // Navigate to the agent's profile with search query let query = { q: this.searchQuery } if (this.$root.isDevelopment) query.development = 1 this.$router.push({ path: `/${this.$root.userId}`, query: query }); } }, routeToUserProfile() { // Navigate to the agent's profile let query = {} if (this.$root.isDevelopment) query.development = 1 this.$router.push({ path: `/${this.$root.userId}`, query: query }); } }, watch: { '$route.query.q': { immediate: true, handler(newVal) { if (newVal) { this.searchQuery = newVal; } } } } } app.component('navigation-main', objNavigationMain); const objPropertyAmenities = { template: `

Amenities

|{{ amenity }}

` , props: { property: { type: Object, required: true, default: {} } }, computed: { amenitiesAvailable() { let amenities = [] if (this.property.garage) amenities.push(`${this.property.garage} Garage`) if (this.property.pool) amenities.push(`Pool`) if (this.property.yearBuilt) amenities.push(`Built in ${this.property.yearBuilt}`) if (this.property.roofStyle) amenities.push(`${this.property.roofStyle} Roof`) if (this.property.cooling) amenities.push(`${this.property.cooling} Cooling`) if (this.property.heating) amenities.push(`${this.property.heating} Heating`) if (this.property.stories) amenities.push(`${this.property.stories} ${this.property.stories == 1 ? 'Story' : 'Stories'}`) return amenities } }, methods: { scrollToContact() { const contactSection = document.getElementById('agent-contact'); if (contactSection) { contactSection.scrollIntoView({ behavior: 'smooth' }); } } } } app.component('property-amenities', objPropertyAmenities); const objPropertyAppointment = { template: `

Schedule an Appointment

` , data(){ return { datetime:{ selectedDate: '1900-01-01', selectedTime: '12:15 PM' }, intervals: [], intervalStart: 45, selectedIndex: 4, } }, methods: { setInitialDate() { let today = new Date() let day = String(today.getDate()).padStart(2, '0') let month = String(today.getMonth() + 1).padStart(2, '0') //January is 0! let year = today.getFullYear() let date = `${year}-${month}-${day}` this.datetime.selectedDate = date if (document.getElementById("selectedDate")) document.getElementById("selectedDate").value = date }, setSelectedTime(value, event) { this.datetime.selectedTime = value let index = this.intervals.indexOf(value); this.intervalStart = index-4; }, triggerPropUpdate() { // trick an update to the child component with .sync this.datetime.selectedDate = '' if (document.getElementById("selectedDate")) this.datetime.selectedDate = document.getElementById("selectedDate").value }, getIntervals(){ let currentTime = new Date(); currentTime.setHours(0,0,0,0); for(i = 0; i < 96; i++){ let hours = currentTime.getHours(); let minutes = currentTime.getMinutes(); let ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; minutes = minutes < 10 ? '0' + minutes : minutes; let interval = hours + ':' + minutes + ' ' + ampm; this.intervals.push(interval); currentTime.setTime(currentTime.getTime() + 15 * 60 * 1000); } } }, mounted() { this.setInitialDate(); this.getIntervals(); }, computed:{ intervalPeriod(){ if(this.intervalStart < 0){ let temparr1; let temparr2; temparr1 = this.intervals.slice(this.intervals.length + this.intervalStart) temparr2 = this.intervals.slice(0, this.intervalStart + 9); let combinedarr = temparr1.concat(temparr2) return combinedarr; } else if(this.intervalStart > 86){ let temparr1; let temparr2; temparr1 = this.intervals.slice(this.intervalStart, this.intervals.length) temparr2 = this.intervals.slice(0, 9 - temparr1.length); let combinedarr = temparr1.concat(temparr2) return combinedarr; } else{ return this.intervals.slice(this.intervalStart, this.intervalStart+9); } }, intervalRows(){ let row1 = [] let row2 = [] let row3 = [] for(let i = 0; i<9; i++){ if(i<3){ row1.push(this.intervalPeriod[i]); } else if(i<6){ row2.push(this.intervalPeriod[i]); } else{ row3.push(this.intervalPeriod[i]); } } let rows = [row1,row2,row3]; return rows; } } } app.component('property-appointment', objPropertyAppointment); const objPropertyAppointmentmodal = { template: `