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 ? `
+
+
+
+ ` : '';
+
+ // 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}
+
+
+
+ Listed Date |
+ ${formatDate(data.listed_date)} |
+
+ ${listingUrlBlock}
+
+ 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}
+
+
+
+ Listed Date |
+ ${formatDate(data.listed_date)} |
+
+ ${listingUrlBlock}
+ ${parkNameBlock}
+
+ List Price |
+ $${data.list_price.toLocaleString()} |
+
+ ${hoaFeeBlock}
+ ${hoaFeeFrequencyBlock}
+
+ Square Feet |
+ ${data.sqft ? `${data.sqft.toLocaleString()}` : "Unknown"} sq. ft |
+
+
+ Price Per Square Foot |
+ ${data.ppsqft ? `$${data.ppsqft.toLocaleString()}` : "Unknown"} |
+
+ ${spaceRentBlock}
+
+ Bedrooms/Bathrooms |
+ ${data.bedrooms_bathrooms} |
+
+
+ Year Built |
+ ${data.year_built || "Unknown"} |
+
+ ${petsAllowedBlock}
+ ${seniorCommunityBlock}
+
+ 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