```jsx 'use client'; import React, { useState, useMemo, useCallback, useEffect } from 'react'; import { Users, Kanban, CheckSquare, DollarSign, UploadCloud, Search, Bell, Phone, Mail, ArrowLeft, ArrowRight, Trophy, AlertCircle, FileText, CheckCircle2, ChevronRight, MoreHorizontal, Send, CreditCard, Building2, Wallet, ArrowDownUp, Banknote, X } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; // --- Mock Data --- const INITIAL_CONTACTS = [ { id: '1', name: 'Mark Hanson', company: 'HVAC Solutions', role: 'Owner', location: 'Chicago, IL', phone: '+1 (312) 555-0182', email: 'm.hanson@hvacsolutions.com', value: 2400, badge: 'Hot lead', badgeColor: 'text-red-400', stage: 3, avatar: 'MH', avatarBg: 'bg-red-900/30', notes: 'Wants website + SEO. Budget ~$2,500. Follow up Friday with proposal.' }, { id: '2', name: 'Sarah Reem', company: 'GreenBuild Ltd.', role: 'Director', location: 'Austin, TX', phone: '+1 (512) 555-0231', email: 's.reem@greenbuild.com', value: 2800, badge: 'Warm', badgeColor: 'text-yellow-400', stage: 1, avatar: 'SR', avatarBg: 'bg-yellow-900/30', notes: '' }, { id: '3', name: 'Tom Parker', company: 'Westside Woodwork', role: 'Owner', location: 'Denver, CO', phone: '+1 (720) 555-0144', email: 'tom@westsidewood.com', value: 1200, badge: 'New', badgeColor: 'text-blue-400', stage: 0, avatar: 'TP', avatarBg: 'bg-blue-900/30', notes: '' }, { id: '4', name: 'Ana Lima', company: 'Spa Luxe Group', role: 'Manager', location: 'Miami, FL', phone: '+1 (305) 555-0376', email: 'ana.lima@spaluxe.com', value: 4200, badge: 'Warm', badgeColor: 'text-yellow-400', stage: 1, avatar: 'AL', avatarBg: 'bg-green-900/30', notes: '' }, { id: '5', name: 'David Kim', company: 'Metro Plumbing', role: 'Owner', location: 'Seattle, WA', phone: '+1 (206) 555-0289', email: 'd.kim@metroplumb.com', value: 3500, badge: 'New', badgeColor: 'text-blue-400', stage: 0, avatar: 'DK', avatarBg: 'bg-purple-900/30', notes: '' }, { id: '6', name: 'Ben Walsh', company: 'Walsh Roofing', role: 'Owner', location: 'Portland, OR', phone: '+1 (503) 555-0412', email: 'ben@walshroofing.com', value: 1800, badge: 'Closed', badgeColor: 'text-emerald-400', stage: 5, avatar: 'BW', avatarBg: 'bg-orange-900/30', notes: '' }, ]; const STAGES = ['New', 'Follow-up', 'Meeting', 'Quote sent', 'Negotiating', 'Closed']; const DAILY_TASKS = [ { id: 'calls', label: '8 cold calls', current: 3, target: 8 }, { id: 'followups', label: '5 follow-up emails', current: 2, target: 5 }, { id: 'quotes', label: '2 quotes sent', current: 0, target: 2 }, { id: 'meetings', label: '1 meeting booked', current: 0, target: 1 }, { id: 'pipeline', label: 'Pipeline updated', current: 0, target: 1 }, ]; const REVENUE_DATA = [ { id: 'r1', client: 'Ben Walsh โ€” Walsh Roofing', value: 1800, method: 'Stripe', status: 'Paid' }, { id: 'r2', client: 'Jen Morris โ€” City Spa', value: 2400, method: 'Bank transfer', status: 'Paid' }, ]; // --- Components --- const ProgressBar = ({ value, max, color = 'bg-emerald-500' }) => (
); const Avatar = ({ initials, bgColor, size = 'md', className = '' }) => { const sizes = { sm: 'w-6 h-6 text-[10px]', md: 'w-9 h-9 text-xs', lg: 'w-10 h-10 text-sm' }; return (
{initials}
); }; const Button = ({ children, variant = 'primary', size = 'md', icon: Icon, className = '', onClick, disabled }) => { const variants = { primary: 'bg-[#4A90E2] hover:bg-[#3B7DD0] text-white', secondary: 'bg-gray-700/40 hover:bg-gray-700/60 text-gray-200 border border-gray-700/50', success: 'bg-emerald-600 hover:bg-emerald-500 text-white', danger: 'bg-red-600 hover:bg-red-500 text-white', ghost: 'bg-transparent hover:bg-gray-700/30 text-gray-300', }; const sizes = { sm: 'px-2.5 py-1.5 text-xs', md: 'px-3 py-2 text-xs', lg: 'px-4 py-2.5 text-sm', }; return ( ); }; const Modal = ({ isOpen, onClose, title, children }) => { if (!isOpen) return null; return (

{title}

{children}
); }; // --- Main Application --- export default function SalesRepCRM() { const [activeTab, setActiveTab] = useState('contact'); const [contacts, setContacts] = useState(INITIAL_CONTACTS); const [selectedContactId, setSelectedContactId] = useState(INITIAL_CONTACTS[0].id); const [wins, setWins] = useState(2); const [tasks, setTasks] = useState(DAILY_TASKS.map(t => ({ ...t, done: false }))); const [isInvoiceOpen, setIsInvoiceOpen] = useState(false); const [notification, setNotification] = useState(null); const [importPhase, setImportPhase] = useState('idle'); // idle, mapping, done const selectedContact = contacts.find(c => c.id === selectedContactId) || contacts[0]; const showNotify = useCallback((msg, type = 'success') => { setNotification({ msg, type }); setTimeout(() => setNotification(null), 3000); }, []); const updateStage = useCallback((id, newStage) => { setContacts(prev => prev.map(c => c.id === id ? { ...c, stage: newStage, badge: newStage === 5 ? 'Closed' : c.badge, badgeColor: newStage === 5 ? 'text-emerald-400' : c.badgeColor } : c)); }, []); const handleMove = useCallback((dir) => { const currentStage = selectedContact.stage; const nextStage = dir === 'fwd' ? Math.min(5, currentStage + 1) : Math.max(0, currentStage - 1); if (nextStage !== currentStage) { updateStage(selectedContact.id, nextStage); showNotify(`Moved ${selectedContact.name} to ${STAGES[nextStage]}`); if (nextStage === 5) { setWins(w => w + 1); showNotify(`๐ŸŽ‰ Deal closed for ${selectedContact.name}!`); } } }, [selectedContact, updateStage, showNotify]); const toggleTask = useCallback((id) => { setTasks(prev => { const updated = prev.map(t => t.id === id ? { ...t, done: !t.done } : t); const doneCount = updated.filter(t => t.done).length; setWins(doneCount); // Sync wins with tasks for this demo return updated; }); }, []); const handleImport = useCallback(() => { if (importPhase === 'idle') { setImportPhase('mapping'); showNotify('File loaded. 47 contacts detected. Please map columns.'); } else { setImportPhase('done'); showNotify('โœ… 47 contacts successfully imported.'); setTimeout(() => setImportPhase('idle'), 2000); } }, [importPhase, showNotify]); // --- Views --- const ContactView = () => { const c = selectedContact; return ( {/* Header */}

{c.name} {c.badge}

{c.role} ยท {c.company} ยท {c.location}

{c.phone} {c.email}
{/* Stage Indicator */}
{STAGES.map((stage, idx) => { const isPast = idx < c.stage; const isCurrent = idx === c.stage; return ( {idx < 5 &&
} ); })}
{/* Actions */}
{/* Content Grid */}
{/* Notes */}
Call Notes