Files
LynkedUpPro_CRM/docs/superpowers/plans/2026-05-29-lead-verification.md
T
2026-05-29 20:59:18 +05:30

12 KiB

Lead Verification Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Steps use checkbox (- [ ]). Follow the execution protocol (2026-05-29-execution-protocol.md) — sequential on shared files, parallel only where lanes are disjoint.

Goal: Add a pre-pipeline Lead Verification stage — a verification-team queue (assign → work → verify/unverify) that, on verify, pushes a real New Lead into our existing leads pipeline. Adapted port from gitea/bugfix/project-refinement (commits 567b29c, 8a4d577), re-authored against our canonical data.

Architecture: New leadVerifications data + 6 mutators in mockStore.jsx (verify writes into our enriched leads array); a reusable portaled ui/Select; the ported LeadVerification/ component set + page; a unified /lead-verification route + sidebar nav. Components reuse our existing useMockStore/usePermissions/SpotlightCard/framer-motion/lucide — so the port is mostly verbatim; the real work is grounding the data and wiring.

Tech Stack: React 18, Vite 7, mock React-context store, framer-motion, lucide-react, pnpm. No test harness → verify via npm run build + grep + dev-run.

Spec: docs/superpowers/specs/2026-05-29-lead-verification-design.md. Source branch: gitea/bugfix/project-refinement (already fetched; pull source files with git show gitea/bugfix/project-refinement:<path>).


File structure

File Responsibility New/Mod
src/data/mockStore.jsx MOCK_LEAD_VERIFICATIONS (15 grounded records) + leadVerifications state + 6 mutators (verify → leads) Modify
src/components/ui/Select.jsx Reusable portaled dark-mode-aware dropdown Create
src/components/LeadVerification/statusConfig.js Status → visuals/icons map Create
src/components/LeadVerification/{SummaryCards,LeadTableRow,LeadCard,LeadStatusBadge,LeadActionsMenu,AssignLeadModal,LeadDetailsModal}.jsx Table/cards/badges/menus/modals Create
src/pages/LeadVerification/LeadVerificationPage.jsx The page: summary tiles + filters + table/cards + modals Create
src/App.jsx /lead-verification route Modify
src/components/Layout.jsx sidebar nav entry Modify

Lane / ownership map

