'use client'; import React, { useState, useEffect, useRef } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { Card } from 'primereact/card'; import { Button } from 'primereact/button'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { Calendar } from 'primereact/calendar'; import { Dropdown } from 'primereact/dropdown'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Toast } from 'primereact/toast'; import { ProgressSpinner } from 'primereact/progressspinner'; import { Toolbar } from 'primereact/toolbar'; import { Message } from 'primereact/message'; import { devisService, clientService } from '../../../../../services/api'; import { formatCurrency } from '../../../../../utils/formatters'; import type { Devis } from '../../../../../types/btp'; import { StatutDevis } from '../../../../../types/btp'; const DuplicateDevisPage = () => { const params = useParams(); const router = useRouter(); const toast = useRef(null); const [originalDevis, setOriginalDevis] = useState(null); const [newDevis, setNewDevis] = useState>({ id: '', numero: '', dateEmission: new Date().toISOString(), dateValidite: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), objet: '', description: '', montantHT: 0, montantTTC: 0, tauxTVA: 20, statut: StatutDevis.BROUILLON, actif: true, lignes: [] }); const [clients, setClients] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const originalDevisId = params.id as string; useEffect(() => { loadData(); }, [originalDevisId]); const loadData = async () => { try { setLoading(true); const [original, clients] = await Promise.all([ devisService.getById(originalDevisId), clientService.getAll() ]); setOriginalDevis(original); setClients(clients); // Générer un nouveau numéro de devis const newNumero = await generateNewNumero(); // Préparer le nouveau devis avec les données de l'original setNewDevis({ id: '', numero: newNumero, dateEmission: new Date().toISOString(), dateValidite: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), objet: `${original.objet} (Copie)`, description: original.description, montantHT: original.montantHT, montantTTC: original.montantTTC, tauxTVA: original.tauxTVA, statut: StatutDevis.BROUILLON, actif: true, client: original.client, lignes: original.lignes ? [...original.lignes] : [] }); } catch (error) { console.error('Erreur lors du chargement:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger le devis original' }); } finally { setLoading(false); } }; const generateNewNumero = async (): Promise => { try { // TODO: Implémenter la génération automatique de numéro const year = new Date().getFullYear(); const timestamp = Date.now().toString().slice(-6); return `DEV-${year}-${timestamp}`; } catch (error) { console.error('Erreur génération numéro:', error); return `DEV-${Date.now()}`; } }; const calculateMontants = () => { const montantHT = (newDevis.lignes || []).reduce((sum, ligne) => sum + (ligne.montantLigne || 0), 0); const montantTTC = montantHT * (1 + (newDevis.tauxTVA || 0) / 100); setNewDevis(prev => ({ ...prev, montantHT, montantTTC })); }; useEffect(() => { calculateMontants(); }, [newDevis.lignes, newDevis.tauxTVA]); const handleSave = async () => { try { setSaving(true); // Validation if (!newDevis.numero || !newDevis.objet || !newDevis.client) { toast.current?.show({ severity: 'warn', summary: 'Attention', detail: 'Veuillez remplir tous les champs obligatoires' }); return; } const createdDevis = await devisService.create(newDevis); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Devis dupliqué avec succès' }); router.push(`/devis/${createdDevis.id}`); } catch (error) { console.error('Erreur lors de la duplication:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la duplication du devis' }); } finally { setSaving(false); } }; const toolbarStartTemplate = () => (
); const toolbarEndTemplate = () => (
); if (loading) { return (
); } if (!originalDevis) { return (

Devis introuvable

Le devis à dupliquer n'existe pas

); } return (
{/* Message d'information */}
{/* Comparaison Original vs Nouveau */}
Devis original

{originalDevis.numero}

{originalDevis.objet}

{formatCurrency(originalDevis.montantTTC)}

Nouveau devis

{newDevis.numero}

{newDevis.objet}

{formatCurrency(newDevis.montantTTC)}

{/* Informations du nouveau devis */}
setNewDevis(prev => ({ ...prev, numero: e.target.value }))} className="w-full" required />
setNewDevis(prev => ({ ...prev, objet: e.target.value }))} className="w-full" required />
{ const selectedClient = clients.find(c => c.id === e.value); setNewDevis(prev => ({ ...prev, client: selectedClient })); }} optionLabel="nom" optionValue="id" placeholder="Sélectionner un client" className="w-full" filter />
setNewDevis(prev => ({ ...prev, dateEmission: e.value?.toISOString() || new Date().toISOString() }))} className="w-full" dateFormat="dd/mm/yy" />
setNewDevis(prev => ({ ...prev, dateValidite: e.value?.toISOString() || new Date().toISOString() }))} className="w-full" dateFormat="dd/mm/yy" />

Brouillon (par défaut pour les nouveaux devis)

setNewDevis(prev => ({ ...prev, description: e.target.value }))} className="w-full" rows={4} />
{/* Prestations copiées */}
rowData.quantite?.toLocaleString('fr-FR')} /> formatCurrency(rowData.prixUnitaire)} /> formatCurrency(rowData.montantHT)} />

Les prestations ont été copiées depuis le devis original. Vous pourrez les modifier après la création du nouveau devis.

Total HT: {formatCurrency(newDevis.montantHT)} Total TTC: {formatCurrency(newDevis.montantTTC)}
); }; export default DuplicateDevisPage;