feat(data): lead-verification queue + mutators (verify pushes a grounded New Lead into the pipeline)
This commit is contained in:
@@ -6899,6 +6899,327 @@ export const SUBCONTRACTOR_FEE_TYPES = [
|
||||
'Other',
|
||||
];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// LEAD VERIFICATION QUEUE
|
||||
// ---------------------------------------------------------------------------
|
||||
// Admins: a1 Wade Hollis · a2 Darlene Brooks · a3 Roy Schaefer
|
||||
// DEMO_TODAY = 2026-05-29
|
||||
|
||||
const MOCK_LEAD_VERIFICATIONS = [
|
||||
{
|
||||
id: 'lv_001', leadId: 'LD-V-001',
|
||||
customerName: 'Kevin Hartley',
|
||||
phone: '(972) 413-8902',
|
||||
email: 'kevin.hartley@gmail.com',
|
||||
address: '2814 Ravenswood Dr, Plano, TX 75023',
|
||||
source: 'Door Knock',
|
||||
status: 'Verified',
|
||||
verificationStatus: 'Verified',
|
||||
assigneeId: 'a1', assigneeName: 'Wade Hollis',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-14T09:10:00Z',
|
||||
assignedAt: '2026-05-14T09:40:00Z',
|
||||
verifiedAt: '2026-05-16T14:25:00Z',
|
||||
verificationNotes: 'Ownership confirmed via county records. Hail damage from April 28 storm event verified.',
|
||||
history: [
|
||||
{ at: '2026-05-14T09:10:00Z', by: 'System', action: 'Lead submitted via door knock intake.' },
|
||||
{ at: '2026-05-14T09:40:00Z', by: 'Wade Hollis', action: 'Assigned to Wade Hollis.' },
|
||||
{ at: '2026-05-15T08:30:00Z', by: 'Wade Hollis', action: 'First contact made — homeowner confirmed damage.' },
|
||||
{ at: '2026-05-16T14:25:00Z', by: 'Wade Hollis', action: 'Verified and pushed to New Leads.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_002', leadId: 'LD-V-002',
|
||||
customerName: 'Sandra Nguyen',
|
||||
phone: '(469) 551-7034',
|
||||
email: 'sandra.nguyen@yahoo.com',
|
||||
address: '4817 Shady Brook Ln, Plano, TX 75093',
|
||||
source: 'Web Form',
|
||||
status: 'Verified',
|
||||
verificationStatus: 'Verified',
|
||||
assigneeId: 'a2', assigneeName: 'Darlene Brooks',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-17T13:45:00Z',
|
||||
assignedAt: '2026-05-17T14:15:00Z',
|
||||
verifiedAt: '2026-05-19T11:00:00Z',
|
||||
verificationNotes: 'Identity and property ownership confirmed. Adjuster appointment already scheduled.',
|
||||
history: [
|
||||
{ at: '2026-05-17T13:45:00Z', by: 'System', action: 'Lead submitted via website form.' },
|
||||
{ at: '2026-05-17T14:15:00Z', by: 'Darlene Brooks', action: 'Assigned to Darlene Brooks.' },
|
||||
{ at: '2026-05-18T09:00:00Z', by: 'Darlene Brooks', action: 'Marked In Progress — reviewing insurance docs.' },
|
||||
{ at: '2026-05-19T11:00:00Z', by: 'Darlene Brooks', action: 'Verified and pushed to New Leads.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_003', leadId: 'LD-V-003',
|
||||
customerName: 'Marcus Trevino',
|
||||
phone: '(214) 837-4561',
|
||||
email: 'marcus.trevino@outlook.com',
|
||||
address: '1234 Oak Creek Blvd, Plano, TX 75075',
|
||||
source: 'Storm Canvass',
|
||||
status: 'In Progress',
|
||||
verificationStatus: 'Verifying Identity',
|
||||
assigneeId: 'a1', assigneeName: 'Wade Hollis',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-22T11:20:00Z',
|
||||
assignedAt: '2026-05-22T12:00:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Storm canvass capture. Cross-checking ownership records with county appraisal district.',
|
||||
history: [
|
||||
{ at: '2026-05-22T11:20:00Z', by: 'System', action: 'Lead captured during storm canvass.' },
|
||||
{ at: '2026-05-22T12:00:00Z', by: 'Wade Hollis', action: 'Assigned to Wade Hollis.' },
|
||||
{ at: '2026-05-23T09:15:00Z', by: 'Wade Hollis', action: 'Marked In Progress — verifying identity via CAD records.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_004', leadId: 'LD-V-004',
|
||||
customerName: 'Brenda Kowalski',
|
||||
phone: '(972) 604-2817',
|
||||
email: 'b.kowalski@gmail.com',
|
||||
address: '890 Custer Rd, Plano, TX 75075',
|
||||
source: 'Referral',
|
||||
status: 'In Progress',
|
||||
verificationStatus: 'Reviewing Insurance',
|
||||
assigneeId: 'a3', assigneeName: 'Roy Schaefer',
|
||||
urgency: 'high',
|
||||
createdAt: '2026-05-20T08:30:00Z',
|
||||
assignedAt: '2026-05-20T09:00:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Referred by existing customer. Adjuster supplement under review — large residential loss.',
|
||||
history: [
|
||||
{ at: '2026-05-20T08:30:00Z', by: 'System', action: 'Referral submitted by existing customer.' },
|
||||
{ at: '2026-05-20T09:00:00Z', by: 'Roy Schaefer', action: 'Assigned to Roy Schaefer.' },
|
||||
{ at: '2026-05-21T10:45:00Z', by: 'Roy Schaefer', action: 'Marked In Progress — reviewing adjuster supplement.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_005', leadId: 'LD-V-005',
|
||||
customerName: 'Diane Castillo',
|
||||
phone: '(469) 228-6390',
|
||||
email: 'diane.castillo@icloud.com',
|
||||
address: '321 Independence Pkwy, Plano, TX 75023',
|
||||
source: 'Call Center',
|
||||
status: 'Assigned',
|
||||
verificationStatus: 'Pending Outreach',
|
||||
assigneeId: 'a2', assigneeName: 'Darlene Brooks',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-25T14:00:00Z',
|
||||
assignedAt: '2026-05-25T14:30:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Inbound call center lead. First outreach attempt scheduled for tomorrow morning.',
|
||||
history: [
|
||||
{ at: '2026-05-25T14:00:00Z', by: 'System', action: 'Lead created from call center intake.' },
|
||||
{ at: '2026-05-25T14:30:00Z', by: 'Darlene Brooks', action: 'Assigned to Darlene Brooks.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_006', leadId: 'LD-V-006',
|
||||
customerName: 'Gerald Hoffmann',
|
||||
phone: '(972) 386-9140',
|
||||
email: 'gerald.hoffmann@yahoo.com',
|
||||
address: '7654 Preston Rd, Plano, TX 75024',
|
||||
source: 'Storm Canvass',
|
||||
status: 'Assigned',
|
||||
verificationStatus: 'Pending Outreach',
|
||||
assigneeId: 'a3', assigneeName: 'Roy Schaefer',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-26T09:05:00Z',
|
||||
assignedAt: '2026-05-26T09:40:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Storm canvass — visible hail damage on south slope. Assigned for morning call.',
|
||||
history: [
|
||||
{ at: '2026-05-26T09:05:00Z', by: 'System', action: 'Lead captured during storm canvass.' },
|
||||
{ at: '2026-05-26T09:40:00Z', by: 'Roy Schaefer', action: 'Assigned to Roy Schaefer.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_007', leadId: 'LD-V-007',
|
||||
customerName: 'Lucinda Farrar',
|
||||
phone: '(214) 509-3762',
|
||||
email: 'lucinda.farrar@gmail.com',
|
||||
address: '2200 Alma Dr, Plano, TX 75075',
|
||||
source: 'Door Knock',
|
||||
status: 'In Progress',
|
||||
verificationStatus: 'Awaiting Confirmation',
|
||||
assigneeId: 'a1', assigneeName: 'Wade Hollis',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-21T10:00:00Z',
|
||||
assignedAt: '2026-05-21T10:30:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Homeowner reachable. Confirmed damage but waiting on insurance policy number before proceeding.',
|
||||
history: [
|
||||
{ at: '2026-05-21T10:00:00Z', by: 'System', action: 'Lead submitted via door knock intake.' },
|
||||
{ at: '2026-05-21T10:30:00Z', by: 'Wade Hollis', action: 'Assigned to Wade Hollis.' },
|
||||
{ at: '2026-05-22T08:00:00Z', by: 'Wade Hollis', action: 'First contact made — awaiting homeowner insurance docs.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_008', leadId: 'LD-V-008',
|
||||
customerName: 'Preston Okafor',
|
||||
phone: '(945) 762-4830',
|
||||
email: 'p.okafor@outlook.com',
|
||||
address: '555 Legacy Dr, Plano, TX 75023',
|
||||
source: 'Referral',
|
||||
status: 'Pending',
|
||||
verificationStatus: 'Unassigned',
|
||||
assigneeId: null, assigneeName: null,
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-27T08:15:00Z',
|
||||
assignedAt: null,
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Referral from verified homeowner on Legacy Dr. Needs verifier assignment.',
|
||||
history: [
|
||||
{ at: '2026-05-27T08:15:00Z', by: 'System', action: 'Referral submitted by existing customer.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_009', leadId: 'LD-V-009',
|
||||
customerName: 'Tamara Whitfield',
|
||||
phone: '(469) 334-6017',
|
||||
email: 'tamara.whitfield@gmail.com',
|
||||
address: '3301 Avenue K, Plano, TX 75074',
|
||||
source: 'Call Center',
|
||||
status: 'Pending',
|
||||
verificationStatus: 'Unassigned',
|
||||
assigneeId: null, assigneeName: null,
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-28T15:30:00Z',
|
||||
assignedAt: null,
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Inbound call — homeowner reported significant granule loss. Awaiting verifier assignment.',
|
||||
history: [
|
||||
{ at: '2026-05-28T15:30:00Z', by: 'System', action: 'Lead created from call center intake.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_010', leadId: 'LD-V-010',
|
||||
customerName: 'Alicia Drummond',
|
||||
phone: '(972) 817-5429',
|
||||
email: 'alicia.drummond@yahoo.com',
|
||||
address: '6711 W Spring Creek Pkwy, Plano, TX 75024',
|
||||
source: 'Web Form',
|
||||
status: 'Pending',
|
||||
verificationStatus: 'Unassigned',
|
||||
assigneeId: null, assigneeName: null,
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-29T07:45:00Z',
|
||||
assignedAt: null,
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Web form submission this morning. No notes from intake yet.',
|
||||
history: [
|
||||
{ at: '2026-05-29T07:45:00Z', by: 'System', action: 'Lead submitted via website form.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_011', leadId: 'LD-V-011',
|
||||
customerName: 'Raymond Ostrowski',
|
||||
phone: '(214) 673-9045',
|
||||
email: 'r.ostrowski@gmail.com',
|
||||
address: '1800 Jupiter Rd, Plano, TX 75074',
|
||||
source: 'Storm Canvass',
|
||||
status: 'Unverified',
|
||||
verificationStatus: 'Failed Contact',
|
||||
assigneeId: 'a2', assigneeName: 'Darlene Brooks',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-18T16:10:00Z',
|
||||
assignedAt: '2026-05-18T16:40:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Four callback attempts — number goes straight to voicemail. Email bounced. Marking unverified.',
|
||||
history: [
|
||||
{ at: '2026-05-18T16:10:00Z', by: 'System', action: 'Lead captured during storm canvass.' },
|
||||
{ at: '2026-05-18T16:40:00Z', by: 'Darlene Brooks', action: 'Assigned to Darlene Brooks.' },
|
||||
{ at: '2026-05-20T09:00:00Z', by: 'Darlene Brooks', action: 'Attempt 1 — voicemail, no response.' },
|
||||
{ at: '2026-05-21T10:30:00Z', by: 'Darlene Brooks', action: 'Attempt 2 — voicemail.' },
|
||||
{ at: '2026-05-22T14:00:00Z', by: 'Darlene Brooks', action: 'Attempt 3 — voicemail. Email bounced.' },
|
||||
{ at: '2026-05-23T11:15:00Z', by: 'Darlene Brooks', action: 'Marked Unverified — no contact after 4 attempts.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_012', leadId: 'LD-V-012',
|
||||
customerName: 'Felicia Granger',
|
||||
phone: '(469) 490-3156',
|
||||
email: 'felicia.granger@gmail.com',
|
||||
address: '4400 W Parker Rd, Plano, TX 75093',
|
||||
source: 'Door Knock',
|
||||
status: 'Unverified',
|
||||
verificationStatus: 'Failed Contact',
|
||||
assigneeId: 'a3', assigneeName: 'Roy Schaefer',
|
||||
urgency: 'standard',
|
||||
createdAt: '2026-05-16T11:00:00Z',
|
||||
assignedAt: '2026-05-16T11:30:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Number disconnected after two attempts. Owner may have moved. Flagged unverified.',
|
||||
history: [
|
||||
{ at: '2026-05-16T11:00:00Z', by: 'System', action: 'Lead submitted via door knock intake.' },
|
||||
{ at: '2026-05-16T11:30:00Z', by: 'Roy Schaefer', action: 'Assigned to Roy Schaefer.' },
|
||||
{ at: '2026-05-17T09:00:00Z', by: 'Roy Schaefer', action: 'Attempt 1 — number disconnected.' },
|
||||
{ at: '2026-05-18T10:00:00Z', by: 'Roy Schaefer', action: 'Marked Unverified — number disconnected, no secondary contact.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_013', leadId: 'LD-V-013',
|
||||
customerName: 'Nathaniel Crosby',
|
||||
phone: '(972) 945-2807',
|
||||
email: 'n.crosby@icloud.com',
|
||||
address: '5920 Coit Rd, Plano, TX 75023',
|
||||
source: 'Storm Canvass',
|
||||
status: 'Assigned',
|
||||
verificationStatus: 'Pending Outreach',
|
||||
assigneeId: 'a1', assigneeName: 'Wade Hollis',
|
||||
urgency: 'high',
|
||||
createdAt: '2026-05-28T10:00:00Z',
|
||||
assignedAt: '2026-05-28T10:35:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Significant hail event last night. Homeowner flagged as high priority — visible structural damage on ridge.',
|
||||
history: [
|
||||
{ at: '2026-05-28T10:00:00Z', by: 'System', action: 'Lead captured during storm canvass after overnight hail.' },
|
||||
{ at: '2026-05-28T10:35:00Z', by: 'Wade Hollis', action: 'Assigned to Wade Hollis — high urgency.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_014', leadId: 'LD-V-014',
|
||||
customerName: 'Josephine Aldridge',
|
||||
phone: '(214) 770-6381',
|
||||
email: 'jo.aldridge@yahoo.com',
|
||||
address: '3108 Hedgcoxe Rd, Plano, TX 75025',
|
||||
source: 'Call Center',
|
||||
status: 'In Progress',
|
||||
verificationStatus: 'Reviewing Insurance',
|
||||
assigneeId: 'a2', assigneeName: 'Darlene Brooks',
|
||||
urgency: 'high',
|
||||
createdAt: '2026-05-24T13:00:00Z',
|
||||
assignedAt: '2026-05-24T13:30:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Homeowner has Allstate claim already filed. Reviewing adjuster report for scope accuracy.',
|
||||
history: [
|
||||
{ at: '2026-05-24T13:00:00Z', by: 'System', action: 'Lead created from call center intake.' },
|
||||
{ at: '2026-05-24T13:30:00Z', by: 'Darlene Brooks', action: 'Assigned to Darlene Brooks.' },
|
||||
{ at: '2026-05-25T09:00:00Z', by: 'Darlene Brooks', action: 'Marked In Progress — reviewing Allstate adjuster report.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lv_015', leadId: 'LD-V-015',
|
||||
customerName: 'Tyrone Beaumont',
|
||||
phone: '(945) 381-7024',
|
||||
email: 'tyrone.beaumont@gmail.com',
|
||||
address: '4712 Mapleshade Ln, Plano, TX 75093',
|
||||
source: 'Door Knock',
|
||||
status: 'In Progress',
|
||||
verificationStatus: 'Emergency — Awaiting Verifier',
|
||||
assigneeId: 'a3', assigneeName: 'Roy Schaefer',
|
||||
urgency: 'emergency',
|
||||
createdAt: '2026-05-29T06:50:00Z',
|
||||
assignedAt: '2026-05-29T07:00:00Z',
|
||||
verifiedAt: null,
|
||||
verificationNotes: 'Active roof leak with interior water intrusion. Family with young children on site. Emergency verification required immediately.',
|
||||
history: [
|
||||
{ at: '2026-05-29T06:50:00Z', by: 'System', action: 'Emergency intake from door knock — active leak reported.' },
|
||||
{ at: '2026-05-29T07:00:00Z', by: 'Roy Schaefer', action: 'Assigned to Roy Schaefer — emergency priority.' },
|
||||
{ at: '2026-05-29T07:05:00Z', by: 'Roy Schaefer', action: 'Marked In Progress — emergency verification in progress.' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const MOCK_SUBCONTRACTORS = [
|
||||
{
|
||||
id: 'sub_001',
|
||||
@@ -8678,6 +8999,7 @@ export const MockStoreProvider = ({ children }) => {
|
||||
const [kanbanColumns, setKanbanColumns] = useState(KANBAN_COLUMNS_INITIAL);
|
||||
const [kanbanLeads, setKanbanLeads] = useState(KANBAN_LEADS_INITIAL);
|
||||
const [stormZones, setStormZones] = useState(INITIAL_STORM_ZONES);
|
||||
const [leadVerifications, setLeadVerifications] = useState(MOCK_LEAD_VERIFICATIONS);
|
||||
|
||||
// Commission Settings — Org defaults + per-user overrides
|
||||
const [orgCommissionDefaults, setOrgCommissionDefaults] = useState({
|
||||
@@ -9303,6 +9625,157 @@ export const MockStoreProvider = ({ children }) => {
|
||||
toast.success(`Task reassigned to ${subcontractor.name}`);
|
||||
};
|
||||
|
||||
// ── Lead Verification Workflow ──────────────────────────────────────────
|
||||
const appendLvHistory = (lv, entry) => ({
|
||||
...lv,
|
||||
history: [...(lv.history || []), { at: new Date().toISOString(), ...entry }],
|
||||
});
|
||||
|
||||
const assignLeadVerification = (id, assigneeId, assigneeName) => {
|
||||
if (!assigneeId) {
|
||||
toast.error('Please select an assignee.');
|
||||
return;
|
||||
}
|
||||
setLeadVerifications(prev => prev.map(lv => {
|
||||
if (lv.id !== id) return lv;
|
||||
const wasUnassigned = !lv.assigneeId;
|
||||
return appendLvHistory({
|
||||
...lv,
|
||||
assigneeId,
|
||||
assigneeName,
|
||||
status: (lv.status === 'Pending' || lv.status === 'Unverified') ? 'Assigned' : lv.status,
|
||||
verificationStatus: wasUnassigned ? 'Pending Outreach' : lv.verificationStatus,
|
||||
assignedAt: lv.assignedAt || new Date().toISOString(),
|
||||
}, { by: assigneeName, action: `${wasUnassigned ? 'Assigned' : 'Reassigned'} to ${assigneeName}.` });
|
||||
}));
|
||||
toast.success(`Lead assigned to ${assigneeName}`);
|
||||
};
|
||||
|
||||
const reassignLeadVerification = (id, assigneeId, assigneeName) => {
|
||||
if (!assigneeId) {
|
||||
toast.error('Please select an assignee.');
|
||||
return;
|
||||
}
|
||||
setLeadVerifications(prev => prev.map(lv => {
|
||||
if (lv.id !== id) return lv;
|
||||
return appendLvHistory({
|
||||
...lv,
|
||||
assigneeId,
|
||||
assigneeName,
|
||||
}, { by: assigneeName, action: `Reassigned to ${assigneeName}.` });
|
||||
}));
|
||||
toast.success(`Lead reassigned to ${assigneeName}`);
|
||||
};
|
||||
|
||||
const setLeadVerificationStatus = (id, newStatus, note = '') => {
|
||||
setLeadVerifications(prev => prev.map(lv => {
|
||||
if (lv.id !== id) return lv;
|
||||
const derivedVerificationStatus =
|
||||
newStatus === 'In Progress' ? 'Verifying Identity' :
|
||||
newStatus === 'Assigned' ? 'Pending Outreach' :
|
||||
newStatus === 'Pending' ? (lv.assigneeId ? 'Pending Outreach' : 'Unassigned') :
|
||||
newStatus === 'Unverified' ? 'Failed Contact' :
|
||||
lv.verificationStatus;
|
||||
return appendLvHistory({
|
||||
...lv,
|
||||
status: newStatus,
|
||||
verificationStatus: derivedVerificationStatus,
|
||||
verificationNotes: note || lv.verificationNotes,
|
||||
}, { by: lv.assigneeName || 'System', action: `Status changed to ${newStatus}${note ? ` — ${note}` : ''}.` });
|
||||
}));
|
||||
toast.success(`Lead moved to ${newStatus}`);
|
||||
};
|
||||
|
||||
const verifyLead = (id) => {
|
||||
const lv = leadVerifications.find(x => x.id === id);
|
||||
if (!lv) return;
|
||||
if (lv.status === 'Verified') {
|
||||
toast.info('Lead already verified.');
|
||||
return;
|
||||
}
|
||||
const nowIso = new Date().toISOString();
|
||||
setLeadVerifications(prev => prev.map(item => {
|
||||
if (item.id !== id) return item;
|
||||
return appendLvHistory({
|
||||
...item,
|
||||
status: 'Verified',
|
||||
verificationStatus: 'Verified',
|
||||
verifiedAt: nowIso,
|
||||
}, { by: item.assigneeName || 'System', action: 'Verified and pushed to New Leads.' });
|
||||
}));
|
||||
|
||||
// Split customerName → firstName / lastName
|
||||
const nameParts = (lv.customerName || '').trim().split(' ');
|
||||
const firstName = nameParts[0] || 'Unknown';
|
||||
const lastName = nameParts.slice(1).join(' ');
|
||||
|
||||
// Parse city/state from address (e.g. "... Plano, TX 75023")
|
||||
const addrMatch = (lv.address || '').match(/,\s*([^,]+),\s*([A-Z]{2})\s+\d+\s*$/);
|
||||
const city = addrMatch ? addrMatch[1].trim() : 'Plano';
|
||||
const state = addrMatch ? addrMatch[2].trim() : 'TX';
|
||||
|
||||
const newLead = {
|
||||
id: `lead_lv_${Date.now()}`,
|
||||
firstName,
|
||||
lastName,
|
||||
address: lv.address || '',
|
||||
city,
|
||||
state,
|
||||
urgency: lv.urgency || 'standard',
|
||||
status: 'New',
|
||||
leadSource: lv.source || 'Lead Verification',
|
||||
phones: lv.phone ? [{ id: '1', number: lv.phone, type: 'Mobile', isPrimary: true }] : [],
|
||||
emails: lv.email ? [{ email: lv.email, isPrimary: true }] : [],
|
||||
createdAt: nowIso,
|
||||
createdByName: 'Lead Verification',
|
||||
verificationId: lv.id,
|
||||
verificationLeadId: lv.leadId,
|
||||
notes: lv.verificationNotes || '',
|
||||
// Minimal enriched fields so LeadsListPage doesn't break
|
||||
canvasserName: lv.assigneeName || '',
|
||||
assignedTo: '',
|
||||
priority: lv.urgency === 'emergency' ? 'critical' : lv.urgency === 'high' ? 'high' : 'low',
|
||||
followUpDate: '',
|
||||
isQuickCapture: false,
|
||||
zip: (lv.address || '').match(/\d{5}$/)?.[0] || '',
|
||||
propertyType: 'Single Family',
|
||||
propertyPhotos: [],
|
||||
leadType: 'Insurance',
|
||||
workType: 'Roof Replacement',
|
||||
tradeType: 'Roofing',
|
||||
referralNote: '',
|
||||
canvasserId: '',
|
||||
insuranceCompany: '', claimNumber: '', claimStatus: '',
|
||||
adjusterName: '', adjusterPhone: '', policyNumber: '',
|
||||
};
|
||||
setLeads(prev => [newLead, ...prev]);
|
||||
toast.success(`${lv.customerName} verified — moved to New Leads`);
|
||||
};
|
||||
|
||||
const unverifyLead = (id, note = '') => {
|
||||
setLeadVerifications(prev => prev.map(lv => {
|
||||
if (lv.id !== id) return lv;
|
||||
return appendLvHistory({
|
||||
...lv,
|
||||
status: 'Unverified',
|
||||
verificationStatus: 'Failed Contact',
|
||||
verificationNotes: note || lv.verificationNotes,
|
||||
}, { by: lv.assigneeName || 'System', action: `Marked Unverified${note ? ` — ${note}` : ''}.` });
|
||||
}));
|
||||
toast.success('Lead marked as Unverified');
|
||||
};
|
||||
|
||||
const addLeadVerificationNote = (id, note) => {
|
||||
if (!note?.trim()) return;
|
||||
setLeadVerifications(prev => prev.map(lv => {
|
||||
if (lv.id !== id) return lv;
|
||||
return appendLvHistory({
|
||||
...lv,
|
||||
verificationNotes: note.trim(),
|
||||
}, { by: lv.assigneeName || 'System', action: `Note added: ${note.trim()}` });
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<MockStoreContext.Provider value={{
|
||||
properties,
|
||||
@@ -9617,6 +10090,14 @@ export const MockStoreProvider = ({ children }) => {
|
||||
resolveProfile,
|
||||
updateOwnProfile,
|
||||
setSkillScore,
|
||||
// ── Lead Verification Queue ──
|
||||
leadVerifications,
|
||||
assignLeadVerification,
|
||||
reassignLeadVerification,
|
||||
setLeadVerificationStatus,
|
||||
verifyLead,
|
||||
unverifyLead,
|
||||
addLeadVerificationNote,
|
||||
}}>
|
||||
{children}
|
||||
</MockStoreContext.Provider>
|
||||
|
||||
Reference in New Issue
Block a user