Task Lane (exclusive files) Phase
T1 Data + mutators src/data/mockStore.jsx A
T2 ui/Select new src/components/ui/Select.jsx A (parallel — disjoint)
T3 Components + page new src/components/LeadVerification/* + src/pages/LeadVerification/LeadVerificationPage.jsx B (after T1+T2)
T4 Route + nav src/App.jsx, src/components/Layout.jsx C (after T3)
T5 Verify (read-only) D

T1 and T2 are disjoint → parallel. T3 imports both (store mutators + Select). T4 imports the page. T5 last.


Task 1: Lead-verification data + mutators

Files: src/data/mockStore.jsx only.

The source has MOCK_LEAD_VERIFICATIONS + assignLeadVerification/reassignLeadVerification/setLeadVerificationStatus/verifyLead/unverifyLead/addLeadVerificationNote. Read the source for the mutator logic (git show gitea/bugfix/project-refinement:src/data/mockStore.jsx — search leadVerifications/verifyLead ~lines 6700-6810), but re-author the DATA to our grounded standards and adapt verifyLead to OUR leads schema.

  • Step 1 — record shape + 15 grounded records. Add const MOCK_LEAD_VERIFICATIONS = [ ... ] near the other mock arrays. Each record:
    {
      id: 'lv_001', leadId: 'LD-V-001',
      customerName: '<realistic Plano homeowner>', phone: '<varied DFW, en-US, NOT (972) 555-0NNN>',
      email: '<name-derived>', address: '<real Plano street>, Plano, TX <zip>',
      source: '<Door Knock | Storm Canvass | Web Form | Call Center | Referral>',
      status: '<Pending | Assigned | In Progress | Verified | Unverified>',
      verificationStatus: '<Unassigned | Pending Outreach | Awaiting Confirmation | Verifying Identity | Reviewing Insurance | Emergency — Awaiting Verifier | Failed Contact | Verified>',
      assigneeId: '<a1|a2|a3|null>', assigneeName: '<Wade Hollis|Darlene Brooks|Roy Schaefer|null>',
      urgency: '<standard|high|emergency>',
      createdAt: '<ISO>', assignedAt: '<ISO|null>', verifiedAt: '<ISO|null>',
      verificationNotes: '<short realistic note>',
      history: [{ at: '<ISO>', by: '<person>', action: '<text>' }],
    }
    
    Grounding (per spec): verifiers = canonical admins a1 Wade Hollis / a2 Darlene Brooks / a3 Roy Schaefer; customers = realistic varied Plano homeowners (NO placeholders/movie names/sequential fakes); phones varied DFW (972/469/214/945), en-US; real Plano addresses+zips; status ↔ verificationStatus internally consistent (Verified↔Verified; In Progress↔a working state; Unassigned↔no assignee); dates createdAt ≤ assignedAt ≤ verifiedAt ≤ 2026-05-29. Spread across states: ~2 Verified, ~2 Unverified/Failed Contact, several Assigned/In Progress, a few Pending/Unassigned, 1 Emergency — Awaiting Verifier.
  • Step 2 — state + mutators. Add const [leadVerifications, setLeadVerifications] = useState(MOCK_LEAD_VERIFICATIONS);. Port the 6 mutators (adapt names/logic from source):
    • assignLeadVerification(id, assigneeId, assigneeName) → status Assigned, verificationStatus Pending Outreach (if was Unassigned), set assignee + assignedAt, append history.
    • reassignLeadVerification(id, assigneeId, assigneeName) → swap assignee, append history.
    • setLeadVerificationStatus(id, newStatus, note) → set status (+ derive a sensible verificationStatus), append history with note.
    • verifyLead(id) → set status:'Verified', verificationStatus:'Verified', verifiedAt, append history "Verified and pushed to New Leads", AND push a New Lead onto leads matching OUR lead schema (read seedLeadsFromAttribution() for the exact shape — { id:'lead_'+Date.now(), createdAt, status:'New', firstName, lastName, address, city:'Plano', state:'TX', zip, urgency, leadSource, phones:[{number,type:'Mobile',isPrimary:true}], emails:[{email,isPrimary:true}], createdByName:'Lead Verification', verificationId:id }). Derive firstName/lastName by splitting customerName.
    • unverifyLead(id, note)status:'Unverified', append history.
    • addLeadVerificationNote(id, note) → append to history.
  • Step 3 — expose leadVerifications + the 6 mutators on the context value object (object-shorthand, matching the existing pattern).
  • Step 4 (verify): npm run build✓ built, 0 duplicate-key warnings. git grep -c "verificationStatus:" -- src/data/mockStore.jsx ≥ 15. git grep -nE "\(972\) 555-0[0-9]{3}" shows none introduced. Spot-check 3 records: status↔verificationStatus consistent, assignees are real admins.
  • Step 5: commit git commit -am "feat(data): lead-verification queue + mutators (verify pushes a grounded New Lead into the pipeline)".

Task 2: Reusable ui/Select

Files: Create src/components/ui/Select.jsx. Parallel with T1.

  • Step 1: Create the file with the source content verbatim (it's framework-only — React + framer-motion + lucide, no app deps): git show gitea/bugfix/project-refinement:src/components/ui/Select.jsx → write it to src/components/ui/Select.jsx. It's a portaled dropdown (props: value, onChange, options:[{value,label}]|string[], placeholder, id, ariaLabel, className) that renders correctly in dark mode.
  • Step 2 (verify): npm run build✓ built (it's unused until T3, so the bundler tree-shakes it — that's fine; the build just confirms it parses). node -e "..." not needed.
  • Step 3: commit git commit -am "feat(ui): add reusable portaled dark-mode-aware Select component" (after git add src/components/ui/Select.jsx).

Task 3: LeadVerification components + page

Files: Create src/components/LeadVerification/{statusConfig.js, SummaryCards.jsx, LeadStatusBadge.jsx, LeadActionsMenu.jsx, LeadTableRow.jsx, LeadCard.jsx, AssignLeadModal.jsx, LeadDetailsModal.jsx} and src/pages/LeadVerification/LeadVerificationPage.jsx. After T1 + T2.

  • Step 1: For EACH file, pull the source with git show gitea/bugfix/project-refinement:<path> and create it in our tree. The imports already match our codebase (../../data/mockStore, ../../hooks/usePermissions, ../../components/SpotlightCard, ../ui/Select, framer-motion, lucide) — keep them.
  • Step 2: Verify the page/components reference the SAME store keys T1 exposed: leadVerifications, assignLeadVerification, reassignLeadVerification, setLeadVerificationStatus, verifyLead, unverifyLead, addLeadVerificationNote. If any source name differs from T1, reconcile to T1's names (T1 is the source of truth).
  • Step 3: The AssignLeadModal lists assignees — point it at our canonical admins (a1/a2/a3) from the store (users/personnel filtered to ADMIN), not any hardcoded source list. The source-filter options derive from the records' source values; the assignee-filter from assigneeName.
  • Step 4 (verify): npm run build✓ built, 0 duplicate-key warnings. Grep that the page imports resolve and reference only T1's store keys.
  • Step 5: commit git commit -am "feat(leadverification): port verification page + components (table, cards, summary, assign/verify modals)".

Task 4: Route + nav

Files: src/App.jsx, src/components/Layout.jsx. After T3.

  • Step 1 (App.jsx): import LeadVerificationPage (import LeadVerificationPage from './pages/LeadVerification/LeadVerificationPage';). Add ONE unified route:
    <Route path="/lead-verification" element={
      <ProtectedRoute allowedRoles={['OWNER', 'ADMIN', 'FIELD_AGENT']}>
        <LeadVerificationPage />
      </ProtectedRoute>
    } />
    
    (Unified per our Plan-2 direction; interim coarse guard — Plan 8 ABAC replaces it. Do NOT add the source's three role-prefixed routes.)
  • Step 2 (Layout.jsx): add a nav entry { to: "/lead-verification", icon: ShieldCheck, label: "Lead Verification" } to the OWNER, ADMIN, and FIELD_AGENT nav arrays (after the "Leads" entry). Import ShieldCheck from lucide-react if not already imported.
  • Step 3 (verify): npm run build✓ built. git grep -n "/lead-verification" -- src/App.jsx src/components/Layout.jsx shows the route + nav entries.
  • Step 4: commit git commit -am "feat(routes): add /lead-verification route + sidebar nav".

Task 5: Verify (read-only)

  • npm run build clean, 0 duplicate-key warnings.
  • 15 verification records; summary tiles' counts equal the per-status record counts (computed, not hardcoded); filters (status/source/assignee) narrow the list.
  • No fake names/placeholders in the records (git grep for movie names / (972) 555-0NNN → none); assignees are a1/a2/a3.
  • The verify→pipeline link (headline): dev-run → open /lead-verification, verify a record → it leaves the active queue (status Verified) AND a matching New Lead appears in the Leads list (/…/leads) with createdByName: 'Lead Verification', and that new lead opens in the lead detail page (Plan 6) with no broken fields.
  • Assign / reassign / set-status / unverify / add-note persist in session and update the table + badges.
  • /lead-verification reachable from the sidebar for OWNER/ADMIN/FIELD_AGENT.

Self-review checklist

  • 15 grounded verification records (real admins/customers/addresses/sources; no fakes; status↔verificationStatus consistent; coherent dates).
  • 6 mutators exposed; verifyLead pushes a schema-correct New Lead into leads.
  • ui/Select + all LeadVerification/ files + page ported; imports resolve; reference only T1's store keys.
  • Unified /lead-verification route + nav for the 3 roles; source's RBAC/access-matrix changes NOT ported.
  • Build clean; verify→New Lead works end-to-end into the existing pipeline.