diff --git a/src/data/mockStore.jsx b/src/data/mockStore.jsx index b361f05..95f92f0 100644 --- a/src/data/mockStore.jsx +++ b/src/data/mockStore.jsx @@ -181,7 +181,8 @@ function getWeightedRandom(items, weights) { } function generateProperties() { - return RAW_LOCATIONS.map((loc, index) => { + // 1. Generate Base Properties + const allProperties = RAW_LOCATIONS.map((loc, index) => { const isCommercial = loc.type === "Commercial" || loc.type === "Apartments"; // Shuffle styles slightly differently than index-based to avoid repeating patterns @@ -224,27 +225,20 @@ function generateProperties() { const rentAmount = isRented ? Math.floor(value * 0.008 / 100) * 100 : null; // Weighted Roof Condition - // 40% Good, 30% Fair, 20% Excellent, 10% Needs Repair const roofCondition = getWeightedRandom( ["Good", "Fair", "Excellent", "Needs Repair"], [0.4, 0.3, 0.2, 0.1] ); - // Canvassing Status Randomization - // 60% Neutral, 20% Hot Lead, 10% Customer, 10% Renovated - const status = isCommercial ? "Neutral" : getWeightedRandom( - ["Neutral", "Hot Lead", "Customer", "Renovated"], - [0.6, 0.2, 0.1, 0.1] - ); - - // Neighborhood Rating (Weighted towards high 7-9) + // Neighborhood Rating const neighRating = getWeightedRandom([7, 8, 9, 10, 6, 5], [0.3, 0.3, 0.2, 0.1, 0.05, 0.05]); return { id: index + 1, center: [loc.lat, loc.lng], polygon: generatePolygon(loc.lat, loc.lng), - canvassingStatus: status, + // Placeholder status, will be overwritten + canvassingStatus: "Neutral", photos: isCommercial ? ["https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=800", "https://images.unsplash.com/photo-1542665952-14513db15293?w=800"] : style.photos, propertyData: { propertyId: `P-${2600 + index}`, @@ -259,7 +253,7 @@ function generateProperties() { propertyTaxAssessmentValue: Math.floor(value * 0.85), roofCondition: roofCondition, renovationDescription: isCommercial ? "Commercial Maintenance" : style.desc, - renovationCost: Math.floor(value * (Math.random() * 0.05 + 0.01)), // 1-6% of value + renovationCost: Math.floor(value * (Math.random() * 0.05 + 0.01)), lastMajorRenovationDate: "2020-05-15", lastRoofRepairReplacementDate: "2018-02-10", recentMajorRepairs: "Routine Maintenance", @@ -309,6 +303,36 @@ function generateProperties() { } }; }); + + // 2. Assign Statuses with Strict Counts + // User Request: 4-9 Hot Leads, 15-20 Customers + const countHotLeads = Math.floor(Math.random() * (9 - 4 + 1)) + 4; // 4 to 9 + const countCustomers = Math.floor(Math.random() * (20 - 15 + 1)) + 15; // 15 to 20 + + // Create indices array and shuffle it + const indices = allProperties.map((_, i) => i); + for (let i = indices.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [indices[i], indices[j]] = [indices[j], indices[i]]; + } + + // Assign based on shuffled indices + indices.forEach((propIndex, i) => { + if (i < countHotLeads) { + allProperties[propIndex].canvassingStatus = "Hot Lead"; + } else if (i < countHotLeads + countCustomers) { + allProperties[propIndex].canvassingStatus = "Customer"; + } else { + // Remaining are Neutral, Renovated, or Not Interested + // Weighted: 70% Neutral, 20% Not Interested, 10% Renovated + allProperties[propIndex].canvassingStatus = getWeightedRandom( + ["Neutral", "Not Interested", "Renovated"], + [0.7, 0.2, 0.1] + ); + } + }); + + return allProperties; } // --- NEW DATA (Users & Meetings) --- diff --git a/src/pages/Maps.jsx b/src/pages/Maps.jsx index 105b5ce..06d6dc4 100644 --- a/src/pages/Maps.jsx +++ b/src/pages/Maps.jsx @@ -28,7 +28,7 @@ L.Marker.prototype.options.icon = DefaultIcon; const StatusBadge = ({ status }) => { const colors = { - "Neutral": "bg-zinc-500", + "Neutral": "bg-violet-400", "Hot Lead": "bg-red-500", "Renovated": "bg-blue-500", "Customer": "bg-emerald-500", @@ -51,6 +51,34 @@ const MapInteraction = ({ onMapClick }) => { return null; }; +const MapLegend = () => ( +