Initial commit
This commit is contained in:
137
components/dashboard/AlertsWidget.tsx
Normal file
137
components/dashboard/AlertsWidget.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Composant widget d'alertes (factures en retard, devis expirant)
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Card } from 'primereact/card';
|
||||
import { Message } from 'primereact/message';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Skeleton } from 'primereact/skeleton';
|
||||
import { FactureEnRetard, DevisEnAttente } from '../../types/btp';
|
||||
|
||||
interface AlertsWidgetProps {
|
||||
facturesEnRetard: FactureEnRetard[];
|
||||
devisEnAttente: DevisEnAttente[];
|
||||
loading?: boolean;
|
||||
onViewFacture?: (id: string) => void;
|
||||
onViewDevis?: (id: string) => void;
|
||||
}
|
||||
|
||||
const AlertsWidget: React.FC<AlertsWidgetProps> = ({
|
||||
facturesEnRetard,
|
||||
devisEnAttente,
|
||||
loading = false,
|
||||
onViewFacture,
|
||||
onViewDevis
|
||||
}) => {
|
||||
const getAlertSeverity = (jours: number) => {
|
||||
if (jours <= 3) return 'warn';
|
||||
if (jours <= 7) return 'info';
|
||||
return 'error';
|
||||
};
|
||||
|
||||
const header = (
|
||||
<div className="flex align-items-center">
|
||||
<i className="pi pi-exclamation-triangle text-orange-500 mr-2" />
|
||||
<h5 className="m-0">Alertes</h5>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex align-items-center mb-3">
|
||||
<Skeleton width="1.5rem" height="1.5rem" className="mr-2" />
|
||||
<Skeleton width="4rem" height="1.5rem" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{[...Array(3)].map((_, i) => (
|
||||
<div key={i} className="p-3 border-1 border-200 border-round">
|
||||
<Skeleton width="100%" height="1rem" className="mb-2" />
|
||||
<Skeleton width="60%" height="0.8rem" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const hasAlerts = facturesEnRetard.length > 0 || devisEnAttente.length > 0;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex align-items-center mb-3">
|
||||
<i className="pi pi-exclamation-triangle text-orange-500 mr-2" />
|
||||
<h5 className="m-0">Alertes</h5>
|
||||
</div>
|
||||
|
||||
{!hasAlerts ? (
|
||||
<Message
|
||||
severity="success"
|
||||
text="Aucune alerte pour le moment"
|
||||
className="w-full"
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{/* Factures en retard */}
|
||||
{facturesEnRetard.map((facture) => (
|
||||
<div
|
||||
key={facture.id}
|
||||
className="flex align-items-center justify-content-between p-3 border-1 border-red-200 border-round bg-red-50"
|
||||
>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-900 mb-1">
|
||||
Facture {facture.numero} en retard
|
||||
</div>
|
||||
<div className="text-500 text-sm">
|
||||
{facture.client} • {facture.montantTTC.toLocaleString()} € •
|
||||
{facture.joursRetard} jour{facture.joursRetard > 1 ? 's' : ''} de retard
|
||||
</div>
|
||||
</div>
|
||||
{onViewFacture && (
|
||||
<Button
|
||||
icon="pi pi-eye"
|
||||
className="p-button-text p-button-sm"
|
||||
onClick={() => onViewFacture(facture.id)}
|
||||
tooltip="Voir la facture"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Devis expirant bientôt */}
|
||||
{devisEnAttente.map((devis) => (
|
||||
<div
|
||||
key={devis.id}
|
||||
className={`flex align-items-center justify-content-between p-3 border-1 border-round ${
|
||||
devis.joursRestants <= 3
|
||||
? 'border-red-200 bg-red-50'
|
||||
: 'border-orange-200 bg-orange-50'
|
||||
}`}
|
||||
>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium text-900 mb-1">
|
||||
Devis {devis.numero} expire bientôt
|
||||
</div>
|
||||
<div className="text-500 text-sm">
|
||||
{devis.client} • {devis.montantTTC.toLocaleString()} € •
|
||||
{devis.joursRestants} jour{devis.joursRestants > 1 ? 's' : ''} restant{devis.joursRestants > 1 ? 's' : ''}
|
||||
</div>
|
||||
</div>
|
||||
{onViewDevis && (
|
||||
<Button
|
||||
icon="pi pi-eye"
|
||||
className="p-button-text p-button-sm"
|
||||
onClick={() => onViewDevis(devis.id)}
|
||||
tooltip="Voir le devis"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default AlertsWidget;
|
||||
Reference in New Issue
Block a user