diff --git a/assets/javascript/popup.js b/assets/javascript/popup.js index fb4003d2..907f2671 100644 --- a/assets/javascript/popup.js +++ b/assets/javascript/popup.js @@ -5,19 +5,273 @@ window.dash_props = Object.assign({}, window.dash_props, { module: { on_each_feature: function(feature, layer, context) { if (!feature.properties) { - return + return; } - if (feature.properties.popup) { - layer.bindPopup(feature.properties.popup, { - // Here you can customize the popup - // https://leafletjs.com/reference.html#popup-option - //autoPan: false, - //closeButton: false, - // Set the maxHeight to 375px if the device is mobile, otherwise use the default value - maxHeight: window.innerWidth < 768 ? 375 : 650, - // Set the maxWidth to 175px if the device is mobile, otherwise use the default value + if (feature.properties.data) { + const data = feature.properties.data; // Get the dataframe rows from the GeoJSON feature properties + const context = feature.properties.context; // Get the type of page (lease or buy) from the GeoJSON feature properties + const selected_subtypes = data.subtype; // Get the selected subtype(s) from the GeoJSON feature properties + + // Log the context object to debug + console.log('Context:', context); + console.log('Data:', data); + + // Function to handle MLS number hyperlink + function getListingUrlBlock(data) { + if (!data.listing_url) { + return ` + + Listing ID (MLS#) + Not Available + + `; + } + return ` + + Listing ID (MLS#) + + ${data.mls_number} + + + `; + } + + // Function to format date string + function formatDate(dateString) { + if (!dateString) return "Unknown"; + const date = new Date(dateString); + return date.toISOString().split('T')[0]; + } + + // Conditionally format the listing URL as a hyperlink or plain text + const listingUrlBlock = getListingUrlBlock(data); + + // Conditionally include the property image row if the image URL is available + const imageRow = data.image_url ? ` + + Property Image + + ` : ''; + + // Conditionally format the phone number as a tel: link or plain text + const phoneNumberBlock = data.phone_number ? ` + ${data.phone_number} + ` : 'Unknown'; + + // Function to generate popup content for lease page + function generateLeasePopupContent(data) { + return ` +
+ ${imageRow} +
+
${data.address}
+
+ + + + + + ${listingUrlBlock} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Listed Date${formatDate(data.listed_date)}
List Office Phone${phoneNumberBlock}
Rental Price$${data.list_price.toLocaleString()}
Security Deposit${data.security_deposit ? `$${data.security_deposit.toLocaleString()}` : "Unknown"}
Pet Deposit${data.pet_deposit ? `$${data.pet_deposit.toLocaleString()}` : "Unknown"}
Key Deposit${data.key_deposit ? `$${data.key_deposit.toLocaleString()}` : "Unknown"}
Other Deposit${data.other_deposit ? `$${data.other_deposit.toLocaleString()}` : "Unknown"}
Square Feet${data.sqft ? `${data.sqft.toLocaleString()}` : "Unknown"} sq. ft
Price Per Square Foot${data.ppsqft ? `$${data.ppsqft.toLocaleString()}` : "Unknown"}
Bedrooms/Bathrooms${data.bedrooms}/${data.bathrooms}
Garage Spaces${data.garage_spaces || "Unknown"}
Pets Allowed?${data.pet_policy || "Unknown"}
Furnished?${data.furnished || "Unknown"}
Laundry Features${data.laundry || "Unknown"}
Senior Community${data.senior_community || "Unknown"}
Year Built${data.year_built || "Unknown"}
Rental Terms${data.terms || "Unknown"}
Physical Sub Type${data.subtype || "Unknown"}
+
+ `; + } + + // Function to generate popup content for buy page + function generateBuyPopupContent(data, selected_subtypes) { + // Conditionally include the park name row if the property subtype is MH or has MH in the selected subtypes + let parkNameBlock = ''; + if (selected_subtypes.includes('MH')) { + parkNameBlock = ` + + Park Name + ${data.park_name || "Unknown"} + + `; + } + + // Conditionally include the pet policy row if the property subtype is MH or has MH in the selected subtypes + let petsAllowedBlock = ''; + if (selected_subtypes.includes('MH')) { + petsAllowedBlock = ` + + Pets Allowed? + ${data.pets_allowed || "Unknown"} + + `; + } + + // Condtionally include the Senior Community row if the property subtype is MH or has MH in the selected subtypes + let seniorCommunityBlock = ''; + if (selected_subtypes.includes('MH')) { + seniorCommunityBlock = ` + + Senior Community + ${data.senior_community || "Unknown"} + + `; + } + + // Conditionally include the space rent row if the property subtype is MH or has MH in the selected subtypes + let spaceRentBlock = ''; + if (selected_subtypes.includes('MH')) { + spaceRentBlock = ` + + Space Rent + ${data.space_rent ? `$${data.space_rent.toLocaleString()}` : "Unknown"} + + `; + } + + // Conditionally include the HOA Fee row if the property subtype is not MH or has MH in the selected subtypes + let hoaFeeBlock = ''; + if (!selected_subtypes.includes('MH')) { + hoaFeeBlock = ` + + HOA Fee + ${data.hoa_fee ? `$${data.hoa_fee.toLocaleString()}` : "Unknown"} + + `; + } + + // Conditionally include the HOA Fee Frequency row if the property subtype is not MH or has MH in the selected subtypes + let hoaFeeFrequencyBlock = ''; + if (!selected_subtypes.includes('MH')) { + hoaFeeFrequencyBlock = ` + + HOA Fee Frequency + ${data.hoa_fee_frequency || "Unknown"} + + `; + } + + return ` +
+ ${imageRow} +
+
${data.address}
+
+ + + + + + ${listingUrlBlock} + ${parkNameBlock} + + + + + ${hoaFeeBlock} + ${hoaFeeFrequencyBlock} + + + + + + + + + ${spaceRentBlock} + + + + + + + + + ${petsAllowedBlock} + ${seniorCommunityBlock} + + + + +
Listed Date${formatDate(data.listed_date)}
List Price$${data.list_price.toLocaleString()}
Square Feet${data.sqft ? `${data.sqft.toLocaleString()}` : "Unknown"} sq. ft
Price Per Square Foot${data.ppsqft ? `$${data.ppsqft.toLocaleString()}` : "Unknown"}
Bedrooms/Bathrooms${data.bedrooms_bathrooms}
Year Built${data.year_built || "Unknown"}
Physical Sub Type${data.subtype || "Unknown"}
+
+ `; + } + + // Determine which popup content to generate based on context + let popupContent = ''; + if (context.pageType === 'lease') { + popupContent = generateLeasePopupContent(data); + } else if (context.pageType === 'buy') { + popupContent = generateBuyPopupContent(data, selected_subtypes); + } + + layer.bindPopup(popupContent, { + maxHeight: window.innerWidth < 768 ? 375 : 650, maxWidth: window.innerWidth < 768 ? 175 : 300, - }) + }); } } } diff --git a/buy_dataframe.py b/buy_dataframe.py index d05bad26..f6a1e3c6 100644 --- a/buy_dataframe.py +++ b/buy_dataframe.py @@ -187,6 +187,9 @@ df['Half Bathrooms'] = (df['Br/Ba'].str.split('/', expand=True)[1]).str.split(',', expand=True)[2] df['Three Quarter Bathrooms'] = (df['Br/Ba'].str.split('/', expand=True)[1]).str.split(',', expand=True)[3] +# Rename the Br/Ba column to bedrooms_bathrooms +df.rename(columns={'Br/Ba': 'bedrooms_bathrooms'}, inplace=True) + # Convert a few columns into int64 # pd.to_numeric will convert into int64 or float64 automatically, which is cool # These columns are assumed to have NO MISSING DATA, so we can cast them as int64 instead of floats (ints can't handle NaNs) @@ -205,7 +208,7 @@ # Convert date_processed into DateTime df['date_processed'] = pd.to_datetime(df['date_processed'], errors='coerce', format='%Y-%m-%d') -cols = ['Full Bathrooms', 'Bedrooms', 'year_built', 'Sqft', 'list_price', 'Total Bathrooms', 'space_rent', 'ppsqft', 'hoa_fee'] +cols = ['Full Bathrooms', 'Bedrooms', 'year_built', 'Sqft', 'list_price', 'Total Bathrooms', 'space_rent', 'ppsqft', 'hoa_fee', 'bedrooms_bathrooms'] # Convert columns to string type for string operations df[cols] = df[cols].astype(str) # Remove commas and other non-numeric characters