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',
|
'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 = [
|
const MOCK_SUBCONTRACTORS = [
|
||||||
{
|
{
|
||||||
id: 'sub_001',
|
id: 'sub_001',
|
||||||
@@ -8678,6 +8999,7 @@ export const MockStoreProvider = ({ children }) => {
|
|||||||
const [kanbanColumns, setKanbanColumns] = useState(KANBAN_COLUMNS_INITIAL);
|
const [kanbanColumns, setKanbanColumns] = useState(KANBAN_COLUMNS_INITIAL);
|
||||||
const [kanbanLeads, setKanbanLeads] = useState(KANBAN_LEADS_INITIAL);
|
const [kanbanLeads, setKanbanLeads] = useState(KANBAN_LEADS_INITIAL);
|
||||||
const [stormZones, setStormZones] = useState(INITIAL_STORM_ZONES);
|
const [stormZones, setStormZones] = useState(INITIAL_STORM_ZONES);
|
||||||
|
const [leadVerifications, setLeadVerifications] = useState(MOCK_LEAD_VERIFICATIONS);
|
||||||
|
|
||||||
// Commission Settings — Org defaults + per-user overrides
|
// Commission Settings — Org defaults + per-user overrides
|
||||||
const [orgCommissionDefaults, setOrgCommissionDefaults] = useState({
|
const [orgCommissionDefaults, setOrgCommissionDefaults] = useState({
|
||||||
@@ -9303,6 +9625,157 @@ export const MockStoreProvider = ({ children }) => {
|
|||||||
toast.success(`Task reassigned to ${subcontractor.name}`);
|
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 (
|
return (
|
||||||
<MockStoreContext.Provider value={{
|
<MockStoreContext.Provider value={{
|
||||||
properties,
|
properties,
|
||||||
@@ -9617,6 +10090,14 @@ export const MockStoreProvider = ({ children }) => {
|
|||||||
resolveProfile,
|
resolveProfile,
|
||||||
updateOwnProfile,
|
updateOwnProfile,
|
||||||
setSkillScore,
|
setSkillScore,
|
||||||
|
// ── Lead Verification Queue ──
|
||||||
|
leadVerifications,
|
||||||
|
assignLeadVerification,
|
||||||
|
reassignLeadVerification,
|
||||||
|
setLeadVerificationStatus,
|
||||||
|
verifyLead,
|
||||||
|
unverifyLead,
|
||||||
|
addLeadVerificationNote,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</MockStoreContext.Provider>
|
</MockStoreContext.Provider>
|
||||||
|
|||||||
Reference in New Issue
Block a user