feat(leads): Lead Creation Phase 1 — page shell, section framework, mock data
- CreateLeadPage.jsx: full page shell with Quick Capture / Full Form toggle, Barlow Condensed header, breadcrumb nav, GSAP progress bar stub, mobile sticky save footer - LeadSectionWrapper.jsx: collapsible section component with Framer Motion height animation, spring chevron rotation, completion dot, dual light/dark header design matching GlassPanel language - 5 sections wired up: Contact (blue), Property (emerald), Job Details (amber), Insurance (violet), Assignment (cyan) — Quick Capture shows first 3, Full Form shows all 5 - Section indicator pills in header dim gracefully when hidden in Quick Capture mode - LEAD_FORM_OPTIONS added to mockStore: lead types, sources, work types, trade types, urgency/priority levels, insurance companies, claim statuses, phone/email types, US states - Route /emp/fa/leads/new added (FIELD_AGENT, ADMIN, OWNER) - New Lead nav item added to sidebar for all 3 roles
This commit is contained in:
@@ -5,7 +5,7 @@ import { useTheme } from '../context/ThemeContext';
|
||||
import {
|
||||
LayoutDashboard, Map, Calendar, LogOut, User, Home, MessageSquare,
|
||||
ChevronLeft, ChevronRight, Sun, Moon, Trophy, Users, Briefcase,
|
||||
FileText, Menu, X, Calculator
|
||||
FileText, Menu, X, Calculator, PlusCircle
|
||||
} from 'lucide-react';
|
||||
|
||||
import PageTransition from './PageTransition';
|
||||
@@ -137,10 +137,11 @@ const Layout = () => {
|
||||
{ to: "/owner/snapshot", icon: LayoutDashboard, label: "Owners Box" },
|
||||
{ to: "/admin/dashboard", icon: LayoutDashboard, label: "Dashboard" },
|
||||
{ to: "/owner/projects", icon: Briefcase, label: "Projects" },
|
||||
{ to: "/emp/fa/leads/new", icon: PlusCircle, label: "New Lead" },
|
||||
{ to: "/owner/maps", icon: Map, label: "Territory Map" },
|
||||
{
|
||||
to: "/owner/pro-canvas",
|
||||
icon: LayoutDashboard, // Placeholder icon, maybe change later
|
||||
icon: LayoutDashboard,
|
||||
label: <span><span className="text-[#fda913]">Pro</span>Canvas</span>
|
||||
},
|
||||
{ to: "/owner/estimate", icon: Calculator, label: "Estimate Builder" },
|
||||
@@ -153,6 +154,7 @@ const Layout = () => {
|
||||
{ to: "/admin/dashboard", icon: LayoutDashboard, label: "Dashboard" },
|
||||
{ to: "/admin/schedule", icon: Calendar, label: "Schedule" },
|
||||
{ to: "/admin/leaderboard", icon: Trophy, label: "Leaderboard" },
|
||||
{ to: "/emp/fa/leads/new", icon: PlusCircle, label: "New Lead" },
|
||||
{ to: "/admin/maps", icon: Map, label: "Territory Map" },
|
||||
{
|
||||
to: "/admin/pro-canvas",
|
||||
@@ -179,6 +181,7 @@ const Layout = () => {
|
||||
return [
|
||||
{ to: "/emp/fa/dashboard", icon: LayoutDashboard, label: "Dashboard" },
|
||||
{ to: "/emp/fa/maps", icon: Map, label: "My Map" },
|
||||
{ to: "/emp/fa/leads/new", icon: PlusCircle, label: "New Lead" },
|
||||
{
|
||||
to: "/emp/fa/pro-canvas",
|
||||
icon: LayoutDashboard,
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import React from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { ChevronDown, CheckCircle2 } from 'lucide-react';
|
||||
import { useTheme } from '../../context/ThemeContext';
|
||||
|
||||
export default function LeadSectionWrapper({
|
||||
title,
|
||||
icon: Icon,
|
||||
accentColor,
|
||||
isOpen,
|
||||
onToggle,
|
||||
children,
|
||||
isComplete = false,
|
||||
}) {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === 'dark';
|
||||
|
||||
return (
|
||||
<div className={`rounded-2xl overflow-hidden border transition-shadow duration-200
|
||||
${isDark
|
||||
? 'bg-zinc-900/70 backdrop-blur-xl border-white/[0.08] shadow-[0_8px_32px_rgba(0,0,0,0.3)]'
|
||||
: 'bg-white border-zinc-200/60 shadow-md hover:shadow-lg'
|
||||
}`}
|
||||
>
|
||||
{/* --- Header Button --- */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggle}
|
||||
className={`w-full flex items-center justify-between px-5 py-3.5 transition-opacity duration-150 hover:opacity-90 active:opacity-75
|
||||
${isDark ? 'border-b border-white/[0.08]' : 'rounded-t-2xl'}
|
||||
`}
|
||||
style={isDark ? { backgroundColor: 'rgba(39,39,42,0.8)' } : { backgroundColor: accentColor }}
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
{/* Left: icon + title */}
|
||||
<div className="flex items-center gap-3">
|
||||
{Icon && (
|
||||
<Icon
|
||||
size={17}
|
||||
className={isDark ? '' : 'text-white'}
|
||||
style={isDark ? { color: accentColor } : { opacity: 0.92 }}
|
||||
/>
|
||||
)}
|
||||
<h3 className={`font-['Barlow_Condensed'] font-black uppercase tracking-widest text-sm
|
||||
${isDark ? 'text-[#E4E4E5]' : 'text-white'}
|
||||
`}>
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{/* Right: completion indicator + chevron */}
|
||||
<div className="flex items-center gap-2">
|
||||
<AnimatePresence>
|
||||
{isComplete && (
|
||||
<motion.div
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
exit={{ scale: 0, opacity: 0 }}
|
||||
transition={{ type: 'spring', stiffness: 400, damping: 25 }}
|
||||
>
|
||||
<CheckCircle2
|
||||
size={15}
|
||||
className={isDark ? '' : 'text-white/90'}
|
||||
style={isDark ? { color: accentColor } : {}}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<motion.div
|
||||
animate={{ rotate: isOpen ? 180 : 0 }}
|
||||
transition={{ type: 'spring', stiffness: 300, damping: 28 }}
|
||||
>
|
||||
<ChevronDown
|
||||
size={16}
|
||||
className={isDark ? 'text-zinc-400' : 'text-white/80'}
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* --- Collapsible Content --- */}
|
||||
<AnimatePresence initial={false}>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
key="content"
|
||||
initial={{ height: 0, opacity: 0 }}
|
||||
animate={{ height: 'auto', opacity: 1 }}
|
||||
exit={{ height: 0, opacity: 0 }}
|
||||
transition={{ type: 'spring', stiffness: 300, damping: 32, opacity: { duration: 0.15 } }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="p-5 pt-4">
|
||||
{children}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user