import React, { useState, useEffect } from 'react'; import { Helmet } from 'react-helmet'; import { useForm, Controller } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronDown, ChevronUp, Info, CheckCircle2, AlertCircle, Save, X, Building2, User, MapPin, Wallet, Tag, FileText, Zap, Shield, ArrowLeft, UploadCloud } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { toast } from '@/components/ui/use-toast'; import { Switch } from '@/components/ui/switch'; import { Progress } from '@/components/ui/progress'; import { cn } from '@/lib/utils'; import { mockUsers } from '@/data/mockData'; // --- Schema Validation --- const prospectSchema = z.object({ // 1. General type: z.enum(['entreprise', 'particulier']), name: z.string().min(2, "Le nom est requis"), companyName: z.string().optional(), siret: z.string().optional(), category: z.string().optional(), origin: z.string().optional(), status: z.string().optional(), assignedTo: z.string().optional(), // 2. Coordinates address1: z.string().min(5, "L'adresse est requise"), address2: z.string().optional(), zipCode: z.string().min(4, "Code postal requis"), city: z.string().min(2, "Ville requise"), country: z.string().default('France'), // Contact civility: z.string().optional(), contactName: z.string().min(2, "Nom requis"), contactFirstName: z.string().min(2, "Prénom requis"), position: z.string().optional(), email: z.string().email("Email invalide"), phone: z.string().min(10, "Numéro invalide"), phoneSecondary: z.string().optional(), contactPref: z.enum(['email', 'phone', 'sms', 'whatsapp']).default('email'), // 3. Company Info (Conditional in UI logic, permissive in schema) legalForm: z.string().optional(), employees: z.string().optional(), revenue: z.string().optional(), sector: z.string().optional(), website: z.string().url("URL invalide").optional().or(z.literal('')), linkedin: z.string().url("URL invalide").optional().or(z.literal('')), // 4. Commercial priceFamily: z.string().optional(), accountingCategory: z.string().optional(), accountingAccount: z.string().optional(), paymentMethod: z.string().optional(), paymentTerm: z.string().optional(), billingConditions: z.string().optional(), discountCommercial: z.string().optional(), discountFinancial: z.string().optional(), // 5. Technical needsDescription: z.string().optional(), products: z.array(z.string()).optional(), interestLevel: z.enum(['low', 'medium', 'high']).default('medium'), urgency: z.string().optional(), budget: z.string().optional(), followUpDate: z.string().optional(), tags: z.string().optional(), // Simplification for tags as comma string // 6. Notes notes: z.string().optional(), // 7. Automation autoOpportunity: z.boolean().default(false), autoTask: z.boolean().default(false), sendWelcome: z.boolean().default(false), autoAssign: z.boolean().default(false), // 8. Permissions visibility: z.enum(['me', 'team', 'all']).default('team'), role: z.string().default('commercial'), }).refine((data) => { if (data.type === 'entreprise' && !data.companyName) { return false; } return true; }, { message: "La raison sociale est requise pour une entreprise", path: ["companyName"], }); // --- Components --- const Section = ({ title, icon: Icon, children, defaultOpen = true, progress = 100 }) => { const [isOpen, setIsOpen] = useState(defaultOpen); return (
{error.message}
}Remplissez les informations pour créer une fiche prospect complète.