Files
LynkedUpPro_CRM/src/data/mockStore.jsx
T
Satyam 8bb321e1f7 feat(leads): Lead Creation Phase 1 — page shell, section framework, mock data
- CreateLeadPage.jsx: full page shell with Quick Capture / Full Form toggle, Barlow Condensed header, breadcrumb nav, GSAP progress bar stub, mobile sticky save footer
- LeadSectionWrapper.jsx: collapsible section component with Framer Motion height animation, spring chevron rotation, completion dot, dual light/dark header design matching GlassPanel language
- 5 sections wired up: Contact (blue), Property (emerald), Job Details (amber), Insurance (violet), Assignment (cyan) — Quick Capture shows first 3, Full Form shows all 5
- Section indicator pills in header dim gracefully when hidden in Quick Capture mode
- LEAD_FORM_OPTIONS added to mockStore: lead types, sources, work types, trade types, urgency/priority levels, insurance companies, claim statuses, phone/email types, US states
- Route /emp/fa/leads/new added (FIELD_AGENT, ADMIN, OWNER)
- New Lead nav item added to sidebar for all 3 roles
2026-03-13 16:07:29 +05:30

2932 lines
131 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { createContext, useContext, useState, useEffect } from 'react';
import { toast } from 'sonner';
import { logger } from '../utils/logger';
// --- DATA CONSTANTS (Extracted from old App.jsx) ---
const RAW_LOCATIONS = [
// Residential
{ address: "2612 Dunwick Dr, Plano, TX 75023", lat: 33.07084060970922, lng: -96.74558398435258, type: "Residential" },
{ address: "2608 Dunwick Dr, Plano, TX 75023", lat: 33.070834939506284, lng: -96.74532009555337, type: "Residential" },
{ address: "2604 Dunwick Dr, Plano, TX 75023", lat: 33.07081036862272, lng: -96.74507199497292, type: "Residential" },
{ address: "2600 Dunwick Dr, Plano, TX 75023", lat: 33.07083115937081, lng: -96.74483066077192, type: "Residential" },
{ address: "2516 Dunwick Dr, Plano, TX 75023", lat: 33.070770677180924, lng: -96.74459158203076, type: "Residential" },
{ address: "2637 Rothland Ln, Plano, TX 75023", lat: 33.070426683935366, lng: -96.74557721797312, type: "Residential" },
{ address: "2633 Rothland Ln, Plano, TX 75023", lat: 33.07042290378234, lng: -96.74534265015158, type: "Residential" },
{ address: "2629 Rothland Ln, Plano, TX 75023", lat: 33.07042857401182, lng: -96.74508552773183, type: "Residential" },
{ address: "2617 Rothland Ln, Plano, TX 75023", lat: 33.070432354164595, lng: -96.74435024782977, type: "Residential" },
{ address: "2513 Rothland Ln, Plano, TX 75023", lat: 33.07016207283135, lng: -96.74304208113281, type: "Residential" },
// New Residential Data
{ address: "6613 Phoenix Pl, Plano, TX 75023, USA", lat: 33.063266298016536, lng: -96.76932248857813, type: "Residential" },
{ address: "6609 Phoenix Pl, Plano, TX 75023, USA", lat: 33.063141994627365, lng: -96.76932089372718, type: "Residential" },
{ address: "6605 Phoenix Pl, Plano, TX 75023, USA", lat: 33.06302437405446, lng: -96.76933365253466, type: "Residential" },
{ address: "6601 Phoenix Pl, Plano, TX 75023, USA", lat: 33.06290541672423, lng: -96.7693424242148, type: "Residential" },
{ address: "6617 Phoenix Pl, Plano, TX 75023, USA", lat: 33.063379067434504, lng: -96.7693376006764, type: "Residential" },
{ address: "3913 Arizona Pl, Plano, TX 75023, USA", lat: 33.06318117622371, lng: -96.7698079594919, type: "Residential" },
{ address: "3917 Arizona Pl, Plano, TX 75023, USA", lat: 33.063193097393324, lng: -96.76997201609075, type: "Residential" },
{ address: "3921 Arizona Pl, Plano, TX 75023, USA", lat: 33.0631946868825, lng: -96.77014555573001, type: "Residential" },
{ address: "3920 Arizona Pl, Plano, TX 75023, USA", lat: 33.06252788822516, lng: -96.77010020638036, type: "Residential" },
{ address: "3916 Arizona Pl, Plano, TX 75023, USA", lat: 33.06254219373469, lng: -96.76993520147747, type: "Residential" },
{ address: "3912 Arizona Pl, Plano, TX 75023, USA", lat: 33.06254378323562, lng: -96.76975502370993, type: "Residential" },
{ address: "3908 Arizona Pl, Plano, TX 75023, USA", lat: 33.06253583573075, lng: -96.76959191541512, type: "Residential" },
{ address: "3904 Arizona Pl, Plano, TX 75023, USA", lat: 33.062526298723945, lng: -96.769445876593, type: "Residential" },
{ address: "3900 Arizona Pl, Plano, TX 75023, USA", lat: 33.06252153022017, lng: -96.76928656151433, type: "Residential" },
{ address: "3917 Sailmaker Ln, Plano, TX 75023, USA", lat: 33.0622004503711, lng: -96.76993899469362, type: "Residential" },
{ address: "3913 Sailmaker Ln, Plano, TX 75023, USA", lat: 33.06218773431336, lng: -96.76979295587151, type: "Residential" },
{ address: "3909 Sailmaker Ln, Plano, TX 75023, USA", lat: 33.06220362938525, lng: -96.76961846792823, type: "Residential" },
{ address: "3905 Sailmaker Ln, Plano, TX 75023, USA", lat: 33.06221157692012, lng: -96.76945725624147, type: "Residential" },
{ address: "3901 Sailmaker Ln, Plano, TX 75023, USA", lat: 33.06219091332797, lng: -96.7692808716901, type: "Residential" },
// Commercial
{ address: "6909 Custer Rd, Plano, TX 75023", lat: 33.07020596727293, lng: -96.7390826077087, type: "Commercial" },
{ address: "2112 Winslow Dr, Plano, TX 75023", lat: 33.069360828751016, lng: -96.73770127012321, type: "Commercial" },
{ address: "7224 Independence Pkwy, Plano, TX 75025", lat: 33.07506839285908, lng: -96.74984052259599, type: "Commercial" },
// New Commercial Data
{ address: "Dallas/Plano Marriott at Legacy Town Center, 7121 Bishop Rd, Plano, TX 75024, United States", lat: 33.074457402913424, lng: -96.8222322519585, type: "Commercial" },
{ address: "Legacy Town Center Plano, 5760 Daniel Rd, Plano, TX 75024, United States", lat: 33.07360554164325, lng: -96.82142050370054, type: "Commercial" },
{ address: "WeWork Office Space & Coworking, 6900 Dallas Pkwy Suite 300, Plano, TX 75024, United States", lat: 33.07281088750022, lng: -96.8235902233433, type: "Commercial" },
{ address: "Truluck's Ocean's Finest Seafood and Crab, 7161 Bishop Rd, Plano, TX 75024, United States", lat: 33.07535565705897, lng: -96.82174939646889, type: "Commercial" },
{ address: "Del Frisco's Grille, 7200 Bishop Rd Suite D9, Plano, TX 75024, United States", lat: 33.07630819707901, lng: -96.82124417346868, type: "Commercial" },
{ address: "Scruffy Duffies, 5865 Kincaid Rd E8, Plano, TX 75024, United States", lat: 33.07601336437884, lng: -96.82257940570773, type: "Commercial" },
{ address: "Half Shells, 7201 Bishop Rd #E4, Plano, TX 75024, United States", lat: 33.07635733578195, lng: -96.82171330913596, type: "Commercial" },
{ address: "Mi Cocina, 5760 Legacy Dr #B7, Plano, TX 75024, United States", lat: 33.07743082031222, lng: -96.82109531315771, type: "Commercial" },
{ address: "Leasing Office space and The Kincaid at Legacy Apartment, 7200 Dallas Pkwy, Plano, TX 75024, United States", lat: 33.07619102009707, lng: -96.82340039310428, type: "Commercial" },
{ address: "Issil Beauty Spa, 7140 Bishop Rd #F4, Plano, TX 75024, United States", lat: 33.07550110630488, lng: -96.82122287598153, type: "Commercial" },
// Apartments
{ address: "2100 Legacy Dr, Plano, TX 75023", lat: 33.07035321131275, lng: -96.73493675556306, type: "Apartments" },
{ address: "2401 Brown Deer Trail, Plano, TX 75023", lat: 33.06897509321587, lng: -96.7419549494157, type: "Residential" },
];
const PROPERTY_STYLES = [
{
label: "Luxury Estate",
canvassingStatus: "Customer",
photos: [
{ id: 'le_1', url: "/assets/images/properties/Luxury_Driveway_Residence.jpg", caption: "Front Exterior" },
{ id: 'le_2', url: "/assets/images/properties/Sunny_Suburban_House.jpg", caption: "Side Elevation" },
{ id: 'le_3', url: "/assets/images/properties/Residential_Roof_Texture.jpg", caption: "Roof Quality" }
],
baseValue: 850000,
areaBase: 4200,
beds: 5,
baths: 4.5,
yearBase: 2010,
desc: "Luxury estate with custom finishes throughout.",
condition: 5
},
{
label: "Standard Family Home",
canvassingStatus: "Neutral",
photos: [
{ id: 'sf_1', url: "/assets/images/properties/Modern_White_Suburban_Home.jpg", caption: "Front View" },
{ id: 'sf_2', url: "/assets/images/properties/Brick_Front_Porch_Home.jpg", caption: "Entryway" },
{ id: 'sf_3', url: "/assets/images/properties/Overlapping_Roof_Shingles.jpg", caption: "Roof Condition" },
{ id: 'sf_4', url: "/assets/images/properties/Red_Shingle_Cottage.jpg", caption: "Cottage Style" }
],
baseValue: 450000,
areaBase: 2800,
beds: 4,
baths: 3,
yearBase: 1995,
desc: "Well-maintained family home in established neighborhood.",
condition: 4
},
{
label: "Fixer Upper",
canvassingStatus: "Hot Lead",
photos: [
{ id: 'fu_1', url: "/assets/images/properties/Beige_Two_Story_House.jpg", caption: "Street View" },
{ id: 'fu_2', url: "/assets/images/properties/Hail_Damaged_Shingles.jpg", caption: "Hail Damage" },
{ id: 'fu_3', url: "/assets/images/properties/Broken_Roof_Surface.jpg", caption: "Critical Repairs Needed" },
{ id: 'fu_4', url: "/assets/images/properties/Cracked_Storm_Shingles.jpg", caption: "Storm Damage" },
{ id: 'fu_5', url: "/assets/images/properties/Storm_Worn_Roof.jpg", caption: "Worn Roof" }
],
baseValue: 320000,
areaBase: 2400,
beds: 3,
baths: 2,
yearBase: 1980,
desc: "Great potential, needs cosmetic updates.",
condition: 2
},
{
label: "Renovated Modern",
canvassingStatus: "Renovated",
photos: [
{ id: 'rm_1', url: "/assets/images/properties/Minimal_Flat_Roof_House.jpg", caption: "Modern Facade" },
{ id: 'rm_2', url: "/assets/images/properties/Red_Tiled_Roof_House.jpg", caption: "New Roof" },
{ id: 'rm_3', url: "/assets/images/properties/Roof_Inspection_Angle.jpg", caption: "Drone Inspection" },
{ id: 'rm_4', url: "/assets/images/properties/Red_Metal_Roof_Home.jpg", caption: "Metal Roof Upgrade" }
],
baseValue: 580000,
areaBase: 3200,
beds: 4,
baths: 3.5,
yearBase: 1990,
desc: "Recently renovated with modern aesthetics.",
condition: 5
}
];
const COMMERCIAL_VARIANTS = [
{ name: "Legacy Retail Group", type: "Retail Mix", email: "leasing@legacyretail.com" },
{ name: "Custer Office Park LLC", type: "Office Space", email: "mgmt@custeroffice.com" },
{ name: "Plano Investments Inc", type: "Mixed Use", email: "contact@planoinvest.com" },
{ name: "North Texas Prop Co", type: "Service Center", email: "info@ntxprops.com" }
];
const REAL_NAMES = [
"James Beauford", "Sarah Miller", "Robert Henderson", "Karen Smith", "Michael Chang",
"Patricia O'Neil", "Dr. Anish Patel", "Marcus Johnson", "Elena Rodriguez", "Greg Alston",
"Linda Grey", "Bill Thompson", "Jennifer Wu", "David Kowalski", "Omar Farooq",
"Lisa Chen", "Tom Baker", "Rachel Green", "Steve Martin", "Angela White"
];
const OCCUPATIONS = [
"Software Engineer", "Petroleum Engineer", "Teacher", "Nurse Practitioner",
"Small Business Owner", "Accountant", "Marketing Director", "retired",
"Attorney", "Real Estate Agent", "Sales Manager", "Consultant"
];
const EMPLOYERS_BY_OCCUPATION = {
"Software Engineer": ["Google", "Microsoft", "Toyota Connected", "Capital One", "Intuit"],
"Petroleum Engineer": ["ExxonMobil", "Chevron", "Pioneer Natural Resources", "Denbury"],
"Teacher": ["Plano ISD", "Frisco ISD", "Dallas ISD", "Richardson ISD"],
"Nurse Practitioner": ["Baylor Scott & White", "Medical City Plano", "Texas Health Resources"],
"Small Business Owner": ["Self Employed", "Local Boutique", "Consultancy Firm"],
"Accountant": ["Deloitte", "PwC", "EY", "KPMG", "Local CPA Firm"],
"Marketing Director": ["PepsiCo", "Toyota", "Frito-Lay", "Yum! Brands"],
"retired": ["N/A"],
"Attorney": ["Jones Day", "Baker Botts", "Norton Rose Fulbright", "Local Law Firm"],
"Real Estate Agent": ["Keller Williams", "Ebby Halliday", "Compass", "Remax"],
"Sales Manager": ["Oracle", "Salesforce", "AT&T", "Samsung"],
"Consultant": ["McKinsey", "BCG", "Accenture", "Freelance"]
};
// --- NEW INSURANCE SCHEMA CONSTANTS ---
const INSURANCE_COMPANIES = [
"State Farm", "Allstate", "Liberty Mutual", "Farmers", "Nationwide",
"USAA", "Chubb", "Travelers", "Progressive", "American Family"
];
const ADJUSTER_TYPES = ["Staff Adjuster", "Independent Adjuster", "Public Adjuster"];
// --- DATA GENERATION HELPERS ---
function generatePolygon(lat, lng) {
const dLat = 0.0001; // ~11 meters
const dLng = 0.0001; // ~11 meters
return [
[lat + dLat, lng - dLng], // Top Left
[lat + dLat, lng + dLng], // Top Right
[lat - dLat, lng + dLng], // Bottom Right
[lat - dLat, lng - dLng], // Bottom Left
];
}
function generateEmail(name, company = null) {
if (company) return company;
const domains = ["gmail.com", "yahoo.com", "outlook.com", "icloud.com"];
const domain = domains[Math.floor(Math.random() * domains.length)];
const parts = name.toLowerCase().split(' ');
const last = parts[parts.length - 1].replace(/[^a-z]/g, '');
const first = parts[0].replace(/[^a-z]/g, '');
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() {
// 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
const styleIndex = Math.floor(Math.random() * PROPERTY_STYLES.length);
const style = isCommercial ? null : PROPERTY_STYLES[styleIndex];
let ownerName, ownerEmail, occupation, income, employerName;
if (isCommercial) {
const commVariant = COMMERCIAL_VARIANTS[index % COMMERCIAL_VARIANTS.length];
ownerName = commVariant.name;
ownerEmail = commVariant.email;
occupation = "Commercial Owner";
income = "$1M+";
employerName = "Self";
} else {
ownerName = REAL_NAMES[index % REAL_NAMES.length];
ownerEmail = generateEmail(ownerName);
occupation = OCCUPATIONS[index % OCCUPATIONS.length];
const potentialEmployers = EMPLOYERS_BY_OCCUPATION[occupation] || ["Self Employed"];
employerName = potentialEmployers[index % potentialEmployers.length];
income = ["$80k - $120k", "$120k - $180k", "$200k+", "$60k - $90k"][index % 4];
}
// 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 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));
// Rental Logic: Target ~10-15 rented (approx 40-50% chance given ~30 props)
const isRented = Math.random() > 0.55;
let tenantData = {};
if (isRented) {
const tName = isCommercial ? "Global Corp Inc." : REAL_NAMES[(index + 5) % REAL_NAMES.length];
const tOcc = isCommercial ? "Retail/Office Mix" : OCCUPATIONS[(index + 3) % OCCUPATIONS.length];
const tPhone = `469-555-${2000 + index}`;
const tEmail = generateEmail(tName.split(' ')[0] || "tenant", isCommercial ? "tenant.com" : null);
const tEmployer = isCommercial ? "N/A" : (EMPLOYERS_BY_OCCUPATION[tOcc]?.[0] || "Self");
const tIncome = isCommercial ? "$5M+" : ["$60k", "$85k", "$110k", "$140k"][index % 4];
const tFamily = isCommercial ? "N/A" : (Math.random() > 0.4 ? "Family" : "Single");
const tLeaseType = isCommercial ? "Commercial NNN" : "Residential Standard";
tenantData = {
currentlyRented: true,
currentTenantName: tName,
tenantPhone: tPhone,
tenantEmail: tEmail,
tenantOccupation: tOcc,
tenantEmployer: tEmployer,
tenantAnnualIncome: tIncome,
livingStatus: tFamily,
leaseType: tLeaseType,
currentMonthlyRentAmount: Math.floor(value * 0.008 / 100) * 100,
leaseStartDate: "2023-01-01",
leaseEndDate: "2025-01-01",
leaseSignedDate: "2022-12-15",
ownerWillingToRent: false // Already rented
};
} else {
tenantData = {
currentlyRented: false,
currentTenantName: null,
tenantPhone: null,
tenantEmail: null,
tenantOccupation: null,
tenantEmployer: null,
tenantAnnualIncome: null,
livingStatus: null,
leaseType: null,
currentMonthlyRentAmount: null,
leaseStartDate: null,
leaseEndDate: null,
leaseSignedDate: null,
ownerWillingToRent: Math.random() > 0.6
};
}
const rentAmount = tenantData.currentMonthlyRentAmount; // For use below if needed, though mapped in tenantData now
// Weighted Roof Condition
const roofCondition = getWeightedRandom(
["Good", "Fair", "Excellent", "Needs Repair"],
[0.4, 0.3, 0.2, 0.1]
);
// 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),
// Placeholder status, will be overwritten
canvassingStatus: "Neutral",
photos: isCommercial ? [
{ id: `com_${index}_1`, url: "/assets/images/properties/Apartment_Complex.jpg", caption: "Exterior View" },
{ id: `com_${index}_2`, url: "/assets/images/properties/Mall_Rooftop_HVAC_Units.jpg", caption: "HVAC Systems" }
] : style.photos,
// --- NEW FIELDS FOR ADMIN ACTION CENTER ---
assignedAgentId: null, // Default unassigned
lastContactDate: null,
pendingSignature: false,
proposalSentDate: null,
proposalValue: 0,
// ------------------------------------------
propertyData: {
propertyId: `P-${2600 + index}`,
propertyAddress: loc.address,
propertyType: loc.type,
totalBuiltUpArea: sqft,
yearBuilt: builtYear,
numberOfBedrooms: isCommercial ? 0 : style.beds,
numberOfBathrooms: isCommercial ? 4 : style.baths,
numberOfParkingSpaces: isCommercial ? 25 : 2,
currentEstimatedMarketValue: value,
propertyTaxAssessmentValue: Math.floor(value * 0.85),
roofCondition: roofCondition,
renovationDescription: isCommercial ? "Commercial Maintenance" : style.desc,
renovationCost: Math.floor(value * (Math.random() * 0.05 + 0.01)),
lastMajorRenovationDate: "2020-05-15",
lastRoofRepairReplacementDate: "2018-02-10",
recentMajorRepairs: "Routine Maintenance",
// Spread new robust tenant data
...tenantData,
expectedMonthlyRentAmount: Math.floor(value * 0.008 / 100) * 100,
rentalAvailabilityDate: null,
rentalTermsPreference: null,
schoolDistrict: "Plano ISD",
neighborhoodRating: neighRating,
crimeRateIndex: "Low",
publicTransportationAccess: "Bus Line 204",
propertyConditionRating: isCommercial ? 4 : style.condition,
furnishingStatus: "Unfurnished",
notes: isCommercial ? "Prime commercial location" : style.desc,
latestPurchasePrice: Math.floor(value * 0.6),
latestPurchaseDate: "2015-06-20",
latestSaleListingDate: null,
latestSaleAskingPrice: null,
lotPlotSize: isCommercial ? "1.5 Acres" : "0.22 Acres",
// New Fields for Chatbot
pendingSignature: Math.random() > 0.9, // 10% chance
closedDate: Math.random() > 0.8 ? "2026-01-15" : null // Simple mock for revenue queries
},
ownerData: {
ownerId: `OWN-${200 + index}`,
fullName: ownerName,
primaryPhoneNumber: `972-555-${1000 + index}`,
secondaryPhoneNumber: null,
emailAddress: ownerEmail,
mailingAddress: loc.address,
occupation: occupation,
employerName: employerName,
annualIncomeRange: income,
creditScoreRange: "720+",
ownershipType: isCommercial ? "Corporate" : "Individual",
ownershipPercentage: "100%",
willingToRentProperty: Math.random() > 0.8,
desiredMonthlyRentalPrice: null,
rentalConditions: null,
willingToSellProperty: Math.random() > 0.85,
desiredSellingPrice: Math.floor(value * 1.1),
minimumAcceptableSellingPrice: Math.floor(value * 1.05)
},
// New Insurance Data Schema
insuranceData: (() => {
const claimFiled = Math.random() > 0.8; // 20% likely
if (!claimFiled) {
return {
insurance_company: getWeightedRandom(INSURANCE_COMPANIES, Array(10).fill(0.1)),
insurance_company_not_listed: false,
damage_location: null,
date_of_loss: null,
claim_filed: false,
claim_number: null,
has_paperwork: false,
adjuster_name: null,
adjuster_phone: null,
adjuster_ext: null,
adjuster_type: null,
adjuster_fax: null,
adjuster_email: null,
met_with_adjuster: false,
claim_approved: false
};
}
// If claim filed, populate detailed data
const lossDate = new Date();
lossDate.setDate(lossDate.getDate() - Math.floor(Math.random() * 60)); // Last 60 days
return {
insurance_company: getWeightedRandom(INSURANCE_COMPANIES, Array(10).fill(0.1)),
insurance_company_not_listed: false,
damage_location: "Roof, Gutters, Fence",
date_of_loss: lossDate.toISOString().split('T')[0],
claim_filed: true,
claim_number: `CLM-${Math.floor(Math.random() * 1000000)}`,
has_paperwork: Math.random() > 0.3,
adjuster_name: REAL_NAMES[Math.floor(Math.random() * REAL_NAMES.length)],
adjuster_phone: `214-555-${Math.floor(Math.random() * 9000) + 1000}`,
adjuster_ext: `${Math.floor(Math.random() * 900) + 100}`,
adjuster_type: ADJUSTER_TYPES[Math.floor(Math.random() * ADJUSTER_TYPES.length)],
adjuster_fax: `214-555-${Math.floor(Math.random() * 9000) + 1000}`,
adjuster_email: `adjuster.${Math.floor(Math.random() * 100)}@insurance.com`,
met_with_adjuster: Math.random() > 0.5,
claim_approved: Math.random() > 0.7
};
})()
};
});
// 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]
);
}
});
// --- INJECT REQUIRED MOCK DATA FOR ACTION CENTER ---
// A. Unassigned Leads (assignedAgentId: null, canvassingStatus: "Lead")
// Target addresses: 2600 Dunwick Dr, 3900 Arizona Pl, 2112 Winslow Dr, Dallas/Plano Marriott, Legacy Town Center
const unassignedTargets = [
"2600 Dunwick Dr, Plano, TX 75023",
"3900 Arizona Pl, Plano, TX 75023, USA", // Note: original data has USA
"2112 Winslow Dr, Plano, TX 75023",
"Dallas/Plano Marriott at Legacy Town Center, 7121 Bishop Rd, Plano, TX 75024, United States",
"Legacy Town Center Plano, 5760 Daniel Rd, Plano, TX 75024, United States"
];
const unassignedValues = {
"2600 Dunwick Dr, Plano, TX 75023": 53173,
"3900 Arizona Pl, Plano, TX 75023, USA": 11608,
"2112 Winslow Dr, Plano, TX 75023": 40669,
"Dallas/Plano Marriott at Legacy Town Center, 7121 Bishop Rd, Plano, TX 75024, United States": 15766,
"Legacy Town Center Plano, 5760 Daniel Rd, Plano, TX 75024, United States": 12792
};
allProperties.forEach(p => {
const addr = p.propertyData.propertyAddress;
if (unassignedTargets.includes(addr)) {
p.canvassingStatus = "Lead"; // "Lead" = Unassigned basically in this context, or just "Neutral" but we track assignments
p.assignedAgentId = null;
p.propertyData.currentEstimatedMarketValue = unassignedValues[addr];
} else {
// Default random assignment for others if not unassigned
if (p.canvassingStatus !== "Hot Lead") { // Keep Hot Leads potentially unassigned or specific
// p.assignedAgentId = "e1"; // Optional: assign everything else
}
}
});
// B. Hot Leads Not Contacted
// Data: 2629 Rothland Ln (2026-02-08), 3920 Arizona Pl (2026-02-08), 3912 Arizona Pl (Never), 3909 Sailmaker Ln (Never)
const hotLeadTargets = {
"2629 Rothland Ln, Plano, TX 75023": "2026-02-08T10:00:00Z",
"3920 Arizona Pl, Plano, TX 75023, USA": "2026-02-08T14:30:00Z",
"3912 Arizona Pl, Plano, TX 75023, USA": null,
"3909 Sailmaker Ln, Plano, TX 75023, USA": null
};
allProperties.forEach(p => {
if (hotLeadTargets.hasOwnProperty(p.propertyData.propertyAddress)) {
p.canvassingStatus = "Hot Lead";
p.lastContactDate = hotLeadTargets[p.propertyData.propertyAddress];
// Set values if needed match User Data?
// The prompt gave values: 2629 ($20,298), 3920 ($84,288), 3912 ($73,307), 3909 ($72,563)
if (p.propertyData.propertyAddress.includes("2629 Rothland")) p.propertyData.currentEstimatedMarketValue = 20298;
if (p.propertyData.propertyAddress.includes("3920 Arizona")) p.propertyData.currentEstimatedMarketValue = 84288;
if (p.propertyData.propertyAddress.includes("3912 Arizona")) p.propertyData.currentEstimatedMarketValue = 73307;
if (p.propertyData.propertyAddress.includes("3909 Sailmaker")) p.propertyData.currentEstimatedMarketValue = 72563;
}
});
// C. Pending Signatures
// Data: Client 1 (2612 Dunwick), Client 2 (2608 Dunwick), Client 9 (2617 Rothland), Client 12 (6609 Phoenix)
const signatureTargets = {
"2612 Dunwick Dr, Plano, TX 75023": { date: "2026-02-05", val: 8521 },
"2608 Dunwick Dr, Plano, TX 75023": { date: "2026-02-09", val: 16468 },
"2617 Rothland Ln, Plano, TX 75023": { date: "2026-02-08", val: 18392 },
"6609 Phoenix Pl, Plano, TX 75023, USA": { date: "2026-02-06", val: 31768 }
};
allProperties.forEach(p => {
if (signatureTargets.hasOwnProperty(p.propertyData.propertyAddress)) {
p.pendingSignature = true;
p.proposalSentDate = signatureTargets[p.propertyData.propertyAddress].date;
p.proposalValue = signatureTargets[p.propertyData.propertyAddress].val;
p.propertyData.pendingSignature = true; // Sync with inner object if needed, but we extended outer
} else {
p.pendingSignature = false;
}
});
// -------------------------------------------------------
// 3. Assign Tenants (Strict Counts & Data Depth)
// User Request: 10-15 Total Rented. 5-8 with "Complete" info, rest "Sparse" (Mandatory only).
// Current Date Context: Feb 5, 2026.
const totalRented = Math.floor(Math.random() * (15 - 10 + 1)) + 10; // 10 to 15
const fullDetailCount = Math.floor(Math.random() * (8 - 5 + 1)) + 5; // 5 to 8
const sparseDetailCount = totalRented - fullDetailCount;
// Reshuffle for tenant assignment (independent of status)
const tenantIndices = allProperties.map((_, i) => i);
for (let i = tenantIndices.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[tenantIndices[i], tenantIndices[j]] = [tenantIndices[j], tenantIndices[i]];
}
tenantIndices.forEach((propIndex, i) => {
if (i < totalRented) {
const prop = allProperties[propIndex];
const isFullDetail = i < fullDetailCount;
const isCommercial = prop.propertyData.propertyType === "Commercial" || prop.propertyData.propertyType === "Apartments";
const val = prop.propertyData.currentEstimatedMarketValue;
// Generate Base Data (Mandatory)
const tName = isCommercial ? "Global Corp Inc." : REAL_NAMES[(propIndex + 5) % REAL_NAMES.length];
const tPhone = `469-555-${3000 + propIndex}`;
// Optional Data (Full vs Sparse)
const tEmail = isFullDetail ? generateEmail(tName.split(' ')[0], isCommercial ? "enterprises.com" : null) : "";
const tOcc = isFullDetail ? (isCommercial ? "Retail/Office Mix" : OCCUPATIONS[(propIndex + 3) % OCCUPATIONS.length]) : "";
const tEmployer = isFullDetail ? (isCommercial ? "N/A" : (EMPLOYERS_BY_OCCUPATION[tOcc]?.[0] || "Self")) : "";
const tIncome = isFullDetail ? (isCommercial ? "$5M+" : ["$60k", "$85k", "$110k", "$140k"][propIndex % 4]) : "";
const tFamily = isFullDetail ? (isCommercial ? "N/A" : (Math.random() > 0.4 ? "Family" : "Single")) : "Single";
const tLeaseType = isFullDetail ? (isCommercial ? "Commercial NNN" : "Residential Standard") : "Residential Standard";
// Dates (Relative to Feb 2026)
// Start: Jan 2025 - Jan 2026
const startYear = Math.random() > 0.5 ? 2025 : 2026;
const tStart = `${startYear}-01-15`;
// Signed: 1 month before start
const tSigned = `${startYear - 1}-12-15`;
// End: 1 year after start (2026 or 2027)
const tEnd = `${startYear + 1}-01-14`;
const tRent = Math.floor(val * 0.008 / 100) * 100;
// Apply updates
allProperties[propIndex].propertyData = {
...allProperties[propIndex].propertyData,
currentlyRented: true,
currentTenantName: tName,
tenantPhone: tPhone,
// Optional / Detail Dependent
tenantEmail: tEmail,
tenantOccupation: tOcc,
tenantEmployer: tEmployer,
tenantAnnualIncome: tIncome,
livingStatus: tFamily,
leaseType: tLeaseType,
// Dates & Financials (Assign sparse ones too if needed, or leave blank? User said sparse has MANDATORY only. But Rent amount is needed to be "Rented" usually. I'll add Rent/Dates to Full, and maybe just Rent to Sparse?)
// Re-reading: "The remaining entries may include only the mandatory fields."
// I will add rent/dates to ALL rented properties because otherwise the map might look broken for "Rented" status without a lease end date. But strictly, I could leave them empty.
// Let's populate Dates/Rent for ALL, but Personal Info (Email/Job/Income) only for Full.
currentMonthlyRentAmount: tRent,
leaseStartDate: tStart,
leaseEndDate: tEnd,
leaseSignedDate: tSigned,
ownerWillingToRent: false
};
}
});
// 4. Refine Renovation Dates (Recent for 'Renovated' status)
// User Request: Not older than 6 months from Feb 2026 (Aug 2025 - Feb 2026)
allProperties.forEach(prop => {
if (prop.canvassingStatus === "Renovated") {
const monthsBack = Math.floor(Math.random() * 6); // 0 to 5 months ago
// Base date: Feb 2026.
// 0 months ago = Feb 2026. 1 = Jan 2026... 5 = Sep 2025.
// Let's pick a random day.
const year = monthsBack <= 1 ? 2026 : 2025;
let month = 2 - monthsBack; // Feb(2) - 0 = 2. Feb(2) - 5 = -3.
if (month <= 0) month += 12; // Wrap around to previous year
const day = Math.floor(Math.random() * 28) + 1;
const monthStr = month.toString().padStart(2, '0');
const dayStr = day.toString().padStart(2, '0');
prop.propertyData.lastMajorRenovationDate = `${year}-${monthStr}-${dayStr}`;
prop.propertyData.recentMajorRepairs = "Full Interior & Exterior Renovation";
prop.propertyData.renovationDescription = "Modernized kitchen, new flooring, fresh paint, roof inspection";
}
});
return allProperties;
}
// --- NEW DATA (Users & Meetings) ---
const MOCK_USERS = [
// Customers
{ id: 'c1', type: 'customer', username: 'alice', email: 'alice@example.com', password: 'password', name: 'Alice Customer', propertyId: 'P-2600' },
{ id: 'c2', type: 'customer', username: 'bob', email: 'bob@example.com', password: 'password', name: 'Bob Buyer' },
{ id: 'c3', type: 'customer', username: 'charlie', email: 'charlie@example.com', password: 'password', name: 'Charlie Client' },
// Field Agents (5 Agents)
{ id: 'e1', type: 'employee', empId: 'FA001', email: 'agent1@plano.com', password: 'password', role: 'FIELD_AGENT', name: 'Frank Agent', xp: 12450, doorsKnocked: 342, leadsGained: 45, appointmentsSet: 18, streakDays: 5, achievements: ['Hot Spot Hunter', 'Storm Chaser'] },
{ id: 'e2', type: 'employee', empId: 'FA002', email: 'agent2@plano.com', password: 'password', role: 'FIELD_AGENT', name: 'Fiona Field', xp: 8200, doorsKnocked: 215, leadsGained: 30, appointmentsSet: 12, streakDays: 2, achievements: ['Star Closer'] },
{ id: 'e3', type: 'employee', empId: 'FA003', email: 'agent3@plano.com', password: 'password', role: 'FIELD_AGENT', name: 'Fred Flyer', xp: 2100, doorsKnocked: 85, leadsGained: 5, appointmentsSet: 2, streakDays: 0, achievements: [] },
{ id: 'e4', type: 'employee', empId: 'FA004', email: 'agent4@plano.com', password: 'password', role: 'FIELD_AGENT', name: 'Felicity Fast', xp: 15600, doorsKnocked: 410, leadsGained: 65, appointmentsSet: 24, streakDays: 8, achievements: ['Map Master', 'Hot Spot Hunter', 'Storm Chaser'] },
{ id: 'e5', type: 'employee', empId: 'FA005', email: 'agent5@plano.com', password: 'password', role: 'FIELD_AGENT', name: 'Felix Fixer', xp: 5400, doorsKnocked: 156, leadsGained: 20, appointmentsSet: 8, streakDays: 1, achievements: ['First Knock'] },
// Admins (3 Admins)
{ id: 'a1', type: 'employee', empId: 'ADM01', email: 'admin@plano.com', password: 'password', role: 'ADMIN', name: 'Adam Admin' },
{ id: 'a2', type: 'employee', empId: 'ADM02', email: 'admin2@plano.com', password: 'password', role: 'ADMIN', name: 'Amanda Manager' },
{ id: 'a3', type: 'employee', empId: 'ADM03', email: 'admin3@plano.com', password: 'password', role: 'ADMIN', name: 'Arthur Director' },
// --- NEW ROLES (Owners Box) ---
// Owner 1 — Active, strong financials, one project under dispute
{
id: 'own_001',
type: 'owner',
username: 'justin',
email: 'justin@johnsondev.com',
password: 'password',
role: 'OWNER',
name: 'Justin Johnson',
companyName: 'Johnson Development Group',
phone: '972-555-1234'
},
// Owner 2 — High Risk, vendor payment delays, over-budget project
{
id: 'own_002',
type: 'owner',
username: 'diana',
email: 'diana@reevesconstruction.com',
password: 'password',
role: 'OWNER',
name: 'Diana Reeves',
companyName: 'Reeves Construction Partners',
phone: '214-555-5678'
},
// Contractor
{
id: 'con_001',
type: 'contractor',
username: 'mike',
email: 'mike@texasbuilders.com',
password: 'password',
role: 'CONTRACTOR',
name: 'Mike Contractor',
companyName: 'Texas Builders LLC',
licenseNumber: 'TX-GC-123456',
phone: '214-555-4567'
},
// Subcontractor
{
id: 'sub_001',
type: 'subcontractor',
username: 'carlos',
email: 'carlos@electricpro.com',
password: 'password',
role: 'SUBCONTRACTOR',
name: 'Carlos Subcontractor',
companyName: 'Electric Pro Services',
tradeType: 'electrical',
phone: '469-555-9012'
},
// Vendor (Supplier)
{
id: 'ven_001',
type: 'vendor',
username: 'abc_supply',
email: 'sales@abcsupply.com',
password: 'password',
role: 'VENDOR',
name: 'ABC Supply Co.',
companyName: 'ABC Supply',
tradeType: 'materials',
phone: '972-555-8888'
}
];
// --- NEW MOCK SALES HISTORY FOR LEADERBOARD ---
const MOCK_SALES_HISTORY = [
// Frank Agent (High Revenue, Low Volume - "The Sniper")
{ id: 'tx_1', agentId: 'e1', date: '2026-02-10', amount: 450000, status: 'closed_won' },
{ id: 'tx_2', agentId: 'e1', date: '2026-02-05', amount: 520000, status: 'closed_won' },
{ id: 'tx_3', agentId: 'e1', date: '2026-01-28', amount: 380000, status: 'closed_won' },
{ id: 'tx_4', agentId: 'e1', date: '2026-02-01', amount: 0, status: 'closed_lost' }, // Lost deal
// Fiona Field (High Volume, Mid Revenue - "The Grinder")
{ id: 'tx_5', agentId: 'e2', date: '2026-02-09', amount: 250000, status: 'closed_won' },
{ id: 'tx_6', agentId: 'e2', date: '2026-02-08', amount: 240000, status: 'closed_won' },
{ id: 'tx_7', agentId: 'e2', date: '2026-02-06', amount: 260000, status: 'closed_won' },
{ id: 'tx_8', agentId: 'e2', date: '2026-01-30', amount: 230000, status: 'closed_won' },
{ id: 'tx_9', agentId: 'e2', date: '2026-02-02', amount: 255000, status: 'closed_won' },
{ id: 'tx_10', agentId: 'e2', date: '2026-01-25', amount: 0, status: 'closed_lost' },
{ id: 'tx_11', agentId: 'e2', date: '2026-01-20', amount: 0, status: 'closed_lost' },
// Fred Flyer (New/Low Performance)
{ id: 'tx_12', agentId: 'e3', date: '2026-02-07', amount: 180000, status: 'closed_won' },
{ id: 'tx_13', agentId: 'e3', date: '2026-02-03', amount: 0, status: 'closed_lost' },
{ id: 'tx_14', agentId: 'e3', date: '2026-01-29', amount: 0, status: 'closed_lost' },
// Felicity Fast (Consistent)
{ id: 'tx_15', agentId: 'e4', date: '2026-02-10', amount: 310000, status: 'closed_won' },
{ id: 'tx_16', agentId: 'e4', date: '2026-02-04', amount: 305000, status: 'closed_won' },
{ id: 'tx_17', agentId: 'e4', date: '2026-01-27', amount: 295000, status: 'closed_won' },
// Felix Fixer (Closer - High Win Rate)
{ id: 'tx_18', agentId: 'e5', date: '2026-02-08', amount: 410000, status: 'closed_won' },
{ id: 'tx_19', agentId: 'e5', date: '2026-02-01', amount: 390000, status: 'closed_won' },
];
// Helper to generate meetings
function generateMockMeetings() {
const agents = ['e1', 'e2', 'e3', 'e4', 'e5'];
const statuses = ['Scheduled', 'Rescheduled', 'Completed', 'Converted', 'Cancelled'];
const meetings = [];
let meetingIdCounter = 1;
agents.forEach(agentId => {
// Generate ~7 meetings per agent
for (let i = 0; i < 7; i++) {
const isPast = i < 4; // First 4 are past/completed/converted
const status = isPast
? (Math.random() > 0.3 ? 'Completed' : (Math.random() > 0.5 ? 'Converted' : 'Cancelled')) // Past mix
: (Math.random() > 0.3 ? 'Scheduled' : 'Rescheduled'); // Future mix
// Date Logic
const date = new Date();
date.setDate(date.getDate() + (isPast ? -1 * (i + 1) * 2 : (i + 1) * 2)); // Spread out days
// Deal Value (only for relevant statuses)
let dealValue = null;
if (['Completed', 'Converted'].includes(status)) {
dealValue = Math.floor(Math.random() * (50000 - 5000) + 5000); // 5k to 50k
}
// Time Logic (09:00 to 16:00)
const hour = 9 + (i % 8);
const timeString = `${hour.toString().padStart(2, '0')}:00`;
// New Data Fields for Chatbot Context
const issues = [
"Leaking skylight in master bath",
"Missing shingles after recent storm",
"Water spots on ceiling",
"Gutter detachment on north side",
"General roof inspection requested"
];
const comments = [
"Customer is worried about upcoming rain.",
"Insurance adjuster already visited.",
"Prefer morning appointments.",
"Dog in backyard, please knock front door.",
"Previous contractor did poor work."
];
meetings.push({
id: `m${meetingIdCounter++}`,
agentId: agentId,
customerName: REAL_NAMES[(meetingIdCounter * 3) % REAL_NAMES.length], // Pick random names
propertyId: `P-${2600 + (meetingIdCounter * 2)}`,
date: date.toISOString().split('T')[0],
time: timeString,
status: status,
dealValue: dealValue,
notes: status === 'Converted' ? 'Contract signed for full roof replacement.' :
status === 'Rescheduled' ? 'Client verified availability.' : 'Standard consultation.',
// New Fields
issueDescription: issues[i % issues.length],
customerComments: comments[i % comments.length],
outcome: status === 'Converted' ? 'Signed Contract' : status === 'Completed' ? 'Quote Sent' : 'Pending'
});
}
});
// Generate Alice's Demo Meetings
const aliceMeetings = [
// Upcoming
{
id: `m-alice-1`,
agentId: 'e1',
customerName: 'Alice Customer',
customerId: 'c1', // Explicit ID link
propertyId: 'P-Alice-1',
date: new Date(Date.now() + 86400000 * 2).toISOString().split('T')[0], // 2 days from now
time: '14:00',
status: 'Scheduled',
agentName: 'Frank Agent',
notes: 'Initial Roof Inspection',
issueDescription: 'Noticed missing shingles after last storm.',
customerComments: 'Gate code is 1234.',
outcome: 'Pending'
},
// History
{
id: `m-alice-2`,
agentId: 'e2',
customerName: 'Alice Customer',
customerId: 'c1',
propertyId: 'P-Alice-1',
date: new Date(Date.now() - 86400000 * 15).toISOString().split('T')[0], // 15 days ago
time: '10:00',
status: 'Completed',
agentName: 'Fiona Field',
dealValue: 1500,
notes: 'Minor repairs completed. Payment received.',
issueDescription: 'Leak in garage.',
customerComments: 'Please call before arriving.',
outcome: 'Repairs Completed'
},
{
id: `m-alice-3`,
agentId: 'e1',
customerName: 'Alice Customer',
customerId: 'c1',
propertyId: 'P-Alice-1',
date: new Date(Date.now() - 86400000 * 45).toISOString().split('T')[0], // 45 days ago
time: '11:00',
status: 'Completed',
agentName: 'Frank Agent',
dealValue: 0,
notes: 'Consultation - Quote provided.',
issueDescription: 'General inspection.',
customerComments: '',
outcome: 'Quote Sent'
}
];
meetings.push(...aliceMeetings);
return meetings;
}
const MOCK_MEETINGS = generateMockMeetings();
// --- OWNER PROFILES ---
const MOCK_OWNERS = [
{
id: 'own_001',
companyName: 'Johnson Development Group',
primaryContact: 'Justin Johnson',
email: 'justin@johnsondev.com',
phone: '972-555-1234',
companyType: 'Real Estate Developer',
portfolioSize: 6,
activeProjects: 4,
completedProjects: 1,
onHoldProjects: 1,
totalInvestmentValue: 187000,
riskScore: 28,
status: 'Active',
location: { city: 'Plano', state: 'TX' },
memberSince: '2023-06-15',
lastActivityDate: '2026-02-15',
dashboardSummary: {
totalBudget: 187000,
committedCost: 156200,
actualSpent: 131500,
roiProjection: 12.4,
pendingApprovals: 3,
openChangeOrders: 2,
openRFIs: 1,
disputes: 1,
upcomingMilestones: [
{ name: 'Shingle Install Complete', project: '2604 Dunwick Dr', dueDate: '2026-02-14', projectId: 'proj_001' },
{ name: 'Electrical Hookup', project: '6613 Phoenix Pl', dueDate: '2026-02-14', projectId: 'proj_003' },
{ name: 'Flooring and Trim', project: '2612 Dunwick Dr', dueDate: '2026-02-18', projectId: 'proj_004' },
{ name: 'Panel Replacement', project: '3913 Arizona Pl', dueDate: '2026-02-20', projectId: 'proj_006' }
],
cashFlowForecast: [
{ month: 'Mar 2026', inflow: 45000, outflow: 38000 },
{ month: 'Apr 2026', inflow: 32000, outflow: 28000 },
{ month: 'May 2026', inflow: 18000, outflow: 15000 },
{ month: 'Jun 2026', inflow: 12000, outflow: 8000 },
{ month: 'Jul 2026', inflow: 8000, outflow: 5000 },
{ month: 'Aug 2026', inflow: 5000, outflow: 3000 }
],
monthlySpend: [
{ month: 'Mar 2025', amount: 0 },
{ month: 'Apr 2025', amount: 0 },
{ month: 'May 2025', amount: 0 },
{ month: 'Jun 2025', amount: 0 },
{ month: 'Jul 2025', amount: 0 },
{ month: 'Aug 2025', amount: 0 },
{ month: 'Sep 2025', amount: 0 },
{ month: 'Oct 2025', amount: 0 },
{ month: 'Nov 2025', amount: 8500 },
{ month: 'Dec 2025', amount: 33200 },
{ month: 'Jan 2026', amount: 52800 },
{ month: 'Feb 2026', amount: 37000 }
]
}
},
{
id: 'own_002',
companyName: 'Reeves Construction Partners',
primaryContact: 'Diana Reeves',
email: 'diana@reevesconstruction.com',
phone: '214-555-5678',
companyType: 'Institutional',
portfolioSize: 6,
activeProjects: 3,
completedProjects: 1,
onHoldProjects: 2,
totalInvestmentValue: 430000,
riskScore: 72,
status: 'High Risk',
location: { city: 'Plano', state: 'TX' },
memberSince: '2024-01-10',
lastActivityDate: '2026-02-12',
dashboardSummary: {
totalBudget: 430000,
committedCost: 385000,
actualSpent: 291300,
roiProjection: 4.8,
pendingApprovals: 5,
openChangeOrders: 5,
openRFIs: 3,
disputes: 2,
upcomingMilestones: [
{ name: 'Section A - TPO Install', project: '6909 Custer Rd', dueDate: '2026-02-28', projectId: 'proj_007' },
{ name: 'Final Grade and Drainage', project: '2112 Winslow Dr', dueDate: '2026-02-10', projectId: 'proj_008' },
{ name: 'Floor 2 Installation', project: '7224 Independence Pkwy', dueDate: '2026-02-14', projectId: 'proj_009' },
{ name: 'Waterproofing Application', project: 'Legacy Town Center', dueDate: '2026-02-12', projectId: 'proj_011' }
],
cashFlowForecast: [
{ month: 'Mar 2026', inflow: 85000, outflow: 92000 },
{ month: 'Apr 2026', inflow: 72000, outflow: 68000 },
{ month: 'May 2026', inflow: 55000, outflow: 45000 },
{ month: 'Jun 2026', inflow: 40000, outflow: 32000 },
{ month: 'Jul 2026', inflow: 25000, outflow: 18000 },
{ month: 'Aug 2026', inflow: 15000, outflow: 10000 }
],
monthlySpend: [
{ month: 'Mar 2025', amount: 0 },
{ month: 'Apr 2025', amount: 0 },
{ month: 'May 2025', amount: 0 },
{ month: 'Jun 2025', amount: 0 },
{ month: 'Jul 2025', amount: 0 },
{ month: 'Aug 2025', amount: 0 },
{ month: 'Sep 2025', amount: 14200 },
{ month: 'Oct 2025', amount: 35000 },
{ month: 'Nov 2025', amount: 52000 },
{ month: 'Dec 2025', amount: 68400 },
{ month: 'Jan 2026', amount: 74200 },
{ month: 'Feb 2026', amount: 47500 }
]
}
}
];
// --- NEW OWNERS BOX DATA SCHEMAS ---
const MOCK_PERSONNEL = [
{
id: 'p1',
name: 'Jesus Gonzales',
role: 'W2_EMPLOYEE',
email: 'jesus@lynkeduppro.com',
phone: '214-555-0101',
team: 'Sales Team A',
manager: 'Justin Johnson',
sensitiveData: {
ssn: '123-45-6789',
bankAccount: '9876543210'
},
compliance: {
w9Signed: true,
payPlanSigned: true,
driverLicense: {
uploaded: true,
expirationDate: '2026-08-15',
status: 'compliant'
}
},
status: 'active'
},
{
id: 'p2',
name: 'Sarah Sales',
role: '1099_SALES_REP',
email: 'sarah@lynkeduppro.com',
phone: '214-555-0102',
team: 'Sales Team A',
manager: 'Jesus Gonzales',
sensitiveData: {
ssn: '987-65-4321',
bankAccount: '1234567890'
},
compliance: {
w9Signed: true,
payPlanSigned: false,
driverLicense: {
uploaded: true,
expirationDate: '2025-12-01',
status: 'expiring'
}
},
status: 'active'
}
];
const MOCK_VENDORS = [
{
id: 'v1',
vendorName: 'Texas Roofing Crew A',
vendorType: 'roofing_crew',
primaryContact: {
name: 'Juan Perez',
email: 'juan@texasroofing.com',
phone: '469-555-0201'
},
sensitiveData: {
ein: '12-3456789',
bankAccount: '1122334455'
},
compliance: {
w9: { uploaded: true, status: 'approved' },
subcontractorAgreement: { uploaded: true, status: 'approved' },
coi: {
uploaded: true,
expirationDate: '2026-06-30',
status: 'compliant'
}
},
spend: {
totalSpend: 218000,
lastPayment: { date: '2026-02-08', amount: 18500 },
ytdSpend: 67000,
pendingInvoices: 4200
},
performance: {
rating: 4.8,
onTimeRate: 0.95,
jobsCompleted: 42,
activeJobs: 3
},
status: 'active'
},
{
id: 'v2',
vendorName: 'Sparky Electric',
vendorType: 'electrical',
primaryContact: {
name: 'Mike Spark',
email: 'mike@sparky.com',
phone: '469-555-0202'
},
sensitiveData: {
ein: '98-7654321',
bankAccount: '5544332211'
},
compliance: {
w9: { uploaded: true, status: 'approved' },
subcontractorAgreement: { uploaded: false, status: 'pending' },
coi: {
uploaded: true,
expirationDate: '2026-01-15',
status: 'expired'
}
},
spend: {
totalSpend: 9200,
lastPayment: { date: '2025-12-15', amount: 1800 },
ytdSpend: 0,
pendingInvoices: 3400
},
performance: {
rating: 4.2,
onTimeRate: 0.88,
jobsCompleted: 8,
activeJobs: 1
},
status: 'non_compliant'
},
{
id: 'v3',
vendorName: 'ABC Supply Co.',
vendorType: 'material_supplier',
primaryContact: {
name: 'Sales Desk',
email: 'sales@abcsupply.com',
phone: '972-555-8888'
},
sensitiveData: {
ein: '55-4433221',
bankAccount: '9988776655'
},
compliance: {
w9: { uploaded: true, status: 'approved' },
subcontractorAgreement: { uploaded: true, status: 'approved' },
coi: { uploaded: true, status: 'compliant', expirationDate: '2027-01-01' }
},
spend: {
totalSpend: 312000,
lastPayment: { date: '2026-02-12', amount: 22400 },
ytdSpend: 98000,
pendingInvoices: 15600
},
performance: {
rating: 5.0,
onTimeRate: 0.99,
jobsCompleted: 124,
activeJobs: 7
},
status: 'active'
},
{
id: 'v4',
vendorName: 'Lone Star Plumbing',
vendorType: 'plumbing',
primaryContact: {
name: 'Ray Gutierrez',
email: 'ray@lonestarplumbing.com',
phone: '469-555-0304'
},
sensitiveData: {
ein: '33-2211009',
bankAccount: '4455667788'
},
compliance: {
w9: { uploaded: true, status: 'approved' },
subcontractorAgreement: { uploaded: true, status: 'approved' },
coi: {
uploaded: true,
expirationDate: '2026-03-05',
status: 'compliant'
}
},
spend: {
totalSpend: 86000,
lastPayment: { date: '2026-01-20', amount: 7200 },
ytdSpend: 14500,
pendingInvoices: 8900
},
performance: {
rating: 4.5,
onTimeRate: 0.91,
jobsCompleted: 19,
activeJobs: 2
},
status: 'active'
},
{
id: 'v5',
vendorName: 'DFW Foundation Pros',
vendorType: 'foundation',
primaryContact: {
name: 'Tom Atkins',
email: 'tom@dfwfoundation.com',
phone: '214-555-0405'
},
sensitiveData: {
ein: '44-5566778',
bankAccount: '7788991100'
},
compliance: {
w9: { uploaded: false, status: 'pending' },
subcontractorAgreement: { uploaded: true, status: 'approved' },
coi: {
uploaded: true,
expirationDate: '2026-09-15',
status: 'compliant'
}
},
spend: {
totalSpend: 142000,
lastPayment: { date: '2026-01-10', amount: 24000 },
ytdSpend: 24000,
pendingInvoices: 18500
},
performance: {
rating: 3.9,
onTimeRate: 0.82,
jobsCompleted: 11,
activeJobs: 2
},
status: 'non_compliant'
},
{
id: 'v6',
vendorName: 'North Texas HVAC Solutions',
vendorType: 'hvac',
primaryContact: {
name: 'Linda Foster',
email: 'linda@ntxhvac.com',
phone: '972-555-0506'
},
sensitiveData: {
ein: '66-7788990',
bankAccount: '2233445566'
},
compliance: {
w9: { uploaded: true, status: 'approved' },
subcontractorAgreement: { uploaded: true, status: 'approved' },
coi: {
uploaded: true,
expirationDate: '2026-11-20',
status: 'compliant'
}
},
spend: {
totalSpend: 178000,
lastPayment: { date: '2026-02-05', amount: 9800 },
ytdSpend: 32000,
pendingInvoices: 6700
},
performance: {
rating: 4.6,
onTimeRate: 0.93,
jobsCompleted: 27,
activeJobs: 3
},
status: 'active'
}
];
const MOCK_ORDERS = [
{
id: 'ORD-001',
vendorId: 'v3',
projectId: 'proj_001',
projectAddress: '2604 Dunwick Dr, Plano, TX 75023',
orderDate: '2026-01-18',
dueDate: '2026-01-28',
deliveryDate: '2026-01-27',
status: 'delivered',
items: [
{
id: 'item_001',
description: 'Roofing Shingles - Architectural',
quantity: 50,
unit: 'bundles',
unitPrice: 45.00,
total: 2250.00,
specifications: 'GAF Timberline HDZ, Charcoal'
},
{
id: 'item_002',
description: 'Roofing Underlayment',
quantity: 10,
unit: 'rolls',
unitPrice: 85.00,
total: 850.00,
specifications: 'Synthetic, 10 sq per roll'
}
],
subtotal: 3100.00,
tax: 255.75,
total: 3355.75,
deliveryAddress: {
street: '2604 Dunwick Dr',
city: 'Plano',
state: 'TX',
zip: '75023',
instructions: 'Deliver to side yard, call foreman on arrival'
},
timeline: [
{ date: '2026-01-18', event: 'Order Placed', status: 'completed' },
{ date: '2026-01-19', event: 'Order Confirmed', status: 'completed' },
{ date: '2026-01-24', event: 'Shipped', status: 'completed' },
{ date: '2026-01-27', event: 'Delivered', status: 'completed' }
],
documents: [
{ id: 'odoc_001', type: 'PO', name: 'PO-2604-Dunwick.pdf', url: '#' },
{ id: 'odoc_002', type: 'Invoice', name: 'INV-ORD001.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: ABC Supply Co., Project Contractor: Texas Builders LLC
notes: 'Rush order for weather window',
contactPerson: 'Juan Perez',
contactPhone: '469-555-0201'
},
{
id: 'ORD-002',
vendorId: 'v3',
projectId: 'proj_002',
projectAddress: '2617 Rothland Ln, Plano, TX 75023',
orderDate: '2025-11-10',
dueDate: '2025-11-20',
deliveryDate: '2025-11-19',
status: 'delivered',
items: [
{
id: 'item_003',
description: 'Gutter System - Seamless Aluminum',
quantity: 150,
unit: 'linear feet',
unitPrice: 12.50,
total: 1875.00,
specifications: 'White, 5-inch K-style'
},
{
id: 'item_004',
description: 'Downspout Extensions',
quantity: 8,
unit: 'pieces',
unitPrice: 28.00,
total: 224.00,
specifications: 'Aluminum, matching white'
}
],
subtotal: 2099.00,
tax: 173.17,
total: 2272.17,
deliveryAddress: {
street: '2617 Rothland Ln',
city: 'Plano',
state: 'TX',
zip: '75023',
instructions: 'Leave at garage side'
},
timeline: [
{ date: '2025-11-10', event: 'Order Placed', status: 'completed' },
{ date: '2025-11-11', event: 'Order Confirmed', status: 'completed' },
{ date: '2025-11-17', event: 'Shipped', status: 'completed' },
{ date: '2025-11-19', event: 'Delivered', status: 'completed' }
],
documents: [
{ id: 'odoc_003', type: 'PO', name: 'PO-2617-Rothland.pdf', url: '#' },
{ id: 'odoc_004', type: 'Delivery Receipt', name: 'DR-ORD002.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: ABC Supply Co., Project Contractor: Texas Builders LLC
notes: 'Completed project delivery - all materials accounted for',
contactPerson: 'Sales Desk',
contactPhone: '972-555-8888'
},
{
id: 'ORD-003',
vendorId: 'v6',
projectId: 'proj_003',
projectAddress: '6613 Phoenix Pl, Plano, TX 75023',
orderDate: '2026-01-25',
dueDate: '2026-02-08',
deliveryDate: null,
status: 'shipped',
items: [
{
id: 'item_005',
description: 'Commercial HVAC Unit - 5 Ton',
quantity: 2,
unit: 'units',
unitPrice: 4200.00,
total: 8400.00,
specifications: 'Carrier 14 SEER2, R-410A'
},
{
id: 'item_006',
description: 'Ductwork - Flex',
quantity: 200,
unit: 'linear feet',
unitPrice: 6.50,
total: 1300.00,
specifications: 'R-8 insulated, 8-inch diameter'
}
],
subtotal: 9700.00,
tax: 800.25,
total: 10500.25,
deliveryAddress: {
street: '6613 Phoenix Pl',
city: 'Plano',
state: 'TX',
zip: '75023',
instructions: 'Equipment pad on south side of building'
},
timeline: [
{ date: '2026-01-25', event: 'Order Placed', status: 'completed' },
{ date: '2026-01-27', event: 'Order Confirmed', status: 'completed' },
{ date: '2026-02-03', event: 'Shipped', status: 'completed' },
{ date: '2026-02-08', event: 'Estimated Delivery', status: 'pending' }
],
documents: [
{ id: 'odoc_005', type: 'PO', name: 'PO-6613-Phoenix-HVAC.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: North Texas HVAC Solutions, Project Contractor: Texas Builders LLC
notes: 'HVAC units backordered 5 days, pushed delivery date',
contactPerson: 'Linda Foster',
contactPhone: '972-555-0506'
},
{
id: 'ORD-004',
vendorId: 'v5',
projectId: 'proj_008',
projectAddress: '2112 Winslow Dr, Plano, TX 75023',
orderDate: '2025-12-02',
dueDate: '2025-12-15',
deliveryDate: '2025-12-14',
status: 'delivered',
items: [
{
id: 'item_007',
description: 'Steel Piers - Foundation',
quantity: 18,
unit: 'piers',
unitPrice: 420.00,
total: 7560.00,
specifications: 'Galvanized steel, 12-foot depth rated'
},
{
id: 'item_008',
description: 'Hydraulic Jacks - Rental',
quantity: 6,
unit: 'units',
unitPrice: 180.00,
total: 1080.00,
specifications: '20-ton capacity, 30-day rental'
}
],
subtotal: 8640.00,
tax: 712.80,
total: 9352.80,
deliveryAddress: {
street: '2112 Winslow Dr',
city: 'Plano',
state: 'TX',
zip: '75023',
instructions: 'Loading dock access required, heavy equipment'
},
timeline: [
{ date: '2025-12-02', event: 'Order Placed', status: 'completed' },
{ date: '2025-12-03', event: 'Order Confirmed', status: 'completed' },
{ date: '2025-12-10', event: 'Shipped', status: 'completed' },
{ date: '2025-12-14', event: 'Delivered', status: 'completed' }
],
documents: [
{ id: 'odoc_006', type: 'PO', name: 'PO-Winslow-Foundation.pdf', url: '#' },
{ id: 'odoc_007', type: 'Invoice', name: 'INV-ORD004.pdf', url: '#' },
{ id: 'odoc_008', type: 'Delivery Receipt', name: 'DR-ORD004.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: DFW Foundation Pros, Project Contractor: Texas Builders LLC
notes: 'Foundation repair materials - additional piers ordered due to scope expansion',
contactPerson: 'Tom Atkins',
contactPhone: '214-555-0405'
},
{
id: 'ORD-005',
vendorId: 'v3',
projectId: 'proj_007',
projectAddress: '6909 Custer Rd, Plano, TX 75023',
orderDate: '2026-02-01',
dueDate: '2026-02-14',
deliveryDate: null,
status: 'confirmed',
items: [
{
id: 'item_009',
description: 'Commercial TPO Membrane',
quantity: 120,
unit: 'rolls',
unitPrice: 95.00,
total: 11400.00,
specifications: '60 mil, white, 10-ft wide'
},
{
id: 'item_010',
description: 'Roof Insulation Boards',
quantity: 300,
unit: 'sheets',
unitPrice: 18.50,
total: 5550.00,
specifications: 'Polyiso, 2-inch, 4x8'
},
{
id: 'item_011',
description: 'Mechanical Fasteners',
quantity: 40,
unit: 'boxes',
unitPrice: 52.00,
total: 2080.00,
specifications: 'FM-approved, #14 x 3-inch'
}
],
subtotal: 19030.00,
tax: 1569.98,
total: 20599.98,
deliveryAddress: {
street: '6909 Custer Rd',
city: 'Plano',
state: 'TX',
zip: '75023',
instructions: 'Crane lift to rooftop, coordinate 48hrs in advance'
},
timeline: [
{ date: '2026-02-01', event: 'Order Placed', status: 'completed' },
{ date: '2026-02-03', event: 'Order Confirmed', status: 'completed' },
{ date: '2026-02-10', event: 'Estimated Ship Date', status: 'pending' },
{ date: '2026-02-14', event: 'Estimated Delivery', status: 'pending' }
],
documents: [
{ id: 'odoc_009', type: 'PO', name: 'PO-Custer-Commercial-Roof.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: ABC Supply Co., Project Contractor: Texas Builders LLC
notes: 'Large commercial order - confirm crane availability before ship',
contactPerson: 'Sales Desk',
contactPhone: '972-555-8888'
},
{
id: 'ORD-006',
vendorId: 'v4',
projectId: 'proj_012',
projectAddress: 'Dallas/Plano Marriott at Legacy Town Center, 7121 Bishop Rd, Plano, TX 75024',
orderDate: '2026-01-15',
dueDate: '2026-01-30',
deliveryDate: '2026-01-29',
status: 'delivered',
items: [
{
id: 'item_012',
description: 'Commercial Grade PVC Pipe - 4 inch',
quantity: 400,
unit: 'linear feet',
unitPrice: 8.75,
total: 3500.00,
specifications: 'Schedule 40, SDR-26'
},
{
id: 'item_013',
description: 'Ball Valves - Brass',
quantity: 24,
unit: 'pieces',
unitPrice: 42.00,
total: 1008.00,
specifications: '2-inch, full port, lead-free'
},
{
id: 'item_014',
description: 'Water Heater - Commercial Tankless',
quantity: 3,
unit: 'units',
unitPrice: 2800.00,
total: 8400.00,
specifications: 'Rinnai CU199iN, 199K BTU'
}
],
subtotal: 12908.00,
tax: 1064.91,
total: 13972.91,
deliveryAddress: {
street: '7121 Bishop Rd',
city: 'Plano',
state: 'TX',
zip: '75024',
instructions: 'Service entrance, coordinate with building management'
},
timeline: [
{ date: '2026-01-15', event: 'Order Placed', status: 'completed' },
{ date: '2026-01-16', event: 'Order Confirmed', status: 'completed' },
{ date: '2026-01-24', event: 'Shipped', status: 'completed' },
{ date: '2026-01-29', event: 'Delivered', status: 'completed' }
],
documents: [
{ id: 'odoc_010', type: 'PO', name: 'PO-Marriott-Plumbing.pdf', url: '#' },
{ id: 'odoc_011', type: 'Delivery Receipt', name: 'DR-ORD006.pdf', url: '#' },
{ id: 'odoc_012', type: 'Invoice', name: 'INV-ORD006.pdf', url: '#' }
],
// TODO: cross-reference — Vendor: Lone Star Plumbing, Project Contractor: Texas Builders LLC
notes: 'Plumbing overhaul materials - project currently on hold pending permit review',
contactPerson: 'Ray Gutierrez',
contactPhone: '469-555-0304'
},
{
id: 'ORD-007',
vendorId: 'v3',
projectId: 'proj_004',
projectAddress: '2612 Dunwick Dr, Plano, TX 75023',
orderDate: '2026-02-15',
dueDate: '2026-02-28',
deliveryDate: null,
status: 'pending',
items: [
{ id: 'item_015', description: 'Interior Drywall Sheets', quantity: 80, unit: 'sheets', unitPrice: 14.50, total: 1160.00, specifications: '4x8, 1/2-inch, fire-rated' },
{ id: 'item_016', description: 'Joint Compound', quantity: 12, unit: 'buckets', unitPrice: 22.00, total: 264.00, specifications: 'All-purpose, 5-gallon' }
],
subtotal: 1424.00,
tax: 117.48,
total: 1541.48,
deliveryAddress: { street: '2612 Dunwick Dr', city: 'Plano', state: 'TX', zip: '75023', instructions: 'Front entrance, stack in garage' },
timeline: [
{ date: '2026-02-15', event: 'Order Placed', status: 'completed' },
{ date: '2026-02-28', event: 'Estimated Delivery', status: 'pending' }
],
documents: [{ id: 'odoc_013', type: 'PO', name: 'PO-Dunwick-Drywall.pdf', url: '#' }],
notes: 'Awaiting vendor confirmation',
contactPerson: 'Sales Desk',
contactPhone: '972-555-8888'
},
{
id: 'ORD-008',
vendorId: 'v3',
projectId: 'proj_009',
projectAddress: '7224 Independence Pkwy, Plano, TX 75025',
orderDate: '2026-02-10',
dueDate: '2026-02-22',
deliveryDate: null,
status: 'shipped',
items: [
{ id: 'item_017', description: 'Window Sealant - Exterior Grade', quantity: 48, unit: 'tubes', unitPrice: 8.50, total: 408.00, specifications: 'Silicone, clear, UV-resistant' },
{ id: 'item_018', description: 'Flashing Tape - Self-Adhesive', quantity: 20, unit: 'rolls', unitPrice: 35.00, total: 700.00, specifications: '6-inch, peel-and-stick, 75-ft' }
],
subtotal: 1108.00,
tax: 91.41,
total: 1199.41,
deliveryAddress: { street: '7224 Independence Pkwy', city: 'Plano', state: 'TX', zip: '75025', instructions: 'Leave at side entrance' },
timeline: [
{ date: '2026-02-10', event: 'Order Placed', status: 'completed' },
{ date: '2026-02-11', event: 'Order Confirmed', status: 'completed' },
{ date: '2026-02-17', event: 'Shipped', status: 'completed' },
{ date: '2026-02-22', event: 'Estimated Delivery', status: 'pending' }
],
documents: [{ id: 'odoc_014', type: 'PO', name: 'PO-Independence-Sealant.pdf', url: '#' }],
notes: 'In transit via FedEx Freight',
contactPerson: 'Sales Desk',
contactPhone: '972-555-8888'
}
];
const MOCK_VENDOR_INVOICES = [
{
id: 'INV-2026-001',
vendorId: 'v3',
orderId: 'ORD-002',
projectId: 'proj_002',
project: '2617 Rothland Ln, Plano, TX 75023',
invoiceDate: '2025-11-22',
dueDate: '2025-12-07',
amount: 2272.17,
status: 'paid',
paymentTerms: 'Net 15',
description: 'Gutter System and Downspout Materials'
},
{
id: 'INV-2026-002',
vendorId: 'v3',
orderId: 'ORD-001',
projectId: 'proj_001',
project: '2604 Dunwick Dr, Plano, TX 75023',
invoiceDate: '2026-01-28',
dueDate: '2026-02-12',
amount: 3355.75,
status: 'pending',
paymentTerms: 'Net 15',
description: 'Roofing Shingles and Underlayment Delivery'
},
{
id: 'INV-2026-003',
vendorId: 'v6',
orderId: 'ORD-003',
projectId: 'proj_003',
project: '6613 Phoenix Pl, Plano, TX 75023',
invoiceDate: '2026-02-04',
dueDate: '2026-02-19',
amount: 10500.25,
status: 'pending',
paymentTerms: 'Net 15',
description: 'HVAC Units and Ductwork Delivery'
},
{
id: 'INV-2026-004',
vendorId: 'v5',
orderId: 'ORD-004',
projectId: 'proj_008',
project: '2112 Winslow Dr, Plano, TX 75023',
invoiceDate: '2025-12-16',
dueDate: '2025-12-31',
amount: 9352.80,
status: 'paid',
paymentTerms: 'Net 15',
description: 'Foundation Steel Piers and Equipment Rental'
},
{
id: 'INV-2026-005',
vendorId: 'v3',
orderId: 'ORD-005',
projectId: 'proj_007',
project: '6909 Custer Rd, Plano, TX 75023',
invoiceDate: '2026-02-03',
dueDate: '2026-02-18',
amount: 20599.98,
status: 'pending',
paymentTerms: 'Net 15',
description: 'Commercial TPO Roofing Materials'
},
{
id: 'INV-2026-006',
vendorId: 'v4',
orderId: 'ORD-006',
projectId: 'proj_012',
project: 'Dallas/Plano Marriott, 7121 Bishop Rd, Plano, TX 75024',
invoiceDate: '2026-01-30',
dueDate: '2026-02-14',
amount: 13972.91,
status: 'pending',
paymentTerms: 'Net 15',
description: 'Commercial Plumbing Materials and Water Heaters'
},
{
id: 'INV-2026-007',
vendorId: 'v1',
orderId: 'ORD-LABOR-001',
projectId: 'proj_004',
project: '2612 Dunwick Dr, Plano, TX 75023',
invoiceDate: '2026-02-10',
dueDate: '2026-02-25',
amount: 8750.00,
status: 'pending',
paymentTerms: 'Net 15',
description: 'Interior Renovation - Roofing Crew Labor Week 3'
},
{
id: 'INV-2026-008',
vendorId: 'v3',
orderId: 'ORD-MAT-006',
projectId: 'proj_006',
project: '3913 Arizona Pl, Plano, TX 75023',
invoiceDate: '2026-02-07',
dueDate: '2026-02-22',
amount: 2850.00,
status: 'pending',
paymentTerms: 'Net 15',
description: 'Electrical Panel and Circuit Breaker Materials'
},
{
id: 'INV-2025-045',
vendorId: 'v1',
orderId: 'ORD-HIST-001',
projectId: 'proj_010',
project: '2100 Legacy Dr, Plano, TX 75023',
invoiceDate: '2025-10-15',
dueDate: '2025-10-30',
amount: 14200.00,
status: 'paid',
paymentTerms: 'Net 15',
description: 'Parking Lot Resurfacing Crew Labor'
},
{
id: 'INV-2025-046',
vendorId: 'v3',
orderId: 'ORD-HIST-002',
projectId: 'proj_010',
project: '2100 Legacy Dr, Plano, TX 75023',
invoiceDate: '2025-10-02',
dueDate: '2025-10-17',
amount: 8400.00,
status: 'paid',
paymentTerms: 'Net 15',
description: 'Asphalt and Sealant Materials'
}
];
const MOCK_DOCUMENTS = [
{
id: 'd1',
name: 'Jesus Gonzales - Driver License',
entityId: 'p1',
entityType: 'personnel',
entityName: 'Jesus Gonzales',
vendorId: 'v1',
documentType: 'DL',
fileName: 'JG_DriverLicense.pdf',
fileUrl: '#',
uploadedBy: 'Jesus Gonzales',
uploadedAt: '2025-08-15',
expirationDate: '2026-08-15',
status: 'approved',
aiConfidence: 0.98,
reviewedBy: 'Admin',
reviewedAt: '2025-08-16'
},
{
id: 'd2',
name: 'Sparky Electric - Certificate of Insurance',
entityId: 'v2',
entityType: 'vendor',
entityName: 'Sparky Electric',
vendorId: 'v2',
documentType: 'COI',
fileName: 'Sparky_COI_2025.pdf',
fileUrl: '#',
uploadedBy: 'Mike Spark',
uploadedAt: '2025-01-10',
expirationDate: '2026-01-15',
status: 'expired',
aiConfidence: 0.95,
reviewedBy: 'Admin',
reviewedAt: '2025-01-11'
},
{
id: 'd3',
name: 'Sarah Sales - Pay Plan Agreement',
entityId: 'p2',
entityType: 'personnel',
entityName: 'Sarah Sales',
vendorId: 'v1',
documentType: 'PAY_PLAN',
fileName: 'Sarah_PayPlan_Signed.pdf',
fileUrl: '#',
uploadedBy: 'Sarah Sales',
uploadedAt: '2026-02-14',
expirationDate: '2027-02-14',
status: 'pending_review',
aiConfidence: 0.88,
reviewedBy: null,
reviewedAt: null
},
{
id: 'd4',
name: 'Lone Star Plumbing - Certificate of Insurance',
entityId: 'v4',
entityType: 'vendor',
entityName: 'Lone Star Plumbing',
vendorId: 'v4',
documentType: 'COI',
fileName: 'LoneStarPlumbing_COI_2026.pdf',
fileUrl: '#',
uploadedBy: 'Ray Gutierrez',
uploadedAt: '2025-03-10',
expirationDate: '2026-03-05',
status: 'approved',
aiConfidence: 0.96,
reviewedBy: 'Admin',
reviewedAt: '2025-03-11'
},
{
id: 'd5',
name: 'DFW Foundation Pros - W9 Form',
entityId: 'v5',
entityType: 'vendor',
entityName: 'DFW Foundation Pros',
vendorId: 'v5',
documentType: 'W9',
fileName: 'DFW_Foundation_W9.pdf',
fileUrl: '#',
uploadedBy: 'Tom Atkins',
uploadedAt: '2026-01-20',
expirationDate: '2027-01-20',
status: 'pending_review',
aiConfidence: 0.82,
reviewedBy: null,
reviewedAt: null
},
{
id: 'd6',
name: 'Texas Roofing Crew A - Subcontractor Agreement',
entityId: 'v1',
entityType: 'vendor',
entityName: 'Texas Roofing Crew A',
vendorId: 'v1',
documentType: 'SUB_AGREEMENT',
fileName: 'TexasRoofing_SubAgreement_2026.pdf',
fileUrl: '#',
uploadedBy: 'Juan Perez',
uploadedAt: '2025-12-01',
expirationDate: '2026-12-01',
status: 'approved',
aiConfidence: 0.97,
reviewedBy: 'Admin',
reviewedAt: '2025-12-02'
},
{
id: 'd7',
name: 'North Texas HVAC - Certificate of Insurance',
entityId: 'v6',
entityType: 'vendor',
entityName: 'North Texas HVAC Solutions',
vendorId: 'v6',
documentType: 'COI',
fileName: 'NTXHVAC_COI_2026.pdf',
fileUrl: '#',
uploadedBy: 'Linda Foster',
uploadedAt: '2025-11-25',
expirationDate: '2026-11-20',
status: 'approved',
aiConfidence: 0.94,
reviewedBy: 'Admin',
reviewedAt: '2025-11-26'
},
{
id: 'd8',
name: 'ABC Supply Co. - Certificate of Insurance',
entityId: 'v3',
entityType: 'vendor',
entityName: 'ABC Supply Co.',
vendorId: 'v3',
documentType: 'COI',
fileName: 'ABCSupply_COI_2027.pdf',
fileUrl: '#',
uploadedBy: 'Sales Desk',
uploadedAt: '2026-01-05',
expirationDate: '2027-01-01',
status: 'approved',
aiConfidence: 0.99,
reviewedBy: 'Admin',
reviewedAt: '2026-01-06'
},
{
id: 'd9',
name: 'Sparky Electric - W9 Form',
entityId: 'v2',
entityType: 'vendor',
entityName: 'Sparky Electric',
vendorId: 'v2',
documentType: 'W9',
fileName: 'Sparky_W9_2026.pdf',
fileUrl: '#',
uploadedBy: 'Mike Spark',
uploadedAt: '2026-02-01',
expirationDate: '2027-02-01',
status: 'approved',
aiConfidence: 0.91,
reviewedBy: 'Admin',
reviewedAt: '2026-02-02'
},
{
id: 'd10',
name: 'DFW Foundation Pros - Certificate of Insurance',
entityId: 'v5',
entityType: 'vendor',
entityName: 'DFW Foundation Pros',
vendorId: 'v5',
documentType: 'COI',
fileName: 'DFW_Foundation_COI_2026.pdf',
fileUrl: '#',
uploadedBy: 'Tom Atkins',
uploadedAt: '2025-09-20',
expirationDate: '2026-09-15',
status: 'approved',
aiConfidence: 0.93,
reviewedBy: 'Admin',
reviewedAt: '2025-09-21'
}
];
const MOCK_PROJECTS = [
// =====================================================================
// OWNER 1: Marcus Whitfield (own_001) — 6 Projects
// Active owner, strong financials, one project under dispute
// =====================================================================
// Project 1: Active, on track, healthy budget
{
id: 'proj_001',
ownerId: 'own_001',
propertyId: 'P-2602',
address: '2604 Dunwick Dr, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Roof Replacement',
status: 'active',
phase: 'Structural',
budget: 45000,
approvedBudget: 45000,
committedCost: 38500,
actualCost: 22500,
spent: 22500,
variancePercent: -50.0,
margin: 0.40,
startDate: '2026-01-20',
endDate: '2026-03-05',
completionPercentage: 55,
healthScore: 82,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 2,
budgetBreakdown: [
{ category: 'Materials - Shingles', allocated: 15000, committed: 14200, actual: 8500 },
{ category: 'Materials - Underlayment', allocated: 3500, committed: 3355, actual: 3355 },
{ category: 'Labor - Tear Off', allocated: 8000, committed: 8000, actual: 8000 },
{ category: 'Labor - Install', allocated: 12000, committed: 7200, actual: 0 },
{ category: 'Permits & Inspection', allocated: 2500, committed: 2500, actual: 2645 },
{ category: 'Cleanup & Haul-Away', allocated: 4000, committed: 3245, actual: 0 }
],
changeOrders: [],
rfis: [],
riskLog: [
{ id: 'risk_001_1', description: 'Weather delay risk during February', severity: 'Medium', likelihood: 'Likely', mitigation: 'Monitor 10-day forecast, flex schedule for rain days', status: 'monitoring' },
{ id: 'risk_001_2', description: 'Material price increase from supplier', severity: 'Low', likelihood: 'Unlikely', mitigation: 'Price locked with PO', status: 'mitigated' }
],
issueLog: [],
paymentSchedule: [
{ id: 'ps_001_1', milestone: 'Mobilization (20%)', amount: 9000, dueDate: '2026-01-22', status: 'paid' },
{ id: 'ps_001_2', milestone: 'Tear-off Complete (30%)', amount: 13500, dueDate: '2026-02-01', status: 'paid' },
{ id: 'ps_001_3', milestone: 'Install Complete (30%)', amount: 13500, dueDate: '2026-02-20', status: 'pending' },
{ id: 'ps_001_4', milestone: 'Final Inspection (20%)', amount: 9000, dueDate: '2026-03-05', status: 'pending' }
],
activityTimeline: [
{ date: '2026-02-12', action: 'Invoice Submitted', user: 'ABC Supply Co.', details: 'INV-001-2 for roofing materials - $3,355.75' },
{ date: '2026-02-08', action: 'Milestone Completed', user: 'Texas Roofing Crew A', details: 'Dry-In Inspection passed' },
{ date: '2026-02-01', action: 'Payment Released', user: 'Justin Johnson', details: 'Tear-off milestone payment - $12,000' },
{ date: '2026-01-27', action: 'Material Delivered', user: 'ABC Supply Co.', details: 'Shingles and underlayment delivered to site' },
{ date: '2026-01-20', action: 'Project Started', user: 'Texas Builders LLC', details: 'Roof replacement project kicked off' }
],
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: ABC Supply Co., Texas Roofing Crew A
milestones: [
{ id: 'ms_001_1', name: 'Material Delivery', dueDate: '2026-01-25', status: 'completed', assignedTo: 'v3' },
{ id: 'ms_001_2', name: 'Roof Tear-off', dueDate: '2026-01-30', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_001_3', name: 'Dry-In Inspection', dueDate: '2026-02-03', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_001_4', name: 'Shingle Install', dueDate: '2026-02-14', status: 'in_progress', assignedTo: 'v1' },
{ id: 'ms_001_5', name: 'Final Inspection', dueDate: '2026-03-01', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_001_1', amount: 12000, submittedBy: 'con_001', status: 'paid', dueDate: '2026-02-01', datePaid: '2026-02-02' },
{ id: 'inv_001_2', amount: 3355.75, submittedBy: 'v3', status: 'pending', dueDate: '2026-02-12' },
{ id: 'inv_001_3', amount: 7200, submittedBy: 'v1', status: 'pending', dueDate: '2026-02-20' }
],
documents: [
{ name: 'Scope of Work - Roof Replacement', url: '#', type: 'contract' },
{ name: 'Permit #26-0401', url: '#', type: 'permit' },
{ name: 'Material Order PO-2604', url: '#', type: 'invoice' }
]
},
// Project 2: Completed, zero variance (perfectly on budget)
{
id: 'proj_002',
ownerId: 'own_001',
propertyId: 'P-2608',
address: '2617 Rothland Ln, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: [],
projectType: 'Gutter Replacement',
status: 'completed',
phase: 'Handover',
budget: 8500,
approvedBudget: 8500,
committedCost: 8500,
actualCost: 8500,
spent: 8500,
variancePercent: 0,
margin: 0.35,
startDate: '2025-11-15',
endDate: '2025-12-10',
completionPercentage: 100,
healthScore: 100,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 0,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: ABC Supply Co.
milestones: [
{ id: 'ms_002_1', name: 'Old Gutter Removal', dueDate: '2025-11-18', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_002_2', name: 'Material Delivery', dueDate: '2025-11-20', status: 'completed', assignedTo: 'v3' },
{ id: 'ms_002_3', name: 'Seamless Gutter Install', dueDate: '2025-11-28', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_002_4', name: 'Downspout Routing', dueDate: '2025-12-03', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_002_5', name: 'Final Walkthrough', dueDate: '2025-12-08', status: 'completed', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_002_1', amount: 2272.17, submittedBy: 'v3', status: 'paid', dueDate: '2025-11-25', datePaid: '2025-11-26' },
{ id: 'inv_002_2', amount: 4200, submittedBy: 'con_001', status: 'paid', dueDate: '2025-12-05', datePaid: '2025-12-06' },
{ id: 'inv_002_3', amount: 2027.83, submittedBy: 'con_001', status: 'paid', dueDate: '2025-12-10', datePaid: '2025-12-10' }
],
documents: [
{ name: 'Scope of Work - Gutter', url: '#', type: 'contract' },
{ name: 'Completion Certificate', url: '#', type: 'certificate' },
{ name: 'Final Invoice Package', url: '#', type: 'invoice' },
{ name: 'Warranty Registration', url: '#', type: 'warranty' }
]
},
// Project 3: Delayed with missed milestone
{
id: 'proj_003',
ownerId: 'own_001',
propertyId: 'P-2610',
address: '6613 Phoenix Pl, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'HVAC Installation',
status: 'active',
phase: 'MEP',
budget: 32000,
approvedBudget: 32000,
committedCost: 28200,
actualCost: 18400,
spent: 18400,
variancePercent: -42.5,
margin: 0.30,
startDate: '2026-01-06',
endDate: '2026-02-28',
completionPercentage: 42,
healthScore: 58,
openRFIs: 1,
changeOrderCount: 2,
pendingInvoiceCount: 2,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: North Texas HVAC Solutions, ABC Supply Co.
milestones: [
{ id: 'ms_003_1', name: 'Site Preparation', dueDate: '2026-01-10', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_003_2', name: 'Ductwork Rough-In', dueDate: '2026-01-20', status: 'completed', assignedTo: 'v6' },
{ id: 'ms_003_3', name: 'Equipment Delivery', dueDate: '2026-01-30', status: 'completed', assignedTo: 'v6' },
{ id: 'ms_003_4', name: 'Unit Installation', dueDate: '2026-02-07', status: 'in_progress', assignedTo: 'v6' },
{ id: 'ms_003_5', name: 'Electrical Hookup', dueDate: '2026-02-14', status: 'pending', assignedTo: 'sub_001' },
{ id: 'ms_003_6', name: 'System Test and Commissioning', dueDate: '2026-02-25', status: 'pending', assignedTo: 'v6' }
],
budgetBreakdown: [
{ category: 'Equipment & Materials', allocated: 15000, committed: 15000, actual: 12500 },
{ category: 'Labor - HVAC', allocated: 8000, committed: 8000, actual: 4000 },
{ category: 'Labor - Electrical', allocated: 3000, committed: 3000, actual: 0 },
{ category: 'Permits & Fees', allocated: 1000, committed: 1000, actual: 950 },
{ category: 'Contingency', allocated: 5000, committed: 1200, actual: 950 }
],
invoices: [
{ id: 'inv_003_1', amount: 8200, submittedBy: 'con_001', status: 'paid', dueDate: '2026-01-15', datePaid: '2026-01-16' },
{ id: 'inv_003_2', amount: 10500.25, submittedBy: 'v6', status: 'pending', dueDate: '2026-02-19' },
{ id: 'inv_003_3', amount: 3400, submittedBy: 'v2', status: 'pending', dueDate: '2026-02-22' }
],
changeOrders: [
{ id: 'CO-003-01', title: 'Upsize Return Ducts', amount: 1200, status: 'approved', dateSubmitted: '2026-01-22', description: 'Increase return duct size for better airflow in master bedroom.' },
{ id: 'CO-003-02', title: 'Smart Thermostat Upgrade', amount: 450, status: 'pending', dateSubmitted: '2026-02-18', description: 'Upgrade to Ecobee Premium thermostats per owner request.' }
],
rfis: [
{ id: 'RFI-003-01', subject: 'Condenser Pad Location', status: 'closed', submittedBy: 'North Texas HVAC', dateOpened: '2026-01-12', dateClosed: '2026-01-14' },
{ id: 'RFI-003-02', subject: 'Duct Routing Conflict in Attic', status: 'open', submittedBy: 'Texas Builders LLC', dateOpened: '2026-02-15' }
],
riskLog: [
{ id: 'risk_003_1', description: 'Equipment backorder from manufacturer', severity: 'High', likelihood: 'Likely', mitigation: 'Source equivalent unit from secondary distributor', status: 'open' }
],
issueLog: [
{ id: 'issue_003_1', title: 'Failed framing inspection for duct clearance', priority: 'High', status: 'open', assignedTo: 'Texas Builders LLC', dateReported: '2026-02-14' }
],
activityTimeline: [
{ date: '2026-02-15', action: 'RFI Submitted', user: 'Site Supervisor', details: 'Duct routing conflict in attic' },
{ date: '2026-02-14', action: 'Inspection Failed', user: 'City Inspector', details: 'Framing clearance insufficient for 12" ducts' },
{ date: '2026-01-30', action: 'Milestone Completed', user: 'North Texas HVAC', details: 'Equipment Delivery phase finished' }
],
documents: [
{ name: 'HVAC Design Plans', url: '#', type: 'plans' },
{ name: 'Mechanical Permit #26-0187', url: '#', type: 'permit' },
{ name: 'Equipment Spec Sheets', url: '#', type: 'specification' }
]
},
// Project 4: Active, over budget (spent > budget)
{
id: 'proj_004',
ownerId: 'own_001',
propertyId: 'P-2600',
address: '2612 Dunwick Dr, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Interior Renovation',
status: 'active',
phase: 'Finishing',
budget: 55000,
approvedBudget: 55000,
committedCost: 62300,
actualCost: 62300,
spent: 62300,
variancePercent: 13.3,
margin: -0.13,
startDate: '2025-12-01',
endDate: '2026-02-28',
completionPercentage: 78,
healthScore: 35,
openRFIs: 1,
changeOrderCount: 2,
pendingInvoiceCount: 2,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: ABC Supply Co., Texas Roofing Crew A, Sparky Electric
milestones: [
{ id: 'ms_004_1', name: 'Demo and Abatement', dueDate: '2025-12-10', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_004_2', name: 'Framing and Structural', dueDate: '2025-12-22', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_004_3', name: 'Electrical Rough-In', dueDate: '2026-01-08', status: 'completed', assignedTo: 'sub_001' },
{ id: 'ms_004_4', name: 'Plumbing Rough-In', dueDate: '2026-01-15', status: 'completed', assignedTo: 'v4' },
{ id: 'ms_004_5', name: 'Drywall and Paint', dueDate: '2026-02-05', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_004_6', name: 'Flooring and Trim', dueDate: '2026-02-18', status: 'in_progress', assignedTo: 'con_001' },
{ id: 'ms_004_7', name: 'Final Punch List', dueDate: '2026-02-25', status: 'pending', assignedTo: 'con_001' }
],
budgetBreakdown: [
{ category: 'Demolition', allocated: 5000, committed: 5500, actual: 5500 },
{ category: 'Framing & Structural', allocated: 8000, committed: 8500, actual: 8500 },
{ category: 'Electrical', allocated: 7000, committed: 7000, actual: 4800 },
{ category: 'Plumbing', allocated: 6000, committed: 6500, actual: 6500 },
{ category: 'Drywall & Paint', allocated: 9000, committed: 10000, actual: 10000 },
{ category: 'Flooring & Trim', allocated: 12000, committed: 15500, actual: 15500 },
{ category: 'Contingency', allocated: 8000, committed: 9300, actual: 11500 }
],
changeOrders: [
{ id: 'CO-004-01', title: 'Scope Expansion - Kitchen Island', amount: 4500, status: 'approved', dateSubmitted: '2026-01-10', description: 'Add a custom 6ft island with quartz countertop and built-in microwave.' },
{ id: 'CO-004-02', title: 'Hardwood Flooring Upgrade', amount: 2800, status: 'approved', dateSubmitted: '2026-01-25', description: 'Upgrade from LVP to engineered hardwood in living areas.' }
],
rfis: [
{ id: 'RFI-004-01', subject: 'Load-bearing wall clarification', status: 'closed', submittedBy: 'Texas Builders LLC', dateOpened: '2025-12-15', dateClosed: '2025-12-16' },
{ id: 'RFI-004-02', subject: 'Paint finish in bathrooms', status: 'open', submittedBy: 'Texas Builders LLC', dateOpened: '2026-02-02' }
],
riskLog: [
{ id: 'risk_004_1', description: 'Flooring shipment delayed at port', severity: 'High', likelihood: 'Likely', mitigation: 'Source alternative matching material from local distributor', status: 'open' },
{ id: 'risk_004_2', description: 'Paint color mismatch between batches', severity: 'Medium', likelihood: 'Possible', mitigation: 'Verify batch numbers before final coat', status: 'mitigated' }
],
issueLog: [
{ id: 'issue_004_1', title: 'Drywall texturing inconsistent in hallway', priority: 'Medium', status: 'open', assignedTo: 'Texas Builders LLC', dateReported: '2026-02-16' },
{ id: 'issue_004_2', title: 'Plumbing rough-in failed initial inspection', priority: 'High', status: 'resolved', assignedTo: 'Lone Star Plumbing', dateReported: '2026-01-16' }
],
activityTimeline: [
{ date: '2026-02-16', action: 'Issue Reported', user: 'Site Supervisor', details: 'Drywall texture inconsistent in main hallway' },
{ date: '2026-02-05', action: 'Milestone Completed', user: 'Texas Builders LLC', details: 'Drywall and Paint phase finished' },
{ date: '2026-01-22', action: 'Payment Released', user: 'Marcus Whitfield', details: 'Truss and framing payment - $12,800' },
{ date: '2026-01-18', action: 'Inspection Passed', user: 'City Inspector', details: 'Plumbing rough-in re-inspection passed' }
],
invoices: [
{ id: 'inv_004_1', amount: 18000, submittedBy: 'con_001', status: 'paid', dueDate: '2025-12-15', datePaid: '2025-12-16' },
{ id: 'inv_004_2', amount: 15500, submittedBy: 'con_001', status: 'paid', dueDate: '2026-01-10', datePaid: '2026-01-12' },
{ id: 'inv_004_3', amount: 12800, submittedBy: 'v3', status: 'paid', dueDate: '2026-01-20', datePaid: '2026-01-22' },
{ id: 'inv_004_3b', amount: 4800, submittedBy: 'sub_001', status: 'paid', dueDate: '2026-01-12', datePaid: '2026-01-14' },
{ id: 'inv_004_4', amount: 8750, submittedBy: 'v1', status: 'pending', dueDate: '2026-02-25' },
{ id: 'inv_004_5', amount: 7250, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-28' }
],
documents: [
{ name: 'Interior Renovation Contract', url: '#', type: 'contract' },
{ name: 'Building Permit #25-1892', url: '#', type: 'permit' },
{ name: 'Change Order #1 - Scope Expansion', url: '#', type: 'change_order' },
{ name: 'Change Order #2 - Material Upgrade', url: '#', type: 'change_order' },
{ name: 'Asbestos Abatement Report', url: '#', type: 'report' }
]
},
// Project 5: On Hold with pending dispute
{
id: 'proj_005',
ownerId: 'own_001',
propertyId: 'P-2601',
address: '2608 Dunwick Dr, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: [],
projectType: 'Siding Replacement',
status: 'on_hold',
phase: 'Structural',
budget: 28000,
approvedBudget: 28000,
committedCost: 20700,
actualCost: 14200,
spent: 14200,
variancePercent: -49.3,
margin: 0.25,
startDate: '2026-01-06',
endDate: '2026-02-20',
completionPercentage: 38,
healthScore: 42,
openRFIs: 0,
changeOrderCount: 1,
pendingInvoiceCount: 1,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: ABC Supply Co.
milestones: [
{ id: 'ms_005_1', name: 'Scaffolding Setup', dueDate: '2026-01-08', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_005_2', name: 'Old Siding Removal', dueDate: '2026-01-15', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_005_3', name: 'Moisture Barrier Install', dueDate: '2026-01-22', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_005_4', name: 'New Siding Install', dueDate: '2026-02-05', status: 'pending', assignedTo: 'con_001' },
{ id: 'ms_005_5', name: 'Trim and Caulking', dueDate: '2026-02-15', status: 'pending', assignedTo: 'con_001' }
],
budgetBreakdown: [
{ category: 'Materials - Siding', allocated: 12000, committed: 12000, actual: 8000 },
{ category: 'Labor - Prep & Install', allocated: 9000, committed: 9000, actual: 3500 },
{ category: 'Equipment Rental', allocated: 2000, committed: 2000, actual: 1500 },
{ category: 'Structural Repairs (CO)', allocated: 0, committed: 850, actual: 850 },
{ category: 'Contingency', allocated: 5000, committed: 5000, actual: 350 }
],
invoices: [
{ id: 'inv_005_1', amount: 8400, submittedBy: 'con_001', status: 'paid', dueDate: '2026-01-12', datePaid: '2026-01-13' },
{ id: 'inv_005_2', amount: 5800, submittedBy: 'v3', status: 'paid', dueDate: '2026-01-20', datePaid: '2026-01-21' },
{ id: 'inv_005_3', amount: 6500, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-10' }
],
changeOrders: [
{ id: 'CO-005-01', title: 'Rotten Fascia Board Replacement', amount: 850, status: 'approved', dateSubmitted: '2026-01-18', description: 'Replace 40 linear feet of rotted fascia discovered during tear-off.' }
],
rfis: [
{ id: 'RFI-005-01', subject: 'Vapor Barrier Specification', status: 'closed', submittedBy: 'Texas Builders LLC', dateOpened: '2026-01-20', dateClosed: '2026-01-21' }
],
riskLog: [
{ id: 'risk_005_1', description: 'Water damage hidden behind existing siding', severity: 'High', likelihood: 'Certain', mitigation: 'Halt work, assess rot, submit change order for structural repair.', status: 'realized' }
],
issueLog: [
{ id: 'issue_005_1', title: 'Defective siding panels delivered', priority: 'Critical', status: 'open', assignedTo: 'ABC Supply Co.', dateReported: '2026-02-04' }
],
activityTimeline: [
{ date: '2026-02-06', action: 'Project Paused', user: 'System', details: 'Status changed to On Hold due to material dispute' },
{ date: '2026-02-04', action: 'Issue Reported', user: 'Site Supervisor', details: 'Batch of siding panels showed unacceptable warping' },
{ date: '2026-01-22', action: 'Milestone Completed', user: 'Texas Builders LLC', details: 'Moisture Barrier Install finished' }
],
documents: [
{ name: 'Siding Replacement Contract', url: '#', type: 'contract' },
{ name: 'Dispute Notice - Material Defect', url: '#', type: 'dispute' },
{ name: 'Manufacturer Warranty Claim', url: '#', type: 'warranty' },
{ name: 'Site Photos - Defective Panels', url: '#', type: 'photos' }
]
},
// Project 6: Active, on track, early stage
{
id: 'proj_006',
ownerId: 'own_001',
propertyId: 'P-2625',
address: '3913 Arizona Pl, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Electrical Upgrade',
status: 'active',
phase: 'MEP',
budget: 18500,
approvedBudget: 18500,
committedCost: 12400,
actualCost: 5600,
spent: 5600,
variancePercent: -69.7,
margin: 0.38,
startDate: '2026-02-03',
endDate: '2026-03-15',
completionPercentage: 22,
healthScore: 88,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 1,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: Sparky Electric
milestones: [
{ id: 'ms_006_1', name: 'Panel Assessment', dueDate: '2026-02-05', status: 'completed', assignedTo: 'sub_001' },
{ id: 'ms_006_2', name: 'Permit Approval', dueDate: '2026-02-10', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_006_3', name: 'Panel Replacement', dueDate: '2026-02-20', status: 'in_progress', assignedTo: 'sub_001' },
{ id: 'ms_006_4', name: 'Circuit Re-routing', dueDate: '2026-03-01', status: 'pending', assignedTo: 'sub_001' },
{ id: 'ms_006_5', name: 'City Inspection', dueDate: '2026-03-12', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_006_1', amount: 2200, submittedBy: 'sub_001', status: 'paid', dueDate: '2026-02-08', datePaid: '2026-02-09' },
{ id: 'inv_006_2', amount: 3400, submittedBy: 'sub_001', status: 'pending', dueDate: '2026-02-22' }
],
documents: [
{ name: 'Electrical Upgrade Proposal', url: '#', type: 'contract' },
{ name: 'Electrical Permit #26-0223', url: '#', type: 'permit' },
{ name: 'Load Calculation Report', url: '#', type: 'report' }
]
},
// =====================================================================
// OWNER 2: Diana Reeves (own_002) — 6 Projects
// High risk owner, vendor payment delays, over-budget project
// =====================================================================
// Project 7: Active, on track, healthy budget (commercial)
{
id: 'proj_007',
ownerId: 'own_002',
propertyId: 'P-2640',
address: '6909 Custer Rd, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Commercial Roof Replacement',
status: 'active',
phase: 'Structural',
budget: 125000,
approvedBudget: 125000,
committedCost: 98000,
actualCost: 48000,
spent: 48000,
variancePercent: -61.6,
margin: 0.35,
startDate: '2026-01-27',
endDate: '2026-04-15',
completionPercentage: 32,
healthScore: 78,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 2,
budgetBreakdown: [
{ category: 'Materials - TPO Membrane', allocated: 38000, committed: 35400, actual: 11400 },
{ category: 'Materials - Insulation', allocated: 18000, committed: 16800, actual: 5550 },
{ category: 'Materials - Fasteners/Adhesive', allocated: 8000, committed: 7200, actual: 2080 },
{ category: 'Labor - Section A', allocated: 22000, committed: 18500, actual: 18500 },
{ category: 'Labor - Section B', allocated: 22000, committed: 8000, actual: 0 },
{ category: 'Crane Rental', allocated: 8000, committed: 5600, actual: 4200 },
{ category: 'Permits & Inspection', allocated: 4000, committed: 3500, actual: 3270 },
{ category: 'Safety Equipment', allocated: 5000, committed: 3000, actual: 3000 }
],
changeOrders: [
{ id: 'CO-007-1', title: 'Additional Drainage Scuppers', amount: 4200, status: 'pending', dateSubmitted: '2026-02-10', description: 'Building management requested 4 additional scuppers on east elevation for improved water management' }
],
rfis: [
{ id: 'RFI-007-1', subject: 'Deck Condition Under Section B', status: 'open', submittedBy: 'Texas Roofing Crew A', dateOpened: '2026-02-14', dateClosed: null },
{ id: 'RFI-007-2', subject: 'Flashing Detail at Parapet Wall', status: 'closed', submittedBy: 'Texas Builders LLC', dateOpened: '2026-02-03', dateClosed: '2026-02-06' }
],
riskLog: [
{ id: 'risk_007_1', description: 'Roof deck deterioration may require additional repairs', severity: 'High', likelihood: 'Possible', mitigation: 'Structural assessment scheduled before Section B tear-off', status: 'open' },
{ id: 'risk_007_2', description: 'High winds could delay membrane installation', severity: 'Medium', likelihood: 'Likely', mitigation: 'Schedule membrane work on low-wind days, use mechanical fasteners as backup', status: 'monitoring' },
{ id: 'risk_007_3', description: 'Supply chain delay on TPO rolls', severity: 'Low', likelihood: 'Unlikely', mitigation: 'Full order confirmed and 60% already delivered', status: 'mitigated' }
],
issueLog: [
{ id: 'issue_007_1', title: 'Crane access blocked by tenant parking', priority: 'Medium', status: 'resolved', assignedTo: 'Texas Builders LLC', dateReported: '2026-02-01' },
{ id: 'issue_007_2', title: 'Section A tear-off revealed wet insulation', priority: 'High', status: 'open', assignedTo: 'Texas Roofing Crew A', dateReported: '2026-02-14' }
],
paymentSchedule: [
{ id: 'ps_007_1', milestone: 'Mobilization (20%)', amount: 25000, dueDate: '2026-01-30', status: 'paid' },
{ id: 'ps_007_2', milestone: 'Section A Complete (25%)', amount: 31250, dueDate: '2026-03-01', status: 'pending' },
{ id: 'ps_007_3', milestone: 'Section B Complete (25%)', amount: 31250, dueDate: '2026-03-30', status: 'pending' },
{ id: 'ps_007_4', milestone: 'Final Inspection (20%)', amount: 25000, dueDate: '2026-04-10', status: 'pending' },
{ id: 'ps_007_5', milestone: 'Warranty Registration (10%)', amount: 12500, dueDate: '2026-04-15', status: 'pending' }
],
activityTimeline: [
{ date: '2026-02-14', action: 'RFI Submitted', user: 'Texas Roofing Crew A', details: 'RFI-007-1: Deck condition under Section B needs assessment' },
{ date: '2026-02-14', action: 'Issue Reported', user: 'Texas Roofing Crew A', details: 'Wet insulation found during Section A tear-off' },
{ date: '2026-02-10', action: 'Change Order Submitted', user: 'Texas Builders LLC', details: 'CO-007-1: Additional drainage scuppers requested - $4,200' },
{ date: '2026-02-06', action: 'RFI Closed', user: 'Texas Builders LLC', details: 'RFI-007-2: Flashing detail resolved per manufacturer spec' },
{ date: '2026-02-03', action: 'Milestone Completed', user: 'ABC Supply Co.', details: 'Material procurement complete - all TPO delivered' },
{ date: '2026-01-30', action: 'Payment Released', user: 'Diana Reeves', details: 'Mobilization payment - $25,000' },
{ date: '2026-01-27', action: 'Project Started', user: 'Texas Builders LLC', details: 'Commercial roof replacement kicked off' }
],
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: ABC Supply Co., Texas Roofing Crew A
milestones: [
{ id: 'ms_007_1', name: 'Roof Survey and Assessment', dueDate: '2026-01-30', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_007_2', name: 'Material Procurement', dueDate: '2026-02-07', status: 'completed', assignedTo: 'v3' },
{ id: 'ms_007_3', name: 'Section A - Tear Off', dueDate: '2026-02-14', status: 'completed', assignedTo: 'v1' },
{ id: 'ms_007_4', name: 'Section A - TPO Install', dueDate: '2026-02-28', status: 'in_progress', assignedTo: 'v1' },
{ id: 'ms_007_5', name: 'Section B - Tear Off', dueDate: '2026-03-15', status: 'pending', assignedTo: 'v1' },
{ id: 'ms_007_6', name: 'Section B - TPO Install', dueDate: '2026-03-30', status: 'pending', assignedTo: 'v1' },
{ id: 'ms_007_7', name: 'Final Inspection and Warranty', dueDate: '2026-04-10', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_007_1', amount: 25000, submittedBy: 'con_001', status: 'paid', dueDate: '2026-02-05', datePaid: '2026-02-06' },
{ id: 'inv_007_2', amount: 20599.98, submittedBy: 'v3', status: 'pending', dueDate: '2026-02-18' },
{ id: 'inv_007_3', amount: 18500, submittedBy: 'v1', status: 'pending', dueDate: '2026-02-28' }
],
documents: [
{ name: 'Commercial Roofing Contract', url: '#', type: 'contract' },
{ name: 'Commercial Building Permit #26-0312', url: '#', type: 'permit' },
{ name: 'TPO Manufacturer Spec', url: '#', type: 'specification' },
{ name: 'Roof Survey Report', url: '#', type: 'report' },
{ name: 'Safety Plan - Fall Protection', url: '#', type: 'safety' }
]
},
// Project 8: Active, over budget (spent > budget)
{
id: 'proj_008',
ownerId: 'own_002',
propertyId: 'P-2641',
address: '2112 Winslow Dr, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: [],
projectType: 'Foundation Repair',
status: 'active',
phase: 'Finishing',
budget: 75000,
approvedBudget: 75000,
committedCost: 91500,
actualCost: 91500,
spent: 91500,
variancePercent: 22.0,
margin: -0.22,
startDate: '2025-11-18',
endDate: '2026-02-28',
completionPercentage: 88,
healthScore: 25,
openRFIs: 0,
changeOrderCount: 2,
pendingInvoiceCount: 2,
// TODO: cross-reference — Contractor: Texas Builders LLC, Vendors: DFW Foundation Pros, ABC Supply Co.
milestones: [
{ id: 'ms_008_1', name: 'Structural Engineering Report', dueDate: '2025-11-22', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_008_2', name: 'Pier Installation - East', dueDate: '2025-12-06', status: 'completed', assignedTo: 'v5' },
{ id: 'ms_008_3', name: 'Pier Installation - West', dueDate: '2025-12-20', status: 'completed', assignedTo: 'v5' },
{ id: 'ms_008_4', name: 'Slab Lifting', dueDate: '2026-01-10', status: 'completed', assignedTo: 'v5' },
{ id: 'ms_008_5', name: 'Plumbing Re-test', dueDate: '2026-01-25', status: 'completed', assignedTo: 'v4' },
{ id: 'ms_008_6', name: 'Final Grade and Drainage', dueDate: '2026-02-10', status: 'in_progress', assignedTo: 'con_001' },
{ id: 'ms_008_7', name: 'Engineering Re-certification', dueDate: '2026-02-25', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_008_1', amount: 30000, submittedBy: 'con_001', status: 'paid', dueDate: '2025-12-01', datePaid: '2025-12-03' },
{ id: 'inv_008_2', amount: 9352.80, submittedBy: 'v5', status: 'paid', dueDate: '2025-12-20', datePaid: '2025-12-22' },
{ id: 'inv_008_3', amount: 24000, submittedBy: 'v5', status: 'paid', dueDate: '2026-01-15', datePaid: '2026-01-18' },
{ id: 'inv_008_4', amount: 18500, submittedBy: 'v5', status: 'pending', dueDate: '2026-02-15' },
{ id: 'inv_008_5', amount: 9647.20, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-28' }
],
documents: [
{ name: 'Foundation Repair Contract', url: '#', type: 'contract' },
{ name: 'Structural Engineering Report', url: '#', type: 'report' },
{ name: 'Pier Layout Diagram', url: '#', type: 'plans' },
{ name: 'Change Order #1 - Additional Piers', url: '#', type: 'change_order' },
{ name: 'Change Order #2 - Plumbing Reroute', url: '#', type: 'change_order' },
{ name: 'Soil Analysis Report', url: '#', type: 'report' }
]
},
// Project 9: Delayed with missed milestone
{
id: 'proj_009',
ownerId: 'own_002',
propertyId: 'P-2642',
address: '7224 Independence Pkwy, Plano, TX 75025',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Window Replacement',
status: 'active',
budget: 42000,
spent: 25800,
margin: 0.28,
startDate: '2026-01-13',
endDate: '2026-03-10',
completionPercentage: 50,
phase: 'Finishing',
approvedBudget: 42000,
committedCost: 32000,
actualCost: 25800,
variancePercent: -38.6,
healthScore: 55,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 1,
milestones: [
{ id: 'ms_009_1', name: 'Window Measurements', dueDate: '2026-01-16', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_009_2', name: 'Custom Window Fabrication', dueDate: '2026-01-30', status: 'completed', assignedTo: 'v3' },
{ id: 'ms_009_3', name: 'Floor 1 Installation', dueDate: '2026-02-07', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_009_4', name: 'Floor 2 Installation', dueDate: '2026-02-14', status: 'in_progress', assignedTo: 'con_001' },
{ id: 'ms_009_5', name: 'Exterior Trim and Sealant', dueDate: '2026-02-25', status: 'pending', assignedTo: 'con_001' },
{ id: 'ms_009_6', name: 'Energy Audit Verification', dueDate: '2026-03-05', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_009_1', amount: 14000, submittedBy: 'v3', status: 'paid', dueDate: '2026-02-01', datePaid: '2026-02-03' },
{ id: 'inv_009_2', amount: 8200, submittedBy: 'con_001', status: 'paid', dueDate: '2026-02-10', datePaid: '2026-02-11' },
{ id: 'inv_009_3', amount: 9800, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-25' }
],
documents: [
{ name: 'Window Replacement Agreement', url: '#', type: 'contract' },
{ name: 'Custom Window Order Confirmation', url: '#', type: 'purchase_order' },
{ name: 'Energy Rating Certificates', url: '#', type: 'certificate' }
]
},
// Project 10: Completed, zero variance
{
id: 'proj_010',
ownerId: 'own_002',
propertyId: 'P-2656',
address: '2100 Legacy Dr, Plano, TX 75023',
contractorId: 'con_001',
subcontractorIds: [],
projectType: 'Parking Lot Resurface',
status: 'completed',
budget: 35000,
spent: 35000,
margin: 0.30,
startDate: '2025-09-15',
endDate: '2025-10-28',
completionPercentage: 100,
phase: 'Handover',
approvedBudget: 35000,
committedCost: 35000,
actualCost: 35000,
variancePercent: 0.0,
healthScore: 100,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 0,
milestones: [
{ id: 'ms_010_1', name: 'Surface Milling', dueDate: '2025-09-20', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_010_2', name: 'Base Repair', dueDate: '2025-09-28', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_010_3', name: 'Asphalt Paving', dueDate: '2025-10-08', status: 'completed', assignedTo: 'v1' },
{ id: 'ms_010_4', name: 'Sealcoat Application', dueDate: '2025-10-18', status: 'completed', assignedTo: 'v1' },
{ id: 'ms_010_5', name: 'Striping and Signage', dueDate: '2025-10-25', status: 'completed', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_010_1', amount: 8400, submittedBy: 'v3', status: 'paid', dueDate: '2025-09-25', datePaid: '2025-09-26' },
{ id: 'inv_010_2', amount: 14200, submittedBy: 'v1', status: 'paid', dueDate: '2025-10-12', datePaid: '2025-10-13' },
{ id: 'inv_010_3', amount: 12400, submittedBy: 'con_001', status: 'paid', dueDate: '2025-10-28', datePaid: '2025-10-28' }
],
documents: [
{ name: 'Paving Contract', url: '#', type: 'contract' },
{ name: 'Completion Certificate', url: '#', type: 'certificate' },
{ name: 'ADA Compliance Verification', url: '#', type: 'report' },
{ name: 'Final Payment Release', url: '#', type: 'invoice' }
]
},
// Project 11: Disputed with open change orders and unresolved issues
{
id: 'proj_011',
ownerId: 'own_002',
propertyId: 'P-2645',
address: 'Legacy Town Center, 5760 Daniel Rd, Plano, TX 75024',
contractorId: 'con_001',
subcontractorIds: ['sub_001'],
projectType: 'Exterior Facade Restoration',
status: 'disputed',
budget: 95000,
spent: 68400,
margin: 0.20,
startDate: '2025-12-08',
endDate: '2026-03-20',
completionPercentage: 62,
phase: 'MEP',
approvedBudget: 95000,
committedCost: 88000,
actualCost: 68400,
variancePercent: -28.0,
healthScore: 30,
openRFIs: 2,
changeOrderCount: 3,
pendingInvoiceCount: 2,
milestones: [
{ id: 'ms_011_1', name: 'Scaffolding and Protection', dueDate: '2025-12-12', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_011_2', name: 'Surface Cleaning and Prep', dueDate: '2025-12-22', status: 'completed', assignedTo: 'con_001' },
{ id: 'ms_011_3', name: 'Masonry Repair - Phase 1', dueDate: '2026-01-10', status: 'completed', assignedTo: 'v1' },
{ id: 'ms_011_4', name: 'Masonry Repair - Phase 2', dueDate: '2026-01-28', status: 'completed', assignedTo: 'v1' },
{ id: 'ms_011_5', name: 'Waterproofing Application', dueDate: '2026-02-12', status: 'in_progress', assignedTo: 'con_001' },
{ id: 'ms_011_6', name: 'Window Sealant Replacement', dueDate: '2026-02-28', status: 'pending', assignedTo: 'v4' },
{ id: 'ms_011_7', name: 'Final Restoration and Paint', dueDate: '2026-03-15', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_011_1', amount: 22000, submittedBy: 'con_001', status: 'paid', dueDate: '2025-12-18', datePaid: '2025-12-20' },
{ id: 'inv_011_2', amount: 18400, submittedBy: 'v1', status: 'paid', dueDate: '2026-01-15', datePaid: '2026-01-18' },
{ id: 'inv_011_3', amount: 15200, submittedBy: 'v3', status: 'paid', dueDate: '2026-01-30', datePaid: '2026-02-02' },
{ id: 'inv_011_4', amount: 12800, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-20' },
{ id: 'inv_011_5', amount: 8900, submittedBy: 'v4', status: 'pending', dueDate: '2026-03-05' }
],
documents: [
{ name: 'Facade Restoration Master Contract', url: '#', type: 'contract' },
{ name: 'Building Permit #25-2101', url: '#', type: 'permit' },
{ name: 'Change Order #1 - Hidden Water Damage', url: '#', type: 'change_order' },
{ name: 'Change Order #2 - Additional Masonry', url: '#', type: 'change_order' },
{ name: 'Change Order #3 - Structural Reinforcement', url: '#', type: 'change_order' },
{ name: 'Dispute Filing - Scope Disagreement', url: '#', type: 'dispute' },
{ name: 'RFI #1 - Original vs Current Scope', url: '#', type: 'rfi' },
{ name: 'RFI #2 - Waterproofing Method', url: '#', type: 'rfi' }
]
},
// Project 12: On Hold
{
id: 'proj_012',
ownerId: 'own_002',
propertyId: 'P-2644',
address: 'Dallas/Plano Marriott at Legacy Town Center, 7121 Bishop Rd, Plano, TX 75024',
contractorId: 'con_001',
subcontractorIds: [],
projectType: 'Plumbing Overhaul',
status: 'on_hold',
budget: 58000,
spent: 22600,
margin: 0.32,
startDate: '2026-01-13',
endDate: '2026-04-01',
completionPercentage: 28,
phase: 'Foundation',
approvedBudget: 58000,
committedCost: 34000,
actualCost: 22600,
variancePercent: -61.0,
healthScore: 45,
openRFIs: 0,
changeOrderCount: 0,
pendingInvoiceCount: 2,
milestones: [
{ id: 'ms_012_1', name: 'Plumbing Assessment', dueDate: '2026-01-17', status: 'completed', assignedTo: 'v4' },
{ id: 'ms_012_2', name: 'Material Procurement', dueDate: '2026-01-25', status: 'completed', assignedTo: 'v4' },
{ id: 'ms_012_3', name: 'Main Line Replacement', dueDate: '2026-02-05', status: 'completed', assignedTo: 'v4' },
{ id: 'ms_012_4', name: 'Water Heater Installation', dueDate: '2026-02-18', status: 'pending', assignedTo: 'v4' },
{ id: 'ms_012_5', name: 'Branch Line Reroute', dueDate: '2026-03-05', status: 'pending', assignedTo: 'v4' },
{ id: 'ms_012_6', name: 'Pressure Testing', dueDate: '2026-03-20', status: 'pending', assignedTo: 'v4' },
{ id: 'ms_012_7', name: 'City Inspection', dueDate: '2026-03-28', status: 'pending', assignedTo: 'con_001' }
],
invoices: [
{ id: 'inv_012_1', amount: 8600, submittedBy: 'v4', status: 'paid', dueDate: '2026-01-22', datePaid: '2026-01-24' },
{ id: 'inv_012_2', amount: 13972.91, submittedBy: 'v4', status: 'pending', dueDate: '2026-02-14' },
{ id: 'inv_012_3', amount: 12000, submittedBy: 'con_001', status: 'pending', dueDate: '2026-02-28' }
],
documents: [
{ name: 'Plumbing Overhaul Contract', url: '#', type: 'contract' },
{ name: 'Plumbing Permit #26-0156', url: '#', type: 'permit' },
{ name: 'Scope Hold Notice - Permit Review', url: '#', type: 'notice' },
{ name: 'Material Delivery Receipt', url: '#', type: 'receipt' }
]
}
];
// --- CONTEXT SETUP ---
const MockStoreContext = createContext();
export const MockStoreProvider = ({ children }) => {
const [properties, setProperties] = useState([]);
const [users, setUsers] = useState(MOCK_USERS);
const [meetings, setMeetings] = useState(MOCK_MEETINGS);
const [salesHistory, setSalesHistory] = useState(MOCK_SALES_HISTORY);
// New Data States
const [owners, setOwners] = useState(MOCK_OWNERS);
const [personnel, setPersonnel] = useState(MOCK_PERSONNEL);
const [vendors, setVendors] = useState(MOCK_VENDORS);
const [documents, setDocuments] = useState(MOCK_DOCUMENTS);
const [projects, setProjects] = useState(MOCK_PROJECTS);
const [orders, setOrders] = useState(MOCK_ORDERS);
const [vendorInvoices, setVendorInvoices] = useState(MOCK_VENDOR_INVOICES);
// Initialize properties once
useEffect(() => {
const data = generateProperties();
setProperties(data);
}, []);
const updatePropertyStatus = (id, newStatus) => {
setProperties(prev => prev.map(p =>
p.id === id ? { ...p, canvassingStatus: newStatus } : p
));
};
const addMeeting = (meeting) => {
setMeetings(prev => [...prev, { ...meeting, id: `m${prev.length + 1}` }]);
};
// --- NEW ACTIONS for ADMIN CENTER ---
const assignAgent = (propertyId, agentId) => {
let found = false;
setProperties(prev => prev.map(p => {
if (p.id === propertyId || p.propertyData.propertyId === propertyId) {
found = true;
return { ...p, assignedAgentId: agentId, canvassingStatus: "Assigned" };
}
return p;
}));
if (!found) {
toast.error("Failed to assign agent: Property not found.");
return false;
}
const agent = users.find(u => u.id === agentId);
toast.success(`Agent ${agent ? agent.name : 'assigned'} linked to property.`);
logger.info(`Property ${propertyId} assigned to Agent ${agentId}`);
return true;
};
const markLeadContacted = (propertyId) => {
let found = false;
setProperties(prev => prev.map(p => {
if (p.id === propertyId || p.propertyData.propertyId === propertyId) {
found = true;
return { ...p, lastContactDate: new Date().toISOString() };
}
return p;
}));
if (!found) {
toast.error("Action failed: Property not found.");
return false;
}
toast.success("Lead marked as contacted.");
return true;
};
const sendReminder = (propertyId) => {
const prop = properties.find(p => p.id === propertyId || p.propertyData.propertyId === propertyId);
if (!prop) {
toast.error("Failed to send reminder: Client not found.");
return false;
}
const name = prop?.ownerData?.fullName || "Client";
toast.success(`Reminder sent to ${name}`);
logger.info(`Reminder sent to property ${propertyId}`);
return true;
};
return (
<MockStoreContext.Provider value={{
properties,
users,
meetings,
salesHistory, // Exported for Leaderboard
// New Owners Box Data
owners,
personnel,
vendors,
documents,
projects,
orders,
vendorInvoices,
updatePropertyStatus,
addMeeting,
updateUser: (updatedUser) => {
setUsers(prev => prev.map(u => u.id === updatedUser.id ? updatedUser : u));
},
// Export new actions
assignAgent,
markLeadContacted,
sendReminder
}}>
{children}
</MockStoreContext.Provider>
);
};
export const useMockStore = () => useContext(MockStoreContext);
// ---------------------------------------------------------------------------
// Lead Creation Form Options
// ---------------------------------------------------------------------------
export const LEAD_FORM_OPTIONS = {
leadTypes: [
'Residential',
'Commercial',
'Multi-Family',
'Industrial',
'HOA / Community',
],
leadSources: [
'Door Knock',
'Referral',
'Storm Chase',
'Online / Web',
'Mailer / Postcard',
'Sign Call',
'Insurance Agent Referral',
'Repeat Customer',
'Social Media',
'Other',
],
workTypes: [
'Roof Replacement',
'Roof Repair',
'Gutters',
'Siding',
'Windows',
'Solar',
'Inspection Only',
'Emergency Tarping',
'Other',
],
tradeTypes: [
'Roofing',
'Gutter',
'Siding',
'Windows',
'Solar',
'General Contractor',
],
urgencyLevels: [
{ label: 'Standard', value: 'standard', color: '#6B7280' },
{ label: 'High', value: 'high', color: '#F59E0B' },
{ label: 'Emergency', value: 'emergency', color: '#EF4444' },
],
priorityLevels: [
{ label: 'Low', value: 'low', color: '#6B7280' },
{ label: 'Medium', value: 'medium', color: '#3B82F6' },
{ label: 'High', value: 'high', color: '#F59E0B' },
{ label: 'Critical', value: 'critical', color: '#EF4444' },
],
insuranceCompanies: [
'State Farm',
'Allstate',
'USAA',
'Farmers Insurance',
'Liberty Mutual',
'Progressive',
'Nationwide',
'American Family',
'Travelers',
'GEICO',
'Chubb',
'Erie Insurance',
'Auto-Owners',
'Other',
],
claimStatuses: [
'Not Filed',
'Filed Pending Adjuster',
'Adjuster Scheduled',
'Adjuster Completed',
'Approved',
'Denied',
'Supplement In Progress',
'Closed',
],
phoneTypes: ['Mobile', 'Home', 'Work', 'Other'],
emailTypes: ['Personal', 'Work', 'Other'],
usStates: [
'AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA',
'HI','ID','IL','IN','IA','KS','KY','LA','ME','MD',
'MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ',
'NM','NY','NC','ND','OH','OK','OR','PA','RI','SC',
'SD','TN','TX','UT','VT','VA','WA','WV','WI','WY',
],
};