new lead created by estimate wizard now list in leads page
This commit is contained in:
@@ -4,11 +4,12 @@
|
||||
* the inspection, and fires the CRM + nurture handoff (once) with the immutable
|
||||
* compliance record (spec §18 G1).
|
||||
*/
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Download, Printer, Mail, Share2, CalendarCheck, FileText, Loader2, Check } from 'lucide-react';
|
||||
import { useEstimateWizard } from '../../EstimateWizardContext';
|
||||
import { useMockStore } from '../../../../data/mockStore';
|
||||
import { buildReportModel, downloadReportPdf, getReportBlobUrl } from '../../utils/wizardReportExport';
|
||||
import { submitToCrm } from '../../api/crmHandoff';
|
||||
import { submitToCrm, buildLeadFromSession } from '../../api/crmHandoff';
|
||||
import { formatUSD } from '../../engine/pricing';
|
||||
|
||||
const PKG_LABEL = { GOOD: 'Good', BETTER: 'Better', BEST: 'Best' };
|
||||
@@ -29,18 +30,33 @@ const ActionButton = ({ icon: Icon, label, onClick, busy, primary }) => (
|
||||
|
||||
const ReportStep = () => {
|
||||
const { session, tenantConfig, patchSession, logEvent } = useEstimateWizard();
|
||||
const { addWizardLead } = useMockStore();
|
||||
const model = buildReportModel(session, tenantConfig);
|
||||
const [busy, setBusy] = useState(null);
|
||||
const [booked, setBooked] = useState(!!session.report?.appointmentBooked);
|
||||
const firedRef = useRef(false);
|
||||
|
||||
// Fire CRM + nurture handoff once (spec §13 / §17 E2).
|
||||
// Fire CRM + nurture handoff once (spec §13 / §17 E2). The ref guard prevents a
|
||||
// duplicate lead under React StrictMode's double-invoked mount effect.
|
||||
useEffect(() => {
|
||||
if (session.report) return;
|
||||
const reportMeta = { reportId: model.reportId, version: 1, generatedAt: model.generatedAt, deliveryStatus: 'created' };
|
||||
if (firedRef.current || session.report) return;
|
||||
firedRef.current = true;
|
||||
|
||||
// Create a real lead in the global CRM mock store so the estimate shows up
|
||||
// in the pipeline (addLead injects id / createdAt / status: 'New').
|
||||
const lead = addWizardLead(buildLeadFromSession(session, tenantConfig, {
|
||||
reportId: model.reportId,
|
||||
estimatedTotal: model.totals.total,
|
||||
}));
|
||||
|
||||
const reportMeta = {
|
||||
reportId: model.reportId, version: 1, generatedAt: model.generatedAt,
|
||||
deliveryStatus: 'created', crmLeadId: lead?.id || null, estimatedTotal: model.totals.total,
|
||||
};
|
||||
patchSession({ report: reportMeta });
|
||||
submitToCrm(session, tenantConfig, reportMeta);
|
||||
logEvent('report_generated', { reportId: model.reportId });
|
||||
logEvent('crm_handoff', { trigger: 'wizard_completed' });
|
||||
logEvent('crm_handoff', { trigger: 'wizard_completed', crmLeadId: lead?.id || null });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Consent is required before proceeding (spec §15 Privacy / §3 compliance).
|
||||
*/
|
||||
import React from 'react';
|
||||
import { User, MapPin, Phone, Mail } from 'lucide-react';
|
||||
import { User, MapPin, Phone, Mail, Wand2 } from 'lucide-react';
|
||||
import { useEstimateWizard } from '../../EstimateWizardContext';
|
||||
|
||||
const Field = ({ icon: Icon, label, children }) => (
|
||||
@@ -21,10 +21,18 @@ const inputCls =
|
||||
'text-zinc-900 dark:text-white placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-amber-500';
|
||||
|
||||
const StartStep = () => {
|
||||
const { inputs, setInput } = useEstimateWizard();
|
||||
const { inputs, setInput, prefillDemo } = useEstimateWizard();
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={prefillDemo}
|
||||
className="w-full flex items-center justify-center gap-2 rounded-xl border border-dashed border-amber-300 dark:border-amber-500/30 bg-amber-50 dark:bg-amber-500/10 px-3 py-2.5 text-sm font-medium text-amber-700 dark:text-amber-300 hover:border-amber-400"
|
||||
>
|
||||
<Wand2 size={15} /> Try a demo address (auto-fills every answer)
|
||||
</button>
|
||||
|
||||
<Field icon={User} label="Name">
|
||||
<input
|
||||
className={inputCls}
|
||||
|
||||
Reference in New Issue
Block a user