'use client'; import React, { useState, useEffect } from 'react'; import { useNotification } from './NotificationProvider'; import Link from 'next/link'; interface HistoriqueItem { id: string; date: string; adherentNom: string; montant: number; } interface PrescripteurBudget { id: string; value: string; montant: number; consommé: number; restant: number; ajustementConsomme: number; historique: HistoriqueItem[]; } interface BudgetData { global: { totalAlloue: number; totalConsomme: number; totalRestant: number; }; prescripteurs: PrescripteurBudget[]; } export default function BudgetContent() { const { showNotification } = useNotification(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [savingId, setSavingId] = useState(null); const [addModalPrescripteur, setAddModalPrescripteur] = useState(null); const [addAmount, setAddAmount] = useState(''); const [rectifierModalPrescripteur, setRectifierModalPrescripteur] = useState(null); const [rectifierBudget, setRectifierBudget] = useState(''); const [rectifierAjustement, setRectifierAjustement] = useState(''); const [expandedPrescripteur, setExpandedPrescripteur] = useState(null); useEffect(() => { fetchBudgets(); }, []); const fetchBudgets = async () => { setLoading(true); try { const response = await fetch('/api/budget'); if (response.ok) { const res = await response.json(); setData(res); } else { showNotification('error', 'Erreur lors du chargement des budgets'); } } catch { showNotification('error', 'Erreur lors du chargement des budgets'); } finally { setLoading(false); } }; const handleAddMoney = async () => { if (!addModalPrescripteur) return; const raw = addAmount.replace(',', '.'); const montantToAdd = parseFloat(raw); if (isNaN(montantToAdd) || montantToAdd <= 0) { showNotification('error', 'Montant invalide'); return; } setSavingId(addModalPrescripteur); try { const response = await fetch('/api/budget', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prescripteurValue: addModalPrescripteur, montantToAdd }), }); if (response.ok) { showNotification('success', 'Budget mis à jour'); setAddModalPrescripteur(null); setAddAmount(''); fetchBudgets(); } else { const res = await response.json(); showNotification('error', res.error || "Erreur lors de l'ajout"); } } catch { showNotification('error', "Erreur lors de l'ajout"); } finally { setSavingId(null); } }; const handleRectifier = async () => { if (!rectifierModalPrescripteur) return; const montant = parseFloat(rectifierBudget.replace(',', '.')); const ajustement = parseFloat(rectifierAjustement.replace(',', '.')); if (isNaN(montant) || montant < 0) { showNotification('error', 'Budget invalide'); return; } setSavingId(rectifierModalPrescripteur.value); try { const response = await fetch('/api/budget', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prescripteurValue: rectifierModalPrescripteur.value, rectifier: true, montant, ajustementConsomme: isNaN(ajustement) ? 0 : ajustement, }), }); if (response.ok) { showNotification('success', 'Corrections enregistrées'); setRectifierModalPrescripteur(null); setRectifierBudget(''); setRectifierAjustement(''); fetchBudgets(); } else { const res = await response.json(); showNotification('error', res.error || 'Erreur lors de la correction'); } } catch { showNotification('error', 'Erreur lors de la correction'); } finally { setSavingId(null); } }; const formatEuro = (n: number) => n.toFixed(2).replace('.', ',') + ' €'; const formatDate = (dateStr: string) => { return new Date(dateStr).toLocaleDateString('fr-FR', { day: '2-digit', month: 'short', year: 'numeric', }); }; if (loading) { return (
Chargement...
); } if (!data || data.prescripteurs.length === 0) { return (

Aucun prescripteur configuré.

Ajoutez des prescripteurs dans la configuration pour pouvoir définir leurs budgets.

Aller à la configuration
); } const { global, prescripteurs } = data; return (
{/* Blocs budget global - style dashboard */}

Budget total alloué

{formatEuro(global.totalAlloue)}

Budget consommé

{formatEuro(global.totalConsomme)}

Budget restant

{formatEuro(global.totalRestant)}

{/* Liste des budgets par prescripteur */}

Budget par prescripteur

Cliquez sur un prescripteur pour voir l'historique. Utilisez « Ajouter » pour créditer le budget.

{/* Vue desktop - Tableau */}
{prescripteurs.map((item) => ( setExpandedPrescripteur(expandedPrescripteur === item.value ? null : item.value)} > {expandedPrescripteur === item.value && item.historique.length > 0 && ( )} {expandedPrescripteur === item.value && item.historique.length === 0 && ( )} ))}
Prescripteur Consommé Restant Actions
{item.value} {item.historique.length > 0 && ( )}
{formatEuro(item.consommé)} item.montant || (item.montant > 0 && item.restant < item.montant * 0.2) ? 'text-red-600' : 'text-lgreen' }`} > {formatEuro(item.restant)} e.stopPropagation()}>

Historique des participations

{item.historique.map((h) => ( ))}
Date Adhérent Montant Lien
{formatDate(h.date)} {h.adherentNom} {formatEuro(h.montant)} Voir

Aucune participation enregistrée pour ce prescripteur.

{/* Vue mobile - Cartes */}
{prescripteurs.map((item) => (
e.stopPropagation()}>
{expandedPrescripteur === item.value && item.historique.length > 0 && (

Historique

{item.historique.map((h) => (

{h.adherentNom}

{formatDate(h.date)}

{formatEuro(h.montant)} Voir
))}
)} {expandedPrescripteur === item.value && item.historique.length === 0 && (

Aucune participation enregistrée.

)}
))}

Les prescripteurs sont définis dans{' '} Paramètres → Configuration .

{/* Modal Rectifier */} {rectifierModalPrescripteur && (
{ setRectifierModalPrescripteur(null); setRectifierBudget(''); setRectifierAjustement(''); }} >
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="rectifier-budget-title" >

Rectifier — {rectifierModalPrescripteur.value}

Corrigez le budget alloué et/ou l'ajustement du consommé en cas d'erreur.

setRectifierBudget(e.target.value.replace(/[^0-9.,]/g, ''))} placeholder="0,00" className="flex-1 px-4 py-2.5 text-sm text-gray-900 border border-gray-300 rounded-lg focus:ring-2 focus:ring-lblue focus:border-transparent" />

Valeur à ajouter au consommé calculé. Négatif pour diminuer (ex: -6,80).

setRectifierAjustement(e.target.value.replace(/[^0-9.,-]/g, ''))} placeholder="0,00" className="flex-1 px-4 py-2.5 text-sm text-gray-900 border border-gray-300 rounded-lg focus:ring-2 focus:ring-lblue focus:border-transparent" />
)} {/* Modal Ajouter de l'argent */} {addModalPrescripteur && (
{ setAddModalPrescripteur(null); setAddAmount(''); }} >
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="add-budget-title" >

Ajouter du budget — {addModalPrescripteur}

Entrez le montant à ajouter au budget existant.

setAddAmount(e.target.value.replace(/[^0-9.,]/g, ''))} placeholder="0,00" className="flex-1 px-4 py-2.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-lblue focus:border-transparent" autoFocus />
)}
); }