'use client'; import React, { useState, useEffect, useRef } from 'react'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Button } from 'primereact/button'; import { InputText } from 'primereact/inputtext'; import { Card } from 'primereact/card'; import { Toast } from 'primereact/toast'; import { Toolbar } from 'primereact/toolbar'; import { Tag } from 'primereact/tag'; import { Dialog } from 'primereact/dialog'; import { Dropdown } from 'primereact/dropdown'; import { InputTextarea } from 'primereact/inputtextarea'; import { ProgressBar } from 'primereact/progressbar'; import { devisService } from '../../../../services/api'; import { formatDate, formatCurrency } from '../../../../utils/formatters'; import type { Devis } from '../../../../types/btp'; import { StatutDevis } from '../../../../types/btp'; const DevisAttentePage = () => { const [devis, setDevis] = useState([]); const [loading, setLoading] = useState(true); const [globalFilter, setGlobalFilter] = useState(''); const [selectedDevis, setSelectedDevis] = useState([]); const [actionDialog, setActionDialog] = useState(false); const [selectedDevisItem, setSelectedDevisItem] = useState(null); const [actionType, setActionType] = useState<'accept' | 'refuse' | 'send' | 'extend'>('send'); const [actionNotes, setActionNotes] = useState(''); const toast = useRef(null); const dt = useRef>(null); useEffect(() => { loadDevis(); }, []); const loadDevis = async () => { try { setLoading(true); const data = await devisService.getAll(); // Filtrer les devis en attente (brouillon ou envoyé) const devisEnAttente = data.filter(devis => devis.statut === 'BROUILLON' || devis.statut === 'ENVOYE' ); setDevis(devisEnAttente); } catch (error) { console.error('Erreur lors du chargement des devis:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les devis en attente', life: 3000 }); } finally { setLoading(false); } }; const getDaysUntilExpiry = (dateValidite: string | Date) => { const today = new Date(); const validityDate = new Date(dateValidite); const diffTime = validityDate.getTime() - today.getTime(); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); return diffDays; }; const isExpiringSoon = (dateValidite: string | Date) => { const days = getDaysUntilExpiry(dateValidite); return days >= 0 && days <= 7; // Expire dans les 7 prochains jours }; const isExpired = (dateValidite: string | Date) => { const days = getDaysUntilExpiry(dateValidite); return days < 0; }; const getUrgencyLevel = (dateValidite: string | Date) => { const days = getDaysUntilExpiry(dateValidite); if (days < 0) return { level: 'EXPIRÉ', color: 'red', severity: 'danger' as const }; if (days <= 3) return { level: 'URGENT', color: 'red', severity: 'danger' as const }; if (days <= 7) return { level: 'BIENTÔT', color: 'orange', severity: 'warning' as const }; return { level: 'NORMAL', color: 'green', severity: 'success' as const }; }; const sendDevis = (devisItem: Devis) => { setSelectedDevisItem(devisItem); setActionType('send'); setActionNotes(''); setActionDialog(true); }; const acceptDevis = (devisItem: Devis) => { setSelectedDevisItem(devisItem); setActionType('accept'); setActionNotes(''); setActionDialog(true); }; const refuseDevis = (devisItem: Devis) => { setSelectedDevisItem(devisItem); setActionType('refuse'); setActionNotes(''); setActionDialog(true); }; const extendValidité = (devisItem: Devis) => { setSelectedDevisItem(devisItem); setActionType('extend'); setActionNotes(''); setActionDialog(true); }; const handleAction = async () => { if (!selectedDevisItem) return; try { let newStatut = selectedDevisItem.statut; let message = ''; switch (actionType) { case 'send': newStatut = StatutDevis.ENVOYE; message = 'Devis envoyé au client'; break; case 'accept': newStatut = StatutDevis.ACCEPTE; message = 'Devis accepté par le client'; break; case 'refuse': newStatut = StatutDevis.REFUSE; message = 'Devis refusé par le client'; break; case 'extend': // Prolonger la validité de 30 jours const newValidityDate = new Date(selectedDevisItem.dateValidite); newValidityDate.setDate(newValidityDate.getDate() + 30); // Pour cette démo, on simule juste le message message = 'Validité du devis prolongée de 30 jours'; break; } // TODO: Implémenter quand l'API backend sera disponible console.log(`Action ${actionType} sur devis ${selectedDevisItem.numero}:`, { nouveauStatut: newStatut, notes: actionNotes }); // Simulation de succès if (actionType === 'accept' || actionType === 'refuse') { // Retirer le devis de la liste car il n'est plus en attente setDevis(prev => prev.filter(d => d.id !== selectedDevisItem.id)); } setActionDialog(false); toast.current?.show({ severity: 'success', summary: 'Succès', detail: `${message} (simulation)`, life: 3000 }); } catch (error) { console.error('Erreur lors de l\'action:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible d\'effectuer l\'action', life: 3000 }); } }; const exportCSV = () => { dt.current?.exportCSV(); }; const bulkSend = async () => { if (selectedDevis.length === 0) { toast.current?.show({ severity: 'warn', summary: 'Attention', detail: 'Veuillez sélectionner au moins un devis', life: 3000 }); return; } // Simulation d'envoi en lot console.log('Envoi en lot de', selectedDevis.length, 'devis'); setSelectedDevis([]); toast.current?.show({ severity: 'success', summary: 'Succès', detail: `${selectedDevis.length} devis envoyé(s) (simulation)`, life: 3000 }); }; const generateFollowUpReport = () => { const urgent = devis.filter(d => getUrgencyLevel(d.dateValidite).level === 'URGENT'); const expiringSoon = devis.filter(d => getUrgencyLevel(d.dateValidite).level === 'BIENTÔT'); const expired = devis.filter(d => getUrgencyLevel(d.dateValidite).level === 'EXPIRÉ'); const report = ` === RAPPORT DE SUIVI DEVIS EN ATTENTE === Date du rapport: ${new Date().toLocaleDateString('fr-FR')} DEVIS URGENTS (${urgent.length}): ${urgent.map(d => ` - ${d.numero} - ${d.objet} Client: ${d.client ? `${d.client.prenom} ${d.client.nom}` : 'N/A'} Montant: ${formatCurrency(d.montantTTC || 0)} Expire: ${formatDate(d.dateValidite)} `).join('')} DEVIS EXPIRANT BIENTÔT (${expiringSoon.length}): ${expiringSoon.map(d => ` - ${d.numero} - ${d.objet} Client: ${d.client ? `${d.client.prenom} ${d.client.nom}` : 'N/A'} Montant: ${formatCurrency(d.montantTTC || 0)} Expire: ${formatDate(d.dateValidite)} `).join('')} DEVIS EXPIRÉS (${expired.length}): ${expired.map(d => ` - ${d.numero} - ${d.objet} Client: ${d.client ? `${d.client.prenom} ${d.client.nom}` : 'N/A'} Montant: ${formatCurrency(d.montantTTC || 0)} Expiré: ${formatDate(d.dateValidite)} `).join('')} STATISTIQUES: - Total devis en attente: ${devis.length} - Montant total en attente: ${formatCurrency(devis.reduce((sum, d) => sum + (d.montantTTC || 0), 0))} - Taux d'urgence: ${Math.round(((urgent.length + expiringSoon.length) / devis.length) * 100)}% `; const blob = new Blob([report], { type: 'text/plain;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `suivi_devis_attente_${new Date().toISOString().split('T')[0]}.txt`; link.click(); toast.current?.show({ severity: 'success', summary: 'Rapport généré', detail: 'Le rapport de suivi a été téléchargé', life: 3000 }); }; const leftToolbarTemplate = () => { return (
Devis en attente ({devis.length})
); }; const rightToolbarTemplate = () => { return (