feat(leads): Phase 5 & 6 — Insurance and Assignment sections
Phase 5 — Insurance (purple #8B5CF6): - Insurance Company custom select, Claim Number + Claim Status (2-col grid) - Adjuster Name + Adjuster Phone (2-col grid, flex-wrapper with Phone icon + mask) - Policy Number full-width input, all focus rings use purple accent Phase 6 — Assignment (cyan #06B6D4): - Role-aware rep selector: Field Agents see self-assign toggle, Admins/Owners see scrollable list of all field agents with Unassigned option - Priority pill selector (Low/Medium/High) with Framer Motion layoutId slide - Follow-up Date: flex-wrapper with Calendar icon + color-scheme fix - sectionCompletion wired for both sections Fix: replace Framer Motion variant inheritance with explicit initial/animate on each section motion.div — inherited variants from already-animated parent caused Insurance and Assignment to render stuck at opacity:0 when added dynamically Author: Satyam Rastogi
This commit is contained in:
@@ -0,0 +1,235 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Calendar } from 'lucide-react';
|
||||||
|
import { useMockStore } from '../../data/mockStore';
|
||||||
|
import { useTheme } from '../../context/ThemeContext';
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Shared field primitives
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
function FieldLabel({ children }) {
|
||||||
|
return (
|
||||||
|
<label className="block text-[11px] uppercase tracking-widest font-bold text-zinc-400 dark:text-zinc-500 mb-1.5">
|
||||||
|
{children}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Priority pill selector — Low / Medium / High
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
const PRIORITY_OPTIONS = [
|
||||||
|
{ value: 'low', label: 'Low', darkColor: '#71717a', lightColor: '#71717a' },
|
||||||
|
{ value: 'medium', label: 'Medium', darkColor: '#06B6D4', lightColor: '#0891b2' },
|
||||||
|
{ value: 'high', label: 'High', darkColor: '#F59E0B', lightColor: '#d97706' },
|
||||||
|
];
|
||||||
|
|
||||||
|
function PriorityPillSelector({ value, onChange }) {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const isDark = theme === 'dark';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`flex items-center p-1 rounded-xl ${isDark ? 'bg-zinc-900' : 'bg-zinc-100/80'}`}>
|
||||||
|
{PRIORITY_OPTIONS.map(opt => {
|
||||||
|
const isSelected = value === opt.value;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={opt.value}
|
||||||
|
type="button"
|
||||||
|
onClick={() => onChange(opt.value)}
|
||||||
|
className="relative flex-1 flex items-center justify-center py-2.5 rounded-lg text-xs font-bold uppercase tracking-wider transition-colors duration-150"
|
||||||
|
>
|
||||||
|
{isSelected && (
|
||||||
|
<motion.div
|
||||||
|
layoutId="priority-pill-bg"
|
||||||
|
className={`absolute inset-0.5 rounded-[7px] ${
|
||||||
|
isDark
|
||||||
|
? 'bg-zinc-700 shadow-lg ring-1 ring-white/10'
|
||||||
|
: 'bg-white shadow-sm'
|
||||||
|
}`}
|
||||||
|
transition={{ type: 'spring', stiffness: 420, damping: 36 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
className="relative z-10 transition-colors duration-150"
|
||||||
|
style={{
|
||||||
|
color: isSelected
|
||||||
|
? (isDark ? opt.darkColor : opt.lightColor)
|
||||||
|
: isDark ? '#3f3f46' : '#a1a1aa',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{opt.label}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Rep selector — role-aware
|
||||||
|
// Agents: only their own name (self-assign toggle)
|
||||||
|
// Admin/Owner: scrollable list of all field agents
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
function RepSelector({ value, onChange, currentUser, agents }) {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const isDark = theme === 'dark';
|
||||||
|
const isAgent = currentUser?.role === 'FIELD_AGENT';
|
||||||
|
|
||||||
|
if (isAgent) {
|
||||||
|
// Simplified self-assign for field agents
|
||||||
|
const isSelf = value === currentUser.id;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => onChange(isSelf ? '' : currentUser.id)}
|
||||||
|
className={`w-full flex items-center gap-3 px-4 py-3 rounded-xl border transition-all duration-150
|
||||||
|
${isSelf
|
||||||
|
? 'border-cyan-400 dark:border-cyan-500 ring-2 ring-cyan-100 dark:ring-cyan-500/20 bg-cyan-50 dark:bg-cyan-500/10'
|
||||||
|
: 'border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800/60'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{/* Avatar circle */}
|
||||||
|
<div
|
||||||
|
className="w-8 h-8 rounded-full flex items-center justify-center text-xs font-black uppercase shrink-0 text-white"
|
||||||
|
style={{ backgroundColor: '#06B6D4' }}
|
||||||
|
>
|
||||||
|
{currentUser.name.split(' ').map(n => n[0]).join('').slice(0, 2)}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 text-left">
|
||||||
|
<p className={`text-sm font-semibold ${isSelf ? 'text-cyan-700 dark:text-cyan-300' : 'text-zinc-800 dark:text-white'}`}>
|
||||||
|
{currentUser.name}
|
||||||
|
</p>
|
||||||
|
<p className="text-[11px] text-zinc-400 dark:text-zinc-500 uppercase tracking-wide">
|
||||||
|
{currentUser.empId ?? 'Field Agent'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors duration-150
|
||||||
|
${isSelf ? 'border-cyan-500 bg-cyan-500' : 'border-zinc-300 dark:border-zinc-600'}`}
|
||||||
|
>
|
||||||
|
{isSelf && <div className="w-1.5 h-1.5 rounded-full bg-white" />}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin / Owner — scrollable agent list
|
||||||
|
return (
|
||||||
|
<div className={`rounded-xl border overflow-hidden
|
||||||
|
${isDark ? 'border-zinc-700 bg-zinc-800/60' : 'border-zinc-200 bg-white'}`}
|
||||||
|
>
|
||||||
|
<div className="max-h-48 overflow-y-auto divide-y divide-zinc-100 dark:divide-zinc-700/60">
|
||||||
|
{/* Unassigned option */}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => onChange('')}
|
||||||
|
className={`w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors duration-100
|
||||||
|
${!value
|
||||||
|
? 'bg-cyan-50 dark:bg-cyan-500/10'
|
||||||
|
: 'hover:bg-zinc-50 dark:hover:bg-zinc-700/40'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="w-8 h-8 rounded-full flex items-center justify-center shrink-0
|
||||||
|
bg-zinc-200 dark:bg-zinc-700 text-zinc-400 dark:text-zinc-500 text-xs font-bold">
|
||||||
|
—
|
||||||
|
</div>
|
||||||
|
<span className={`text-sm font-medium ${!value ? 'text-cyan-700 dark:text-cyan-300' : 'text-zinc-500 dark:text-zinc-400'}`}>
|
||||||
|
Unassigned
|
||||||
|
</span>
|
||||||
|
{!value && <div className="ml-auto w-1.5 h-1.5 rounded-full bg-cyan-500" />}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{agents.map(agent => {
|
||||||
|
const isSelected = value === agent.id;
|
||||||
|
const initials = agent.name.split(' ').map(n => n[0]).join('').slice(0, 2);
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={agent.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => onChange(agent.id)}
|
||||||
|
className={`w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors duration-100
|
||||||
|
${isSelected
|
||||||
|
? 'bg-cyan-50 dark:bg-cyan-500/10'
|
||||||
|
: 'hover:bg-zinc-50 dark:hover:bg-zinc-700/40'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="w-8 h-8 rounded-full flex items-center justify-center text-xs font-black uppercase shrink-0 text-white"
|
||||||
|
style={{ backgroundColor: '#06B6D4', opacity: isSelected ? 1 : 0.7 }}
|
||||||
|
>
|
||||||
|
{initials}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<p className={`text-sm font-semibold truncate
|
||||||
|
${isSelected ? 'text-cyan-700 dark:text-cyan-300' : 'text-zinc-800 dark:text-white'}`}
|
||||||
|
>
|
||||||
|
{agent.name}
|
||||||
|
</p>
|
||||||
|
<p className="text-[11px] text-zinc-400 dark:text-zinc-500 uppercase tracking-wide">
|
||||||
|
{agent.empId ?? 'Field Agent'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{isSelected && <div className="ml-auto w-1.5 h-1.5 rounded-full bg-cyan-500 shrink-0" />}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Assignment Section — Phase 6 (Full Form only)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
export default function LeadAssignmentSection({ formData, updateField, currentUser }) {
|
||||||
|
const { users } = useMockStore();
|
||||||
|
const agents = users.filter(u => u.role === 'FIELD_AGENT');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Assign Rep */}
|
||||||
|
<div>
|
||||||
|
<FieldLabel>Assign Rep</FieldLabel>
|
||||||
|
<RepSelector
|
||||||
|
value={formData.assignedTo}
|
||||||
|
onChange={v => updateField('assignedTo', v)}
|
||||||
|
currentUser={currentUser}
|
||||||
|
agents={agents}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Priority */}
|
||||||
|
<div>
|
||||||
|
<FieldLabel>Priority</FieldLabel>
|
||||||
|
<PriorityPillSelector
|
||||||
|
value={formData.priority}
|
||||||
|
onChange={v => updateField('priority', v)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Follow-up Date */}
|
||||||
|
<div>
|
||||||
|
<FieldLabel>Follow-up Date</FieldLabel>
|
||||||
|
<div className="flex items-center rounded-xl
|
||||||
|
bg-white dark:bg-zinc-800/60
|
||||||
|
border border-zinc-200 dark:border-zinc-700
|
||||||
|
focus-within:border-cyan-400 dark:focus-within:border-cyan-500
|
||||||
|
focus-within:ring-2 focus-within:ring-cyan-100 dark:focus-within:ring-cyan-500/20
|
||||||
|
transition-all duration-150"
|
||||||
|
>
|
||||||
|
<Calendar size={14} className="ml-4 shrink-0 text-zinc-400 pointer-events-none" />
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
value={formData.followUpDate}
|
||||||
|
onChange={e => updateField('followUpDate', e.target.value)}
|
||||||
|
className="flex-1 py-3 pl-3 pr-4 text-sm font-medium
|
||||||
|
outline-none bg-transparent
|
||||||
|
text-zinc-800 dark:text-white
|
||||||
|
[color-scheme:light] dark:[color-scheme:dark]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Phone } from 'lucide-react';
|
||||||
|
import { LEAD_FORM_OPTIONS } from '../../data/mockStore';
|
||||||
|
import LeadCustomSelect from './LeadCustomSelect';
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Shared field primitives
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
function FieldLabel({ children }) {
|
||||||
|
return (
|
||||||
|
<label className="block text-[11px] uppercase tracking-widest font-bold text-zinc-400 dark:text-zinc-500 mb-1.5">
|
||||||
|
{children}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function LeadInput({ label, value, onChange, placeholder, type = 'text' }) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FieldLabel>{label}</FieldLabel>
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
value={value}
|
||||||
|
onChange={e => onChange(e.target.value)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
className="w-full rounded-xl px-4 py-3 text-sm font-medium
|
||||||
|
outline-none transition-all duration-150
|
||||||
|
bg-white dark:bg-zinc-800/60
|
||||||
|
border border-zinc-200 dark:border-zinc-700
|
||||||
|
text-zinc-800 dark:text-white
|
||||||
|
placeholder-zinc-400 dark:placeholder-zinc-500
|
||||||
|
focus:border-purple-400 dark:focus:border-purple-500
|
||||||
|
focus:ring-2 focus:ring-purple-100 dark:focus:ring-purple-500/20"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phone input with (xxx) xxx-xxxx mask and purple focus ring
|
||||||
|
function AdjusterPhoneInput({ label, value, onChange }) {
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const digits = e.target.value.replace(/\D/g, '').slice(0, 10);
|
||||||
|
let formatted = digits;
|
||||||
|
if (digits.length >= 7) {
|
||||||
|
formatted = `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`;
|
||||||
|
} else if (digits.length >= 4) {
|
||||||
|
formatted = `(${digits.slice(0, 3)}) ${digits.slice(3)}`;
|
||||||
|
} else if (digits.length >= 1) {
|
||||||
|
formatted = `(${digits}`;
|
||||||
|
}
|
||||||
|
onChange(formatted);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FieldLabel>{label}</FieldLabel>
|
||||||
|
<div className="flex items-center rounded-xl
|
||||||
|
bg-white dark:bg-zinc-800/60
|
||||||
|
border border-zinc-200 dark:border-zinc-700
|
||||||
|
focus-within:border-purple-400 dark:focus-within:border-purple-500
|
||||||
|
focus-within:ring-2 focus-within:ring-purple-100 dark:focus-within:ring-purple-500/20
|
||||||
|
transition-all duration-150"
|
||||||
|
>
|
||||||
|
<Phone size={14} className="ml-4 shrink-0 text-zinc-400 pointer-events-none" />
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
placeholder="(555) 000-0000"
|
||||||
|
className="flex-1 py-3 pl-3 pr-4 text-sm font-medium
|
||||||
|
outline-none bg-transparent
|
||||||
|
text-zinc-800 dark:text-white
|
||||||
|
placeholder-zinc-400 dark:placeholder-zinc-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Insurance Section — Phase 5 (Full Form only)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
export default function LeadInsuranceSection({ formData, updateField }) {
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Row 1: Insurance Company (full width) */}
|
||||||
|
<LeadCustomSelect
|
||||||
|
label="Insurance Company"
|
||||||
|
value={formData.insuranceCompany}
|
||||||
|
onChange={v => updateField('insuranceCompany', v)}
|
||||||
|
options={LEAD_FORM_OPTIONS.insuranceCompanies}
|
||||||
|
placeholder="Select carrier…"
|
||||||
|
accent="purple"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Row 2: Claim Number + Claim Status */}
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
<LeadInput
|
||||||
|
label="Claim Number"
|
||||||
|
value={formData.claimNumber}
|
||||||
|
onChange={v => updateField('claimNumber', v)}
|
||||||
|
placeholder="e.g. CLM-2026-00482"
|
||||||
|
/>
|
||||||
|
<LeadCustomSelect
|
||||||
|
label="Claim Status"
|
||||||
|
value={formData.claimStatus}
|
||||||
|
onChange={v => updateField('claimStatus', v)}
|
||||||
|
options={LEAD_FORM_OPTIONS.claimStatuses}
|
||||||
|
placeholder="Select status…"
|
||||||
|
accent="purple"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Row 3: Adjuster Name + Adjuster Phone */}
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
<LeadInput
|
||||||
|
label="Adjuster Name"
|
||||||
|
value={formData.adjusterName}
|
||||||
|
onChange={v => updateField('adjusterName', v)}
|
||||||
|
placeholder="Full name"
|
||||||
|
/>
|
||||||
|
<AdjusterPhoneInput
|
||||||
|
label="Adjuster Phone"
|
||||||
|
value={formData.adjusterPhone}
|
||||||
|
onChange={v => updateField('adjusterPhone', v)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Row 4: Policy Number (full width) */}
|
||||||
|
<LeadInput
|
||||||
|
label="Policy Number"
|
||||||
|
value={formData.policyNumber}
|
||||||
|
onChange={v => updateField('policyNumber', v)}
|
||||||
|
placeholder="e.g. POL-7734892-A"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ import LeadSectionWrapper from '../components/leads/LeadSectionWrapper';
|
|||||||
import LeadJobSection from '../components/leads/LeadJobSection';
|
import LeadJobSection from '../components/leads/LeadJobSection';
|
||||||
import LeadContactSection from '../components/leads/LeadContactSection';
|
import LeadContactSection from '../components/leads/LeadContactSection';
|
||||||
import LeadPropertySection from '../components/leads/LeadPropertySection';
|
import LeadPropertySection from '../components/leads/LeadPropertySection';
|
||||||
|
import LeadInsuranceSection from '../components/leads/LeadInsuranceSection';
|
||||||
|
import LeadAssignmentSection from '../components/leads/LeadAssignmentSection';
|
||||||
import gsap from 'gsap';
|
import gsap from 'gsap';
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -59,23 +61,6 @@ const SECTIONS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Animation variants
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
const containerVariants = {
|
|
||||||
hidden: {},
|
|
||||||
visible: { transition: { staggerChildren: 0.07 } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const sectionVariants = {
|
|
||||||
hidden: { opacity: 0, y: 22 },
|
|
||||||
visible: {
|
|
||||||
opacity: 1,
|
|
||||||
y: 0,
|
|
||||||
transition: { type: 'spring', stiffness: 280, damping: 28 },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Initial form state
|
// Initial form state
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -144,8 +129,8 @@ export default function CreateLeadPage() {
|
|||||||
job: isQuickCapture
|
job: isQuickCapture
|
||||||
? !!formData.leadSource
|
? !!formData.leadSource
|
||||||
: !!(formData.leadSource && formData.leadType && formData.workType),
|
: !!(formData.leadSource && formData.leadType && formData.workType),
|
||||||
insurance: false, // Phase 5
|
insurance: !!(formData.insuranceCompany && formData.claimStatus),
|
||||||
assignment: false, // Phase 6
|
assignment: !!(formData.assignedTo && formData.followUpDate),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Progress = % of visible sections that are complete
|
// Progress = % of visible sections that are complete
|
||||||
@@ -213,20 +198,24 @@ export default function CreateLeadPage() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Placeholder for sections not yet built
|
if (section.id === 'insurance') {
|
||||||
return (
|
return (
|
||||||
<div className={`rounded-xl border-2 border-dashed px-6 py-8 flex flex-col items-center justify-center gap-2 text-center
|
<LeadInsuranceSection
|
||||||
${isDark ? 'border-zinc-700' : 'border-zinc-200'}
|
formData={formData}
|
||||||
`}>
|
updateField={updateField}
|
||||||
<section.icon
|
|
||||||
size={28}
|
|
||||||
style={{ color: section.accentColor, opacity: 0.35 }}
|
|
||||||
/>
|
/>
|
||||||
<p className="text-xs font-semibold uppercase tracking-widest text-zinc-400">
|
);
|
||||||
{section.description}
|
}
|
||||||
</p>
|
if (section.id === 'assignment') {
|
||||||
</div>
|
return (
|
||||||
);
|
<LeadAssignmentSection
|
||||||
|
formData={formData}
|
||||||
|
updateField={updateField}
|
||||||
|
currentUser={user}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -325,17 +314,14 @@ export default function CreateLeadPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- Sections --- */}
|
{/* --- Sections --- */}
|
||||||
<motion.div
|
<div className="space-y-3">
|
||||||
variants={containerVariants}
|
|
||||||
initial="hidden"
|
|
||||||
animate="visible"
|
|
||||||
className="space-y-3"
|
|
||||||
>
|
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
{visibleSections.map(section => (
|
{visibleSections.map(section => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={section.id}
|
key={section.id}
|
||||||
variants={sectionVariants}
|
initial={{ opacity: 0, y: 22 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ type: 'spring', stiffness: 280, damping: 28 }}
|
||||||
layout
|
layout
|
||||||
exit={{
|
exit={{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
@@ -357,7 +343,7 @@ export default function CreateLeadPage() {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</motion.div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ----------------------------------------------------------------
|
{/* ----------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user