'use client'; import React, { useState, useEffect, useRef } from 'react'; import { Card } from 'primereact/card'; import { Chart } from 'primereact/chart'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Button } from 'primereact/button'; import { Calendar } from 'primereact/calendar'; import { Dropdown } from 'primereact/dropdown'; import { Tag } from 'primereact/tag'; import { ProgressBar } from 'primereact/progressbar'; import { Toast } from 'primereact/toast'; import { Toolbar } from 'primereact/toolbar'; import { Badge } from 'primereact/badge'; import { factureService } from '../../../../services/api'; import { formatCurrency, formatDate } from '../../../../utils/formatters'; interface FactureStats { totalFactures: number; chiffreAffaires: number; montantEnAttente: number; montantEnRetard: number; tauxRecouvrement: number; delaiMoyenPaiement: number; repartitionStatuts: { [key: string]: number }; evolutionMensuelle: Array<{ mois: string; emises: number; payees: number; montantEmis: number; montantPaye: number }>; topClients: Array<{ client: string; nombre: number; montant: number; montantPaye: number }>; retardsParClient: Array<{ client: string; factures: number; montant: number; retardMoyen: number }>; } const FactureStatsPage = () => { const toast = useRef(null); const [stats, setStats] = useState({ totalFactures: 0, chiffreAffaires: 0, montantEnAttente: 0, montantEnRetard: 0, tauxRecouvrement: 0, delaiMoyenPaiement: 0, repartitionStatuts: {}, evolutionMensuelle: [], topClients: [], retardsParClient: [] }); const [loading, setLoading] = useState(true); const [dateDebut, setDateDebut] = useState(new Date(new Date().getFullYear(), 0, 1)); const [dateFin, setDateFin] = useState(new Date()); const [periodeSelectionnee, setPeriodeSelectionnee] = useState('annee'); const periodeOptions = [ { label: 'Cette année', value: 'annee' }, { label: 'Ce trimestre', value: 'trimestre' }, { label: 'Ce mois', value: 'mois' }, { label: 'Personnalisée', value: 'custom' } ]; useEffect(() => { loadStats(); }, [dateDebut, dateFin]); const loadStats = async () => { try { setLoading(true); // TODO: Remplacer par un vrai appel API // const response = await factureService.getStatistiques(dateDebut, dateFin); // Données simulées pour la démonstration const mockStats: FactureStats = { totalFactures: 234, chiffreAffaires: 3250000, montantEnAttente: 485000, montantEnRetard: 125000, tauxRecouvrement: 87.5, delaiMoyenPaiement: 28.5, repartitionStatuts: { 'PAYEE': 156, 'ENVOYEE': 45, 'EN_RETARD': 18, 'PARTIELLEMENT_PAYEE': 12, 'BROUILLON': 3 }, evolutionMensuelle: [ { mois: 'Jan', emises: 18, payees: 15, montantEmis: 285000, montantPaye: 240000 }, { mois: 'Fév', emises: 22, payees: 19, montantEmis: 340000, montantPaye: 295000 }, { mois: 'Mar', emises: 25, payees: 22, montantEmis: 395000, montantPaye: 350000 }, { mois: 'Avr', emises: 20, payees: 18, montantEmis: 315000, montantPaye: 285000 }, { mois: 'Mai', emises: 28, payees: 24, montantEmis: 445000, montantPaye: 380000 }, { mois: 'Jun', emises: 24, payees: 21, montantEmis: 375000, montantPaye: 320000 }, { mois: 'Jul', emises: 30, payees: 26, montantEmis: 485000, montantPaye: 420000 }, { mois: 'Aoû', emises: 26, payees: 23, montantEmis: 410000, montantPaye: 365000 }, { mois: 'Sep', emises: 29, payees: 25, montantEmis: 465000, montantPaye: 395000 } ], topClients: [ { client: 'Bouygues Construction', nombre: 12, montant: 680000, montantPaye: 620000 }, { client: 'Vinci Construction', nombre: 9, montant: 520000, montantPaye: 485000 }, { client: 'Eiffage', nombre: 8, montant: 445000, montantPaye: 445000 }, { client: 'Spie Batignolles', nombre: 6, montant: 385000, montantPaye: 320000 }, { client: 'GTM Bâtiment', nombre: 5, montant: 295000, montantPaye: 295000 } ], retardsParClient: [ { client: 'Constructa SARL', factures: 3, montant: 85000, retardMoyen: 45 }, { client: 'Bâti Plus', factures: 2, montant: 65000, retardMoyen: 38 }, { client: 'Rénov Express', factures: 4, montant: 125000, retardMoyen: 32 }, { client: 'Maisons du Sud', factures: 1, montant: 35000, retardMoyen: 28 } ] }; setStats(mockStats); } catch (error) { console.error('Erreur lors du chargement des statistiques:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les statistiques' }); } finally { setLoading(false); } }; const handlePeriodeChange = (periode: string) => { setPeriodeSelectionnee(periode); const now = new Date(); switch (periode) { case 'annee': setDateDebut(new Date(now.getFullYear(), 0, 1)); setDateFin(new Date()); break; case 'trimestre': const trimestre = Math.floor(now.getMonth() / 3); setDateDebut(new Date(now.getFullYear(), trimestre * 3, 1)); setDateFin(new Date()); break; case 'mois': setDateDebut(new Date(now.getFullYear(), now.getMonth(), 1)); setDateFin(new Date()); break; } }; // Configuration des graphiques const chartOptions = { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' as const } }, scales: { y: { beginAtZero: true } } }; const evolutionData = { labels: stats.evolutionMensuelle.map(item => item.mois), datasets: [ { label: 'Factures émises', data: stats.evolutionMensuelle.map(item => item.emises), borderColor: '#3B82F6', backgroundColor: 'rgba(59, 130, 246, 0.1)', yAxisID: 'y' }, { label: 'Factures payées', data: stats.evolutionMensuelle.map(item => item.payees), borderColor: '#10B981', backgroundColor: 'rgba(16, 185, 129, 0.1)', yAxisID: 'y' } ] }; const chiffreAffairesData = { labels: stats.evolutionMensuelle.map(item => item.mois), datasets: [ { label: 'CA émis (k€)', data: stats.evolutionMensuelle.map(item => item.montantEmis / 1000), backgroundColor: 'rgba(59, 130, 246, 0.8)' }, { label: 'CA encaissé (k€)', data: stats.evolutionMensuelle.map(item => item.montantPaye / 1000), backgroundColor: 'rgba(16, 185, 129, 0.8)' } ] }; const repartitionData = { labels: Object.keys(stats.repartitionStatuts), datasets: [{ data: Object.values(stats.repartitionStatuts), backgroundColor: [ '#10B981', // PAYEE - vert '#3B82F6', // ENVOYEE - bleu '#EF4444', // EN_RETARD - rouge '#F59E0B', // PARTIELLEMENT_PAYEE - orange '#6B7280' // BROUILLON - gris ] }] }; 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 toolbarStartTemplate = () => (

Statistiques des Factures

); const toolbarEndTemplate = () => (
handlePeriodeChange(e.value)} className="w-10rem" /> {periodeSelectionnee === 'custom' && ( <> setDateDebut(e.value || new Date())} placeholder="Date début" dateFormat="dd/mm/yy" /> setDateFin(e.value || new Date())} placeholder="Date fin" dateFormat="dd/mm/yy" /> )}
); return (
{/* KPIs principaux */}
Total Factures
{stats.totalFactures}
+15% vs période précédente
Chiffre d'Affaires
{formatCurrency(stats.chiffreAffaires)}
+12% vs période précédente
Taux de Recouvrement
{stats.tauxRecouvrement}%
Délai Moyen Paiement
{stats.delaiMoyenPaiement} jours
+2.5j vs période précédente
{/* Alertes financières */}
Alertes Financières
Factures en retard

{formatCurrency(stats.montantEnRetard)} à recouvrer

En attente de paiement

{formatCurrency(stats.montantEnAttente)} en cours

{/* Graphiques d'évolution */}
{/* Top clients */}
(
{rowData.client}
)} /> formatCurrency(rowData.montant)} /> ( 0.9 ? 'success' : 'warning'} /> )} />
{/* Clients en retard */}
formatCurrency(rowData.montant)} /> ( 30 ? 'danger' : 'warning'} /> )} />
{/* Analyse et recommandations */}
Performance
  • • CA en croissance de 12%
  • • Taux de recouvrement à 87.5%
  • • 234 factures émises
Points d'attention
  • • {formatCurrency(stats.montantEnRetard)} en retard
  • • Délai moyen en hausse (+2.5j)
  • • 18 factures en retard
Actions recommandées
  • • Relancer les impayés
  • • Revoir les conditions de paiement
  • • Mettre en place des acomptes
); }; export default FactureStatsPage;