diff --git a/src/data/mockStore.jsx b/src/data/mockStore.jsx index db0ef24..e2ec6fa 100644 --- a/src/data/mockStore.jsx +++ b/src/data/mockStore.jsx @@ -4644,43 +4644,43 @@ const MOCK_PROJECTS = [ export const DISPATCH_REPS = [ { - id: 'REP-01', name: 'Carlos Mendez', initials: 'CM', + id: 'REP-01', personId: 'e1', name: 'Cody Tatum', initials: 'CT', status: 'en_route', // available | en_route | busy currentLat: 33.0612, currentLng: -96.7891, todayAppointments: 3, maxDaily: 6, - skills: ['insurance_claim', 'retail_estimate'], + skills: ['sk_emergency_tarp', 'sk_insurance_claim', 'sk_drone_survey'], performanceScore: 94, rating: 4.8, closeRate: 82, }, { - id: 'REP-02', name: 'Aisha Kumar', initials: 'AK', + id: 'REP-02', personId: 'e2', name: 'Hannah Reyes', initials: 'HR', status: 'available', currentLat: 33.0812, currentLng: -96.7234, todayAppointments: 2, maxDaily: 6, - skills: ['roof_inspection', 'emergency_tarp'], + skills: ['sk_customer_comms', 'sk_retail_estimate', 'sk_roof_inspection'], performanceScore: 88, rating: 4.9, closeRate: 76, }, { - id: 'REP-03', name: 'Tom Bradley', initials: 'TB', + id: 'REP-03', personId: 'e3', name: 'Travis Boone', initials: 'TB', status: 'busy', currentLat: 33.0389, currentLng: -96.7401, todayAppointments: 5, maxDaily: 6, - skills: ['retail_estimate', 'roof_inspection'], + skills: ['sk_customer_comms', 'sk_retail_estimate', 'sk_roof_inspection'], performanceScore: 79, rating: 4.5, closeRate: 68, }, { - id: 'REP-04', name: 'Nina Patel', initials: 'NP', + id: 'REP-04', personId: 'e4', name: 'Shelby Greer', initials: 'SG', status: 'available', currentLat: 33.0516, currentLng: -96.7512, todayAppointments: 1, maxDaily: 6, - skills: ['insurance_claim', 'roof_inspection', 'emergency_tarp'], + skills: ['sk_roof_inspection', 'sk_insurance_claim', 'sk_emergency_tarp'], performanceScore: 91, rating: 4.7, closeRate: 79, }, { - id: 'REP-05', name: 'Derek Walsh', initials: 'DW', + id: 'REP-05', personId: 'e5', name: 'Dalton Pruitt', initials: 'DP', status: 'en_route', currentLat: 33.0198, currentLng: -96.7234, todayAppointments: 4, maxDaily: 6, - skills: ['retail_estimate', 'roof_inspection'], + skills: ['sk_customer_comms', 'sk_retail_estimate', 'sk_roof_inspection'], performanceScore: 82, rating: 4.6, closeRate: 74, }, ]; @@ -4706,7 +4706,7 @@ const DISPATCH_LEADS_INITIAL = [ id: 'LD-1003', source: 'canvassing', leadType: 'insurance_claim', urgency: 'high', customer: { name: 'Robert Chen', phone: '(972) 555-1003', email: 'robert.chen@outlook.com' }, property: { address: '1234 Oak Creek Blvd', city: 'Plano', state: 'TX', zip: '75075', lat: 33.0421, lng: -96.7138 }, - canvassedBy: { agentId: 'U-05', name: 'Marcus Webb' }, + canvassedBy: { agentId: 'e1', name: 'Cody Tatum' }, notes: 'Filed insurance claim after hail event 3/18. Adjuster visit scheduled 3/28 — needs estimate in hand beforehand. Cooperative and responsive.', estimatedDuration: 45, status: 'assigned', arrivedMinsAgo: 22, assignedRepId: 'REP-01', }, @@ -4738,7 +4738,7 @@ const DISPATCH_LEADS_INITIAL = [ id: 'LD-1007', source: 'canvassing', leadType: 'retail_estimate', urgency: 'standard', customer: { name: 'David Park', phone: '(972) 555-1007', email: 'dpark.plano@gmail.com' }, property: { address: '2200 Alma Dr', city: 'Plano', state: 'TX', zip: '75075', lat: 33.0516, lng: -96.7289 }, - canvassedBy: { agentId: 'U-07', name: 'Priya Nair' }, + canvassedBy: { agentId: 'e2', name: 'Hannah Reyes' }, notes: 'Customer confirmed appointment. Wants two options: repair patch vs full replacement. Existing roof is 19 years old.', estimatedDuration: 30, status: 'confirmed', arrivedMinsAgo: 62, assignedRepId: 'REP-04', }, @@ -4770,7 +4770,7 @@ const DISPATCH_LEADS_INITIAL = [ id: 'LD-1011', source: 'canvassing', leadType: 'insurance_claim', urgency: 'high', customer: { name: 'Michael Anderson', phone: '(972) 555-1011', email: 'michael.a@outlook.com' }, property: { address: '1800 Jupiter Rd', city: 'Plano', state: 'TX', zip: '75074', lat: 33.0267, lng: -96.7102 }, - canvassedBy: { agentId: 'U-05', name: 'Marcus Webb' }, + canvassedBy: { agentId: 'e1', name: 'Cody Tatum' }, notes: 'Multiple hail impacts on canvass route. Customer receptive, confirmed hail event on property. Adjuster not yet contacted — walk them through the process.', estimatedDuration: 60, status: 'unassigned', arrivedMinsAgo: 11, assignedRepId: null, }, @@ -4842,284 +4842,310 @@ export const MOCK_HAIL_HISTORY = { export const DISPATCH_RECOMMENDATIONS = { 'LD-1001': [ { + // LD-1001 leadType: emergency_tarp — REP-04 = Shelby Greer (e4), sk_emergency_tarp: 78 repId: 'REP-04', score: 91, slotStart: '1:30 PM', slotEnd: '2:30 PM', distanceMi: '2.1', - factors: { proximity: 88, driveTime: 90, calendarFit: 95, weather: 90, skillMatch: 100 }, - reasons: ['Closest eligible rep — 2.1 mi', '12 min drive time estimated', 'Insurance claim certified', 'Buffer preserved before next appointment'], - stormReasons: ['Lightning risk before 2 PM — slot pushed to 1:30 PM', 'Rep carries emergency tarp kit'], - aiInsight: 'Calendar and proximity align perfectly — earliest safe window before afternoon storm risk', + factors: { proximity: 88, driveTime: 90, calendarFit: 95, weather: 90, skillMatch: 78 }, + reasons: ['Closest eligible rep — 2.1 mi', '12 min drive time estimated', 'Emergency Tarp 78/100 — storm-ready', 'Carries drone + tarp kit + moisture meter', 'Buffer preserved before next appointment'], + stormReasons: ['Lightning risk before 2 PM — slot pushed to 1:30 PM', 'Shelby carries a tarp kit and moisture meter for post-tarp verification'], + aiInsight: 'Shelby scores 78 on Emergency Tarp and carries a tarp kit and moisture meter — calendar and proximity align perfectly for the earliest safe window before afternoon storm risk.', conflictFlag: null, routePath: [[33.0516, -96.7512], [33.0612, -96.7484], [33.0708, -96.7456]], }, { + // REP-02 = Hannah Reyes (e2), sk_emergency_tarp: 55 repId: 'REP-02', score: 79, slotStart: '3:00 PM', slotEnd: '4:00 PM', distanceMi: '3.8', - factors: { proximity: 72, driveTime: 75, calendarFit: 82, weather: 80, skillMatch: 85 }, - reasons: ['Available at 3 PM', '18 min drive — moderate traffic', 'Roof inspection certified'], + factors: { proximity: 72, driveTime: 75, calendarFit: 82, weather: 80, skillMatch: 55 }, + reasons: ['Available at 3 PM', '18 min drive — moderate traffic', 'Emergency Tarp 55/100 — baseline capable', 'Carries ladder rack for access'], stormReasons: ['Afternoon slot carries weather risk — monitor closely'], - aiInsight: 'Solid backup with roof certification — afternoon slot viable but weather requires monitoring', + aiInsight: 'Hannah scores 55 on Emergency Tarp — solid backup if Shelby is occupied, but afternoon slot requires weather monitoring.', conflictFlag: 'Post-3 PM weather risk — confirm conditions before dispatch', routePath: [[33.0812, -96.7234], [33.0760, -96.7345], [33.0708, -96.7456]], }, { + // REP-01 = Cody Tatum (e1), sk_emergency_tarp: 92 repId: 'REP-01', score: 71, slotStart: '4:30 PM', slotEnd: '5:30 PM', distanceMi: '5.2', - factors: { proximity: 62, driveTime: 60, calendarFit: 78, weather: 70, skillMatch: 100 }, - reasons: ['Available later in the day', '24 min drive from current location', 'High performer — score 94'], + factors: { proximity: 62, driveTime: 60, calendarFit: 78, weather: 70, skillMatch: 92 }, + reasons: ['Available later in the day', '24 min drive from current location', 'Emergency Tarp 92/100 — highest score on team', 'Carries tarp kit + drone for aerial damage assessment'], stormReasons: ['Late afternoon — weather conditions improving'], - aiInsight: 'High performer but distance and late slot reduce overall optimality for this job type', + aiInsight: 'Cody scores 92 on Emergency Tarp and carries a tarp kit — highest skill match, but the 5.2 mi drive and late slot make him the third-best option for this time-sensitive job.', conflictFlag: '20 min buffer only after completion — schedule at risk if job runs long', routePath: [[33.0612, -96.7891], [33.0660, -96.7674], [33.0708, -96.7456]], }, ], 'LD-1002': [ { + // LD-1002 leadType: roof_inspection — REP-01 = Cody Tatum (e1), sk_roof_inspection: 81 repId: 'REP-01', score: 88, slotStart: '2:00 PM', slotEnd: '2:45 PM', distanceMi: '1.4', - factors: { proximity: 92, driveTime: 88, calendarFit: 85, weather: 88, skillMatch: 100 }, - reasons: ['Closest rep — 1.4 mi from lead location', '8 min drive time', 'Buffer maintained after current job'], - stormReasons: ['Weather clear until 3 PM — slot timing is safe', 'Rep familiar with West Plano territory'], - aiInsight: 'Nearest eligible rep with strong calendar fit — weather window closes cleanly after completion', + factors: { proximity: 92, driveTime: 88, calendarFit: 85, weather: 88, skillMatch: 81 }, + reasons: ['Closest rep — 1.4 mi from lead location', '8 min drive time', 'Roof Inspection 81/100 — carrier-ready documentation', 'Carries drone for aerial scan on steep slopes', 'Buffer maintained after current job'], + stormReasons: ['Weather clear until 3 PM — slot timing is safe', 'Cody runs a DJI drone on every steep-slope job'], + aiInsight: 'Cody scores 81 on Roof Inspection and flies a drone on every steep-slope job — nearest eligible rep with a clean weather window and strong documentation skills.', conflictFlag: null, routePath: [[33.0612, -96.7891], [33.0632, -96.7956], [33.0652, -96.8021]], }, { + // REP-04 = Shelby Greer (e4), sk_roof_inspection: 88 repId: 'REP-04', score: 74, slotStart: '3:30 PM', slotEnd: '4:15 PM', distanceMi: '4.1', - factors: { proximity: 70, driveTime: 68, calendarFit: 85, weather: 72, skillMatch: 100 }, - reasons: ['Available at 3:30 PM', '22 min drive from current position', 'Insurance claim certified'], + factors: { proximity: 70, driveTime: 68, calendarFit: 85, weather: 72, skillMatch: 88 }, + reasons: ['Available at 3:30 PM', '22 min drive from current position', 'Roof Inspection 88/100 — highest roof score on team', 'Carries drone + moisture meter for subsurface checks'], stormReasons: ['Afternoon slot — weather risk moderate after 3 PM'], - aiInsight: 'Certified fallback with open afternoon — drive time and weather reduce confidence vs. top pick', + aiInsight: 'Shelby scores 88 on Roof Inspection — team-best score — and brings a moisture meter for subsurface checks. Drive time and afternoon weather are the only detractors.', conflictFlag: 'Afternoon weather window tight — start punctually or reschedule', routePath: [[33.0516, -96.7512], [33.0584, -96.7767], [33.0652, -96.8021]], }, ], 'LD-1003': [ { + // LD-1003 leadType: insurance_claim — REP-01 = Cody Tatum (e1), sk_insurance_claim: 88 repId: 'REP-01', score: 87, slotStart: '11:00 AM', slotEnd: '11:45 AM', distanceMi: '2.8', - factors: { proximity: 85, driveTime: 88, calendarFit: 90, weather: 85, skillMatch: 100 }, - reasons: ['Currently assigned — optimal for continuity', '11 min drive from current stop', 'Insurance claim specialist'], + factors: { proximity: 85, driveTime: 88, calendarFit: 90, weather: 85, skillMatch: 88 }, + reasons: ['Currently assigned — optimal for continuity', '11 min drive from current stop', 'Insurance Claim 88/100 — carrier-certified supplement writer', 'Carries drone for aerial hail documentation'], stormReasons: ['Morning slot — no weather concerns'], - aiInsight: 'Continuity assignment maximizes close probability — same rep builds on prior customer rapport', + aiInsight: 'Cody scores 88 on Insurance Claim and flies a drone for every hail job — continuity assignment maximizes close probability with prior customer rapport already established.', conflictFlag: null, routePath: [[33.0612, -96.7891], [33.0517, -96.7515], [33.0421, -96.7138]], }, { + // REP-05 = Dalton Pruitt (e5), sk_insurance_claim: 60 repId: 'REP-05', score: 67, slotStart: '1:00 PM', slotEnd: '1:45 PM', distanceMi: '4.4', factors: { proximity: 65, driveTime: 62, calendarFit: 72, weather: 75, skillMatch: 60 }, - reasons: ['Available afternoon slot', '19 min drive', 'Less specialized — retail estimate primary skill'], + reasons: ['Available afternoon slot', '19 min drive', 'Insurance Claim 60/100 — functional but developing', 'Retail estimate is Dalton\'s primary skill (87/100)'], stormReasons: ['Afternoon — monitor weather after 1 PM'], - aiInsight: 'Capable fallback but skill mismatch lowers confidence for insurance claim type', - conflictFlag: 'Skill mismatch — retail primary, insurance secondary skill only', + aiInsight: 'Dalton scores 60 on Insurance Claim versus Cody\'s 88 — capable fallback but the skill gap lowers confidence for this adjuster-prep appointment.', + conflictFlag: 'Skill gap — Dalton\'s Insurance Claim score (60) is 28 points below primary rep', routePath: [[33.0198, -96.7234], [33.0310, -96.7186], [33.0421, -96.7138]], }, ], 'LD-1004': [ { + // LD-1004 leadType: retail_estimate — REP-03 = Travis Boone (e3), sk_retail_estimate: 50 repId: 'REP-03', score: 95, slotStart: '10:30 AM', slotEnd: '11:00 AM', distanceMi: '0.6', - factors: { proximity: 98, driveTime: 97, calendarFit: 88, weather: 95, skillMatch: 100 }, - reasons: ['0.6 mi away — optimal proximity', '4 min drive time', 'Retail estimate specialist'], + factors: { proximity: 98, driveTime: 97, calendarFit: 88, weather: 95, skillMatch: 50 }, + reasons: ['0.6 mi away — optimal proximity', '4 min drive time', 'Retail Estimate 50/100 — developing skill', 'Customer Comms 67/100 — good rapport builder for new clients'], stormReasons: ['Morning slot — conditions favorable'], - aiInsight: 'Near-perfect assignment — virtually on-site with ideal skill set and favorable morning conditions', - conflictFlag: null, + aiInsight: 'Travis scores 50 on Retail Estimate — still building this skill — but his proximity (0.6 mi, 4 min) and open morning calendar make him the best available option. Coach him post-appointment.', + conflictFlag: 'Skill score moderate — pair with follow-up review for estimate accuracy', routePath: [[33.0389, -96.7401], [33.0389, -96.7368], [33.0389, -96.7334]], }, { + // REP-05 = Dalton Pruitt (e5), sk_retail_estimate: 87 repId: 'REP-05', score: 73, slotStart: '2:00 PM', slotEnd: '2:30 PM', distanceMi: '3.3', - factors: { proximity: 70, driveTime: 68, calendarFit: 80, weather: 72, skillMatch: 80 }, - reasons: ['Available afternoon', '16 min drive', 'Retail estimate capable'], + factors: { proximity: 70, driveTime: 68, calendarFit: 80, weather: 72, skillMatch: 87 }, + reasons: ['Available afternoon', '16 min drive', 'Retail Estimate 87/100 — strong closer on cash jobs', 'Customer Comms 88/100 — high rapport score'], stormReasons: ['Afternoon slot — watch post-2 PM weather'], - aiInsight: 'Retail-capable with open afternoon — viable if top pick becomes unavailable', + aiInsight: 'Dalton scores 87 on Retail Estimate — far stronger skill fit than Travis — but the 3.3 mi drive and afternoon timing drop his overall score. Upgrade to him if Travis\'s morning slot falls through.', conflictFlag: null, routePath: [[33.0198, -96.7234], [33.0294, -96.7284], [33.0389, -96.7334]], }, ], 'LD-1005': [ { + // LD-1005 leadType: roof_inspection — REP-02 = Hannah Reyes (e2), sk_roof_inspection: 70 repId: 'REP-02', score: 94, slotStart: '12:00 PM', slotEnd: '12:45 PM', distanceMi: '0.3', - factors: { proximity: 97, driveTime: 96, calendarFit: 90, weather: 92, skillMatch: 95 }, - reasons: ['0.3 mi from lead — effectively on-site', '3 min drive time', 'Roof inspection specialist', 'Low daily load — 2 of 6 slots used'], - stormReasons: ['Midday window — weather acceptable', 'Rep carries safety equipment'], - aiInsight: 'Exceptional proximity with light workload — highest-confidence dispatch of the day', + factors: { proximity: 97, driveTime: 96, calendarFit: 90, weather: 92, skillMatch: 70 }, + reasons: ['0.3 mi from lead — effectively on-site', '3 min drive time', 'Roof Inspection 70/100 — competent on standard inspections', 'Carries pitch gauge + measuring wheel for accurate slope docs', 'Low daily load — 2 of 6 slots used'], + stormReasons: ['Midday window — weather acceptable', 'Hannah carries pitch gauge for slope documentation'], + aiInsight: 'Hannah scores 70 on Roof Inspection and carries a pitch gauge and measuring wheel — exceptional proximity with a light workload makes this the highest-confidence dispatch of the day.', conflictFlag: null, routePath: [[33.0812, -96.7234], [33.0812, -96.7378], [33.0812, -96.7521]], }, { + // REP-04 = Shelby Greer (e4), sk_roof_inspection: 88 repId: 'REP-04', score: 77, slotStart: '2:30 PM', slotEnd: '3:15 PM', distanceMi: '3.6', - factors: { proximity: 72, driveTime: 70, calendarFit: 88, weather: 78, skillMatch: 90 }, - reasons: ['Available at 2:30 PM', '17 min drive', 'Roof inspection certified'], + factors: { proximity: 72, driveTime: 70, calendarFit: 88, weather: 78, skillMatch: 88 }, + reasons: ['Available at 2:30 PM', '17 min drive', 'Roof Inspection 88/100 — team-best score', 'Carries drone + moisture meter for thorough assessment'], stormReasons: ['Afternoon — post-3 PM weather worsening, start punctually'], - aiInsight: 'Certified backup with clean afternoon window — must start on time before weather closes in', + aiInsight: 'Shelby scores 88 on Roof Inspection — best on the team — and brings a moisture meter. The drive time and weather window are the only reasons she trails Hannah here.', conflictFlag: 'Start before 3 PM — weather deteriorates sharply after', routePath: [[33.0516, -96.7512], [33.0664, -96.7517], [33.0812, -96.7521]], }, ], 'LD-1006': [ { + // LD-1006 leadType: insurance_claim — REP-01 = Cody Tatum (e1), sk_insurance_claim: 88 repId: 'REP-01', score: 83, slotStart: '3:00 PM', slotEnd: '4:00 PM', distanceMi: '3.1', - factors: { proximity: 80, driveTime: 78, calendarFit: 85, weather: 82, skillMatch: 100 }, - reasons: ['Best available slot — 3 PM', '14 min drive from current route', 'Insurance claim specialist'], - stormReasons: ['Wind advisory active — exterior inspection may need delay', 'Insurance claim can proceed indoors'], - aiInsight: 'Best certified specialist available — indoor claim process can proceed despite active wind advisory', + factors: { proximity: 80, driveTime: 78, calendarFit: 85, weather: 82, skillMatch: 88 }, + reasons: ['Best available slot — 3 PM', '14 min drive from current route', 'Insurance Claim 88/100 — supplement-certified', 'Carries drone for aerial ridge-cap documentation'], + stormReasons: ['Wind advisory active — exterior inspection may need delay', 'Cody can advance the claim indoors then fly drone when winds subside'], + aiInsight: 'Cody scores 88 on Insurance Claim and carries a drone for aerial ridge-cap documentation — best certified specialist available; indoor claim work can proceed despite the active wind advisory.', conflictFlag: 'Wind advisory active — verify exterior conditions before starting roof portion', routePath: [[33.0612, -96.7891], [33.0773, -96.7947], [33.0934, -96.8002]], }, { + // REP-02 = Hannah Reyes (e2), sk_insurance_claim: 65 repId: 'REP-02', score: 69, slotStart: '4:30 PM', slotEnd: '5:30 PM', distanceMi: '5.8', - factors: { proximity: 65, driveTime: 62, calendarFit: 75, weather: 68, skillMatch: 85 }, - reasons: ['Late afternoon availability', '26 min drive', 'Roof inspection skilled'], + factors: { proximity: 65, driveTime: 62, calendarFit: 75, weather: 68, skillMatch: 65 }, + reasons: ['Late afternoon availability', '26 min drive', 'Insurance Claim 65/100 — capable but secondary skill', 'Customer Comms 91/100 — strong at keeping clients calm during complex claims'], stormReasons: ['Late afternoon — conditions deteriorating, not recommended'], - aiInsight: 'Low-confidence option — weather and distance combine unfavorably for late afternoon exterior work', + aiInsight: 'Hannah scores 65 on Insurance Claim (23 points below Cody) and the 4:30 PM slot lands in deteriorating conditions — low-confidence option, use only if Cody is unavailable.', conflictFlag: 'Not recommended — conditions deteriorating by 4:30 PM, daylight limited', routePath: [[33.0812, -96.7234], [33.0873, -96.7618], [33.0934, -96.8002]], }, ], 'LD-1007': [ { + // LD-1007 leadType: retail_estimate — REP-04 = Shelby Greer (e4), sk_retail_estimate: 72 repId: 'REP-04', score: 87, slotStart: '11:30 AM', slotEnd: '12:00 PM', distanceMi: '1.5', - factors: { proximity: 90, driveTime: 88, calendarFit: 92, weather: 90, skillMatch: 80 }, - reasons: ['1.5 mi away — close proximity', '9 min drive time', 'Low daily load', 'Buffer before afternoon appointments'], + factors: { proximity: 90, driveTime: 88, calendarFit: 92, weather: 90, skillMatch: 72 }, + reasons: ['1.5 mi away — close proximity', '9 min drive time', 'Retail Estimate 72/100 — solid on reroof presentations', 'Low daily load', 'Buffer before afternoon appointments'], stormReasons: ['Morning window — safe conditions'], - aiInsight: 'Light daily load with close proximity — midday window maximizes buffer for afternoon pipeline', + aiInsight: 'Shelby scores 72 on Retail Estimate and has light calendar load — close proximity and a clean morning window make this an efficient midday dispatch.', conflictFlag: null, routePath: [[33.0516, -96.7512], [33.0516, -96.7401], [33.0516, -96.7289]], }, { + // REP-03 = Travis Boone (e3), sk_retail_estimate: 50 repId: 'REP-03', score: 78, slotStart: '1:30 PM', slotEnd: '2:00 PM', distanceMi: '2.9', - factors: { proximity: 78, driveTime: 75, calendarFit: 70, weather: 82, skillMatch: 100 }, - reasons: ['Retail estimate specialist', '12 min drive', 'Near current work site'], + factors: { proximity: 78, driveTime: 75, calendarFit: 70, weather: 82, skillMatch: 50 }, + reasons: ['Near current work site — 2.9 mi', '12 min drive', 'Retail Estimate 50/100 — developing skill', 'Customer Comms 67/100 — personable with new homeowners'], stormReasons: ['Early afternoon — conditions acceptable'], - aiInsight: 'Specialist-level skill match but heavier daily load reduces calendar fit score', + aiInsight: 'Travis scores 50 on Retail Estimate — still building this skill set — and his calendar is already heavy at 5 appointments. Backup only; upgrade to Dalton (87/100) if Shelby is pulled.', conflictFlag: '5 appointments today — buffer is tight if any job runs over', routePath: [[33.0389, -96.7401], [33.0453, -96.7345], [33.0516, -96.7289]], }, ], 'LD-1008': [ { + // LD-1008 leadType: roof_inspection — REP-04 = Shelby Greer (e4), sk_roof_inspection: 88 repId: 'REP-04', score: 86, slotStart: '2:00 PM', slotEnd: '2:45 PM', distanceMi: '2.7', - factors: { proximity: 84, driveTime: 85, calendarFit: 90, weather: 85, skillMatch: 95 }, - reasons: ['2.7 mi from lead — manageable drive', '15 min estimated travel', 'Roof inspection certified', 'Open afternoon slot'], + factors: { proximity: 84, driveTime: 85, calendarFit: 90, weather: 85, skillMatch: 88 }, + reasons: ['2.7 mi from lead — manageable drive', '15 min estimated travel', 'Roof Inspection 88/100 — team-best score', 'Carries drone + moisture meter for comprehensive assessment', 'Open afternoon slot'], stormReasons: ['Weather acceptable until 3:30 PM', 'Book for 2 PM to maximize safe window'], - aiInsight: 'Certified for roof inspection with open slot — 2 PM booking maximizes safe weather window', + aiInsight: 'Shelby scores 88 on Roof Inspection — highest on the team — and carries a drone and moisture meter for a thorough assessment. 2 PM booking maximizes the safe weather window.', conflictFlag: null, routePath: [[33.0516, -96.7512], [33.0630, -96.7562], [33.0744, -96.7612]], }, { + // REP-02 = Hannah Reyes (e2), sk_roof_inspection: 70 repId: 'REP-02', score: 75, slotStart: '3:30 PM', slotEnd: '4:15 PM', distanceMi: '4.1', - factors: { proximity: 72, driveTime: 70, calendarFit: 82, weather: 74, skillMatch: 90 }, - reasons: ['Available at 3:30 PM', '19 min drive', 'Roof inspection specialist'], + factors: { proximity: 72, driveTime: 70, calendarFit: 82, weather: 74, skillMatch: 70 }, + reasons: ['Available at 3:30 PM', '19 min drive', 'Roof Inspection 70/100 — competent on standard inspections', 'Carries pitch gauge for slope documentation'], stormReasons: ['Late afternoon — weather risk elevated after 3 PM'], - aiInsight: 'Roof specialist with afternoon availability — weather risk increases as slot approaches 4 PM', + aiInsight: 'Hannah scores 70 on Roof Inspection and carries a pitch gauge — solid fallback but the 4.1 mi drive and weather risk in the 3:30 PM slot lower confidence.', conflictFlag: '15 min buffer after completion — schedule may be tight if delayed', routePath: [[33.0812, -96.7234], [33.0778, -96.7423], [33.0744, -96.7612]], }, { + // REP-01 = Cody Tatum (e1), sk_roof_inspection: 81 repId: 'REP-01', score: 68, slotStart: '5:00 PM', slotEnd: '5:45 PM', distanceMi: '5.5', - factors: { proximity: 62, driveTime: 58, calendarFit: 70, weather: 68, skillMatch: 80 }, - reasons: ['End of day slot only', '22 min drive', 'High performer — score 94'], + factors: { proximity: 62, driveTime: 58, calendarFit: 70, weather: 68, skillMatch: 81 }, + reasons: ['End of day slot only', '22 min drive', 'Roof Inspection 81/100 — strong documentation skills', 'Carries drone for aerial scan'], stormReasons: ['Evening — conditions improving but daylight limited'], - aiInsight: 'High performer but 5 PM slot limits daylight for roof work — use only as last resort', + aiInsight: 'Cody scores 81 on Roof Inspection and carries a drone, but the 5 PM slot limits daylight for exterior work — use only as a last resort.', conflictFlag: 'Daylight limited at 5 PM — roof inspection may be incomplete', routePath: [[33.0612, -96.7891], [33.0678, -96.7752], [33.0744, -96.7612]], }, ], 'LD-1009': [ { + // LD-1009 leadType: emergency_tarp — REP-05 = Dalton Pruitt (e5), sk_emergency_tarp: 45 repId: 'REP-05', score: 97, slotStart: '11:00 AM', slotEnd: '12:30 PM', distanceMi: '0.8', - factors: { proximity: 99, driveTime: 98, calendarFit: 95, weather: 95, skillMatch: 90 }, - reasons: ['0.8 mi away — nearest rep on site', '5 min drive time', 'Emergency certified', 'PRIORITY: emergency tarp needed'], - stormReasons: ['EMERGENCY — dispatch immediately', 'Rep stocked with emergency tarp materials'], - aiInsight: 'PRIORITY dispatch — nearest certified rep with emergency materials on hand, 5 min ETA', - conflictFlag: null, + factors: { proximity: 99, driveTime: 98, calendarFit: 95, weather: 95, skillMatch: 45 }, + reasons: ['0.8 mi away — nearest rep on site', '5 min drive time', 'Emergency Tarp 45/100 — limited experience, proximity overrides skill gap', 'Carries ladder rack for roof access', 'PRIORITY: active leak, family with newborn on premises'], + stormReasons: ['EMERGENCY — dispatch immediately', 'Dalton is physically nearest — 5 min ETA critical for active leak'], + aiInsight: 'PRIORITY dispatch — Dalton scores 45 on Emergency Tarp but his 0.8 mi proximity (5 min ETA) is critical for this active-leak emergency. Dispatch now and coordinate with Cody (92/100) or Shelby (78/100) for backup if the job escalates.', + conflictFlag: 'Skill score limited (45/100) — flag for supervisor oversight; escalate to Cody Tatum if tarp complexity exceeds Dalton\'s capability', routePath: [[33.0198, -96.7234], [33.0198, -96.7112], [33.0198, -96.6989]], }, { + // REP-03 = Travis Boone (e3), sk_emergency_tarp: 33 repId: 'REP-03', score: 71, slotStart: '1:00 PM', slotEnd: '2:30 PM', distanceMi: '4.6', - factors: { proximity: 65, driveTime: 62, calendarFit: 75, weather: 72, skillMatch: 75 }, - reasons: ['Backup option — 5 appointments today', '21 min drive', 'Roof inspection capable'], + factors: { proximity: 65, driveTime: 62, calendarFit: 75, weather: 72, skillMatch: 33 }, + reasons: ['Backup option — 5 appointments today', '21 min drive', 'Emergency Tarp 33/100 — minimal hands-on experience', 'Carries only tape measure + clipboard — no tarp materials'], stormReasons: ['Secondary option — use only if REP-05 unavailable'], - aiInsight: 'Emergency backup only — heavier daily load and longer drive make this a secondary option', - conflictFlag: '5 appointments today — minimal buffer if any prior job overruns', + aiInsight: 'Travis scores 33 on Emergency Tarp and carries no tarp materials — emergency backup only. Heavier daily load (5 appointments) and 4.6 mi drive make this a last-resort option.', + conflictFlag: '5 appointments today — minimal buffer if any prior job overruns; low tarp skill (33/100)', routePath: [[33.0389, -96.7401], [33.0294, -96.7195], [33.0198, -96.6989]], }, ], 'LD-1010': [ { + // LD-1010 leadType: retail_estimate — REP-01 = Cody Tatum (e1), sk_retail_estimate: 74 repId: 'REP-01', score: 84, slotStart: '2:30 PM', slotEnd: '3:00 PM', distanceMi: '2.9', - factors: { proximity: 82, driveTime: 80, calendarFit: 88, weather: 84, skillMatch: 80 }, - reasons: ['Best proximity match — 2.9 mi', '16 min drive', 'High performer — score 94', 'Manageable daily load'], + factors: { proximity: 82, driveTime: 80, calendarFit: 88, weather: 84, skillMatch: 74 }, + reasons: ['Best proximity match — 2.9 mi', '16 min drive', 'Retail Estimate 74/100 — solid on material-quality presentations', 'Manageable daily load'], stormReasons: ['Afternoon slot — monitor weather', 'Retail estimate can proceed partially indoors'], - aiInsight: 'Top performer with manageable load — retail estimate can proceed indoors if afternoon weather shifts', + aiInsight: 'Cody scores 74 on Retail Estimate — strong enough for an architectural shingle consultation — and has manageable load. The estimate can move indoors if afternoon weather shifts.', conflictFlag: null, routePath: [[33.0612, -96.7891], [33.0750, -96.7824], [33.0888, -96.7756]], }, { + // REP-02 = Hannah Reyes (e2), sk_retail_estimate: 89 repId: 'REP-02', score: 72, slotStart: '4:00 PM', slotEnd: '4:30 PM', distanceMi: '4.8', - factors: { proximity: 70, driveTime: 68, calendarFit: 78, weather: 70, skillMatch: 80 }, - reasons: ['Available late afternoon', '22 min drive', 'Roof inspection certified'], + factors: { proximity: 70, driveTime: 68, calendarFit: 78, weather: 70, skillMatch: 89 }, + reasons: ['Available late afternoon', '22 min drive', 'Retail Estimate 89/100 — top retail closer on team', 'Customer Comms 91/100 — excels at price-sensitive consultations'], stormReasons: ['4 PM slot — weather conditions deteriorating, not ideal'], - aiInsight: 'Viable backup but 4 PM timing and weather trend reduce confidence for exterior estimate', + aiInsight: 'Hannah scores 89 on Retail Estimate — best on the team for cash-pay closes — but the 4 PM timing and 4.8 mi drive reduce confidence. She is the better skill fit if Cody\'s slot becomes unavailable.', conflictFlag: '4 PM slot — low daylight and deteriorating conditions for exterior work', routePath: [[33.0812, -96.7234], [33.0850, -96.7495], [33.0888, -96.7756]], }, ], 'LD-1011': [ { + // LD-1011 leadType: insurance_claim — REP-05 = Dalton Pruitt (e5), sk_insurance_claim: 60 repId: 'REP-05', score: 89, slotStart: '12:30 PM', slotEnd: '1:30 PM', distanceMi: '1.6', - factors: { proximity: 90, driveTime: 88, calendarFit: 85, weather: 88, skillMatch: 90 }, - reasons: ['Closest rep — 1.6 mi', '9 min drive time', 'Insurance claim proficient', 'Midday slot timing is optimal'], - stormReasons: ['Midday window — acceptable conditions', 'Insurance claim can be initiated outdoors then moved inside'], - aiInsight: 'Close proximity with optimal midday timing — insurance initiation can flex indoors if needed', + factors: { proximity: 90, driveTime: 88, calendarFit: 85, weather: 88, skillMatch: 60 }, + reasons: ['Closest rep — 1.6 mi', '9 min drive time', 'Insurance Claim 60/100 — can walk customer through initial adjuster steps', 'Customer Comms 88/100 — high rapport for new hail claimants', 'Midday slot timing is optimal'], + stormReasons: ['Midday window — acceptable conditions', 'Insurance claim initiation can flex indoors if needed'], + aiInsight: 'Dalton scores 60 on Insurance Claim and 88 on Customer Comms — well-suited to walk this first-time claimant through the process. Proximity and midday timing optimize the slot.', conflictFlag: null, routePath: [[33.0198, -96.7234], [33.0233, -96.7168], [33.0267, -96.7102]], }, { + // REP-03 = Travis Boone (e3), sk_insurance_claim: 28 repId: 'REP-03', score: 76, slotStart: '2:00 PM', slotEnd: '3:00 PM', distanceMi: '3.5', - factors: { proximity: 74, driveTime: 70, calendarFit: 78, weather: 76, skillMatch: 80 }, - reasons: ['Available at 2 PM', '18 min drive', 'Retail estimate skilled'], + factors: { proximity: 74, driveTime: 70, calendarFit: 78, weather: 76, skillMatch: 28 }, + reasons: ['Available at 2 PM', '18 min drive', 'Insurance Claim 28/100 — early-stage skill, needs coaching on adjuster process', 'Customer Comms 67/100 — approachable demeanor'], stormReasons: ['Afternoon slot — conditions marginal after 2:30 PM'], - aiInsight: 'Partial skill match with afternoon availability — conditions deteriorate mid-appointment window', - conflictFlag: 'Skill alignment moderate — retail primary, insurance secondary only', + aiInsight: 'Travis scores only 28 on Insurance Claim — the weakest fit for this lead type. Pair with a detailed briefing note or reassign to Cody (88/100) if Dalton\'s slot is unavailable.', + conflictFlag: 'Significant skill gap — Insurance Claim 28/100; supervisor review recommended before dispatch', routePath: [[33.0389, -96.7401], [33.0328, -96.7252], [33.0267, -96.7102]], }, ], 'LD-1012': [ { + // LD-1012 leadType: roof_inspection — REP-01 = Cody Tatum (e1), sk_roof_inspection: 81 repId: 'REP-01', score: 92, slotStart: '10:00 AM', slotEnd: '10:45 AM', distanceMi: '1.7', - factors: { proximity: 94, driveTime: 92, calendarFit: 88, weather: 92, skillMatch: 95 }, - reasons: ['Currently assigned — optimal', '1.7 mi from current position', 'Morning slot — ideal weather window', 'Insurance + retail estimate certified'], + factors: { proximity: 94, driveTime: 92, calendarFit: 88, weather: 92, skillMatch: 81 }, + reasons: ['Currently assigned — optimal', '1.7 mi from current position', 'Roof Inspection 81/100 — strong documentation for competing-estimate rebuttal', 'Morning slot — ideal weather window', 'Carries drone for aerial measurement — differentiates vs. competitor'], stormReasons: ['Morning slot — safe window before any afternoon weather'], - aiInsight: 'Morning assignment with ideal conditions — dual-certified rep maximizes flexibility for this job type', + aiInsight: 'Cody scores 81 on Roof Inspection and flies a drone on every steep-slope job — his aerial measurement capability directly counters the competing estimate. Morning slot with ideal conditions maximizes close probability.', conflictFlag: null, routePath: [[33.0612, -96.7891], [33.0612, -96.8018], [33.0612, -96.8145]], }, { + // REP-04 = Shelby Greer (e4), sk_roof_inspection: 88 repId: 'REP-04', score: 70, slotStart: '1:00 PM', slotEnd: '1:45 PM', distanceMi: '5.3', - factors: { proximity: 65, driveTime: 62, calendarFit: 82, weather: 70, skillMatch: 85 }, - reasons: ['Afternoon availability', '24 min drive from current location', 'Roof inspection certified'], + factors: { proximity: 65, driveTime: 62, calendarFit: 82, weather: 70, skillMatch: 88 }, + reasons: ['Afternoon availability', '24 min drive from current location', 'Roof Inspection 88/100 — team-best score, strongest for competing-estimate rebuttal', 'Carries drone + moisture meter'], stormReasons: ['Afternoon — conditions acceptable but watch post-2 PM'], - aiInsight: 'Longer drive reduces score significantly — afternoon window is viable if morning rep unavailable', + aiInsight: 'Shelby scores 88 on Roof Inspection — higher than Cody — and carries a drone and moisture meter. The 5.3 mi drive is the main drag; she is the upgrade choice if morning availability opens up.', conflictFlag: '24 min drive cuts into slot buffer — delays cascade to next appointment', routePath: [[33.0516, -96.7512], [33.0564, -96.7829], [33.0612, -96.8145]], }, @@ -5465,7 +5491,7 @@ const MOCK_ESTIMATES_INITIAL = [ total: 18450.00, templateId: 'certainteed_landmark', templateName: 'CertainTeed Landmark AR', - estimatedBy: 'Marcus Webb', + estimatedBy: 'Cody Tatum', roofArea: 28.4, notes: 'Hail damage from March 15 storm. Insurance claim approved.', }, @@ -5491,7 +5517,7 @@ const MOCK_ESTIMATES_INITIAL = [ total: 14800.00, templateId: 'atlas_glassmaster', templateName: 'Atlas GlassMaster', - estimatedBy: 'Marcus Webb', + estimatedBy: 'Cody Tatum', roofArea: 24.6, notes: null, }, @@ -5530,7 +5556,7 @@ const MOCK_ESTIMATES_INITIAL = [ total: 16900.00, templateId: 'atlas_stormmaster_shake', templateName: 'Atlas StormMaster Shake', - estimatedBy: 'Marcus Webb', + estimatedBy: 'Cody Tatum', roofArea: 26.8, notes: 'Impact resistant upgrade. HOA approved color: Weathered Wood.', }, @@ -5569,7 +5595,7 @@ const MOCK_ESTIMATES_INITIAL = [ total: 11600.00, templateId: 'owens_corning_duration', templateName: 'Owens Corning Duration', - estimatedBy: 'Marcus Webb', + estimatedBy: 'Cody Tatum', roofArea: 18.9, notes: 'Apartment unit — common area roof section only.', }, @@ -9705,7 +9731,7 @@ export const INITIAL_STORM_ZONES = [ [33.080, -96.720], [33.086, -96.738], [33.100, -96.738], ], assignedAgentId: 'REP-01', - assignedAgentName: 'Carlos Mendez', + assignedAgentName: 'Cody Tatum', color: '#F59E0B', status: 'active', createdAt: '2026-04-29T08:00:00Z', @@ -9719,7 +9745,7 @@ export const INITIAL_STORM_ZONES = [ [33.003, -96.712], [33.011, -96.727], [33.025, -96.727], ], assignedAgentId: 'REP-02', - assignedAgentName: 'Aisha Kumar', + assignedAgentName: 'Hannah Reyes', color: '#8B5CF6', status: 'active', createdAt: '2026-02-04T09:00:00Z', @@ -9733,7 +9759,7 @@ export const INITIAL_STORM_ZONES = [ [33.017, -96.774], [33.025, -96.791], [33.039, -96.791], ], assignedAgentId: 'REP-04', - assignedAgentName: 'Nina Patel', + assignedAgentName: 'Shelby Greer', color: '#10B981', status: 'completed', createdAt: '2025-11-06T07:30:00Z',