'use client'; import React, { useState, useEffect, useRef } from 'react'; import { Card } from 'primereact/card'; import { Button } from 'primereact/button'; import { Calendar } from 'primereact/calendar'; import { Dropdown } from 'primereact/dropdown'; import { MultiSelect } from 'primereact/multiselect'; import { Checkbox } from 'primereact/checkbox'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Toast } from 'primereact/toast'; import { ProgressBar } from 'primereact/progressbar'; import { Toolbar } from 'primereact/toolbar'; import { Tag } from 'primereact/tag'; import { Badge } from 'primereact/badge'; import { Divider } from 'primereact/divider'; import { factureService, clientService } from '../../../../services/api'; import { formatDate, formatCurrency } from '../../../../utils/formatters'; import type { Facture, Client } from '../../../../types/btp'; import { StatutFacture, TypeFacture } from '../../../../types/btp'; interface ExportConfig { format: string; dateDebut: Date; dateFin: Date; statuts: string[]; clients: Client[]; types: string[]; includeDetails: boolean; includeStatistiques: boolean; grouperParClient: boolean; grouperParMois: boolean; } const FactureExportPage = () => { const toast = useRef(null); const [factures, setFactures] = useState([]); const [clients, setClients] = useState([]); const [loading, setLoading] = useState(false); const [exporting, setExporting] = useState(false); const [exportProgress, setExportProgress] = useState(0); const [config, setConfig] = useState({ format: 'EXCEL', dateDebut: new Date(new Date().getFullYear(), 0, 1), dateFin: new Date(), statuts: [], clients: [], types: [], includeDetails: true, includeStatistiques: false, grouperParClient: false, grouperParMois: false }); const formatOptions = [ { label: 'Excel (.xlsx)', value: 'EXCEL', icon: 'pi pi-file-excel' }, { label: 'PDF', value: 'PDF', icon: 'pi pi-file-pdf' }, { label: 'CSV', value: 'CSV', icon: 'pi pi-file' }, { label: 'JSON', value: 'JSON', icon: 'pi pi-code' } ]; const statutOptions = [ { label: 'Brouillon', value: 'BROUILLON' }, { label: 'Envoyée', value: 'ENVOYEE' }, { label: 'Payée', value: 'PAYEE' }, { label: 'Partiellement payée', value: 'PARTIELLEMENT_PAYEE' }, { label: 'En retard', value: 'EN_RETARD' } ]; const typeOptions = [ { label: 'Facture', value: 'FACTURE' }, { label: 'Acompte', value: 'ACOMPTE' }, { label: 'Facture de situation', value: 'SITUATION' }, { label: 'Facture de solde', value: 'SOLDE' } ]; useEffect(() => { loadData(); }, []); useEffect(() => { loadFactures(); }, [config.dateDebut, config.dateFin, config.statuts, config.clients, config.types]); const loadData = async () => { try { setLoading(true); // Charger les clients const clientsResponse = await clientService.getAll(); setClients(clientsResponse); } catch (error) { console.error('Erreur lors du chargement:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les données' }); } finally { setLoading(false); } }; const loadFactures = async () => { try { setLoading(true); // TODO: Appel API avec filtres // const response = await factureService.getFiltered({ // dateDebut: config.dateDebut, // dateFin: config.dateFin, // statuts: config.statuts, // clients: config.clients.map(c => c.id), // types: config.types // }); // Données simulées pour la démonstration const mockFactures: Facture[] = [ { id: '1', numero: 'FAC-2024-001', objet: 'Rénovation salle de bain', typeFacture: TypeFacture.FACTURE, statut: StatutFacture.PAYEE, dateEmission: new Date('2024-01-15').toISOString(), dateEcheance: new Date('2024-02-15').toISOString(), client: { id: '1', nom: 'Dupont Construction' } as Client, montantHT: 2500, montantTTC: 3000, tauxTVA: 20, montantPaye: 3000 } as Facture, { id: '2', numero: 'FAC-2024-002', objet: 'Extension maison', typeFacture: TypeFacture.ACOMPTE, statut: StatutFacture.ENVOYEE, dateEmission: new Date('2024-02-01').toISOString(), dateEcheance: new Date('2024-03-01').toISOString(), client: { id: '2', nom: 'Martin SARL' } as Client, montantHT: 5000, montantTTC: 6000, tauxTVA: 20, montantPaye: 0 } as Facture, { id: '3', numero: 'FAC-2024-003', objet: 'Travaux électricité', typeFacture: TypeFacture.FACTURE, statut: StatutFacture.ECHUE, dateEmission: new Date('2024-01-20').toISOString(), dateEcheance: new Date('2024-02-20').toISOString(), client: { id: '3', nom: 'Bâti Plus' } as Client, montantHT: 1800, montantTTC: 2160, tauxTVA: 20, montantPaye: 0 } as Facture ]; // Appliquer les filtres let facturesFiltrees = mockFactures; if (config.statuts.length > 0) { facturesFiltrees = facturesFiltrees.filter(f => config.statuts.includes(f.statut)); } if (config.types.length > 0) { facturesFiltrees = facturesFiltrees.filter(f => config.types.includes(f.typeFacture)); } if (config.clients.length > 0) { const clientIds = config.clients.map(c => c.id); facturesFiltrees = facturesFiltrees.filter(f => typeof f.client === 'object' && clientIds.includes(f.client.id) ); } setFactures(facturesFiltrees); } catch (error) { console.error('Erreur lors du chargement des factures:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les factures' }); } finally { setLoading(false); } }; const handleExport = async () => { try { setExporting(true); setExportProgress(0); // Simulation du processus d'export const steps = [ 'Préparation des données...', 'Application des filtres...', 'Génération du fichier...', 'Finalisation...' ]; for (let i = 0; i < steps.length; i++) { await new Promise(resolve => setTimeout(resolve, 1000)); setExportProgress((i + 1) * 25); toast.current?.show({ severity: 'info', summary: 'Export en cours', detail: steps[i], life: 1000 }); } // TODO: Appel API réel pour l'export // const response = await factureService.export(config); // Simulation du téléchargement const filename = `factures_${formatDate(config.dateDebut)}_${formatDate(config.dateFin)}.${config.format.toLowerCase()}`; toast.current?.show({ severity: 'success', summary: 'Export terminé', detail: `Fichier ${filename} généré avec succès` }); // Simuler le téléchargement const link = document.createElement('a'); link.href = '#'; link.download = filename; link.click(); } catch (error) { console.error('Erreur lors de l\'export:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de l\'export' }); } finally { setExporting(false); setExportProgress(0); } }; const getStatutSeverity = (statut: string) => { switch (statut) { case 'PAYEE': return 'success'; case 'EN_RETARD': return 'danger'; case 'PARTIELLEMENT_PAYEE': return 'warning'; case 'ENVOYEE': return 'info'; case 'BROUILLON': return 'secondary'; default: return 'info'; } }; const calculateTotals = () => { const montantTotal = factures.reduce((sum, f) => sum + f.montantTTC, 0); const montantPaye = factures.reduce((sum, f) => sum + (f.montantPaye || 0), 0); const montantEnAttente = montantTotal - montantPaye; return { montantTotal, montantPaye, montantEnAttente }; }; const totals = calculateTotals(); const toolbarStartTemplate = () => (

Export des Factures

); const toolbarEndTemplate = () => (
); return (
{/* Configuration de l'export */}
setConfig(prev => ({ ...prev, format: e.value }))} className="w-full" itemTemplate={(option) => (
{option.label}
)} />
setConfig(prev => ({ ...prev, dateDebut: e.value?.toISOString() || new Date().toISOString() }))} className="w-full" dateFormat="dd/mm/yy" />
setConfig(prev => ({ ...prev, dateFin: e.value?.toISOString() || new Date().toISOString() }))} className="w-full" dateFormat="dd/mm/yy" />
setConfig(prev => ({ ...prev, statuts: e.value }))} className="w-full" placeholder="Tous les statuts" maxSelectedLabels={2} />
setConfig(prev => ({ ...prev, types: e.value }))} className="w-full" placeholder="Tous les types" maxSelectedLabels={2} />
({ label: client.nom, value: client }))} onChange={(e) => setConfig(prev => ({ ...prev, clients: e.value }))} className="w-full" placeholder="Tous les clients" maxSelectedLabels={2} filter />
Options d'export
setConfig(prev => ({ ...prev, includeDetails: e.checked || false }))} />
setConfig(prev => ({ ...prev, includeStatistiques: e.checked || false }))} />
setConfig(prev => ({ ...prev, grouperParClient: e.checked || false }))} />
setConfig(prev => ({ ...prev, grouperParMois: e.checked || false }))} />
{/* Aperçu des données */}
{exporting && (
Export en cours... {exportProgress}%
)} Factures sélectionnées
} > ( )} /> ( )} /> typeof rowData.client === 'string' ? rowData.client : rowData.client?.nom } /> formatDate(rowData.dateEmission)} sortable /> formatCurrency(rowData.montantTTC)} sortable />
{/* Résumé financier */}
{factures.length}
Factures
{formatCurrency(totals.montantTotal)}
Montant Total
{formatCurrency(totals.montantPaye)}
Montant Payé
{formatCurrency(totals.montantEnAttente)}
En Attente
); }; export default FactureExportPage;