feat: complete dashboard widgets, fix tooltips, integrate chatbot, and update docs

This commit is contained in:
Satyam
2026-02-01 16:00:17 +05:30
parent cfc5c943e5
commit 719172372e
12 changed files with 1269 additions and 296 deletions
+52 -12
View File
@@ -165,11 +165,27 @@ function generateEmail(name, company = null) {
return `${first}.${last}@${domain}`;
}
// Weighted Random Helper
function getWeightedRandom(items, weights) {
const totalWeight = weights.reduce((a, b) => a + b, 0);
const random = Math.random() * totalWeight;
let weightSum = 0;
for (let i = 0; i < items.length; i++) {
weightSum += weights[i];
if (random <= weightSum) {
return items[i];
}
}
return items[items.length - 1]; // Fallback
}
function generateProperties() {
return RAW_LOCATIONS.map((loc, index) => {
const isCommercial = loc.type === "Commercial" || loc.type === "Apartments";
const styleIndex = (index * 7) % PROPERTY_STYLES.length;
// Shuffle styles slightly differently than index-based to avoid repeating patterns
const styleIndex = Math.floor(Math.random() * PROPERTY_STYLES.length);
const style = isCommercial ? null : PROPERTY_STYLES[styleIndex];
let ownerName, ownerEmail, occupation, income, employerName;
@@ -191,20 +207,44 @@ function generateProperties() {
income = ["$80k - $120k", "$120k - $180k", "$200k+", "$60k - $90k"][index % 4];
}
const builtYear = isCommercial ? 1995 + (index % 10) : style.yearBase + (index % 15);
const sqft = isCommercial ? 12000 + (index * 500) : style.areaBase + (index * 132);
const value = isCommercial ? 2500000 + (index * 100000) : style.baseValue + (index * 12500);
// Randomize Year and Value to break lines
const yearOffset = Math.floor(Math.random() * 20) - 10; // +/- 10 years
const builtYear = isCommercial ? 1995 + (index % 10) : style.yearBase + yearOffset;
const isRented = index % 3 === 0;
const valueVariance = (Math.random() * 0.4) - 0.2; // +/- 20%
const baseSqft = isCommercial ? 12000 + (index * 500) : style.areaBase;
const sqft = Math.floor(baseSqft * (1 + (valueVariance / 2))); // Size correlates with value but not perfectly
const baseVal = isCommercial ? 2500000 + (index * 100000) : style.baseValue;
const value = Math.floor(baseVal * (1 + valueVariance));
const isRented = Math.random() > 0.7; // 30% rented
const tenantName = isRented ? (isCommercial ? "Multiple Commercial Tenants" : REAL_NAMES[(index + 5) % REAL_NAMES.length]) : null;
const tenantOcc = isRented ? (isCommercial ? "Retail/Office Mix" : OCCUPATIONS[(index + 3) % OCCUPATIONS.length]) : null;
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)
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: isCommercial ? "Neutral" : style.canvassingStatus,
canvassingStatus: status,
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}`,
@@ -217,9 +257,9 @@ function generateProperties() {
numberOfParkingSpaces: isCommercial ? 25 : 2,
currentEstimatedMarketValue: value,
propertyTaxAssessmentValue: Math.floor(value * 0.85),
roofCondition: ["Good", "Fair", "Excellent", "Needs Repair"][index % 4],
roofCondition: roofCondition,
renovationDescription: isCommercial ? "Commercial Maintenance" : style.desc,
renovationCost: Math.floor(value * 0.05),
renovationCost: Math.floor(value * (Math.random() * 0.05 + 0.01)), // 1-6% of value
lastMajorRenovationDate: "2020-05-15",
lastRoofRepairReplacementDate: "2018-02-10",
recentMajorRepairs: "Routine Maintenance",
@@ -230,12 +270,12 @@ function generateProperties() {
currentMonthlyRentAmount: rentAmount,
leaseStartDate: isRented ? "2023-01-01" : null,
leaseEndDate: isRented ? "2025-01-01" : null,
ownerWillingToRent: index % 4 === 0,
ownerWillingToRent: !isRented && Math.random() > 0.6,
expectedMonthlyRentAmount: Math.floor(value * 0.008 / 100) * 100,
rentalAvailabilityDate: null,
rentalTermsPreference: null,
schoolDistrict: "Plano ISD",
neighborhoodRating: 8 + (index % 3),
neighborhoodRating: neighRating,
crimeRateIndex: "Low",
publicTransportationAccess: "Bus Line 204",
propertyConditionRating: isCommercial ? 4 : style.condition,
@@ -260,10 +300,10 @@ function generateProperties() {
creditScoreRange: "720+",
ownershipType: isCommercial ? "Corporate" : "Individual",
ownershipPercentage: "100%",
willingToRentProperty: false,
willingToRentProperty: Math.random() > 0.8,
desiredMonthlyRentalPrice: null,
rentalConditions: null,
willingToSellProperty: index % 5 === 0,
willingToSellProperty: Math.random() > 0.85,
desiredSellingPrice: Math.floor(value * 1.1),
minimumAcceptableSellingPrice: Math.floor(value * 1.05)
}