112 lines
3.8 KiB
JavaScript
112 lines
3.8 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { api } from '../stores/api';
|
|
import PageHeader from '../components/PageHeader';
|
|
|
|
const STATUTS = {
|
|
en_attente: { label: 'En attente', bg: 'bg-yellow-100', text: 'text-yellow-800', emoji: '⏳' },
|
|
en_cours: { label: 'En cours', bg: 'bg-blue-100', text: 'text-blue-800', emoji: '🔄' },
|
|
complete: { label: 'Complété', bg: 'bg-green-100', text: 'text-green-800', emoji: '✓' },
|
|
};
|
|
|
|
function Badge({ statut }) {
|
|
const s = STATUTS[statut] || STATUTS.en_attente;
|
|
return (
|
|
<span className={`inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-bold ${s.bg} ${s.text}`}>
|
|
{s.emoji} {s.label}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export default function Decisions() {
|
|
const [decisions, setDecisions] = useState([]);
|
|
const [filtre, setFiltre] = useState('ouvertes'); // ouvertes | toutes
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
const charger = async () => {
|
|
setLoading(true);
|
|
try {
|
|
let url = '/decisions/';
|
|
if (filtre === 'ouvertes') {
|
|
// Charger en_attente et en_cours
|
|
const [att, enc] = await Promise.all([
|
|
api.get('/decisions/?statut=en_attente'),
|
|
api.get('/decisions/?statut=en_cours'),
|
|
]);
|
|
setDecisions([...enc, ...att]);
|
|
} else {
|
|
const data = await api.get(url);
|
|
setDecisions(data);
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
setLoading(false);
|
|
};
|
|
|
|
useEffect(() => { charger(); }, [filtre]);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-100">
|
|
<PageHeader titre="Décisions en cours" sousTitre="C5 — Suivi réunion d'affaires" />
|
|
|
|
{/* Filtres */}
|
|
<div className="p-4 pb-0">
|
|
<div className="flex gap-2">
|
|
{[
|
|
{ key: 'ouvertes', label: 'Ouvertes' },
|
|
{ key: 'toutes', label: 'Toutes' },
|
|
].map((f) => (
|
|
<button
|
|
key={f.key}
|
|
onClick={() => setFiltre(f.key)}
|
|
className={`px-4 py-2 rounded-full text-sm font-bold transition ${
|
|
filtre === f.key
|
|
? 'bg-aa-blue text-white'
|
|
: 'bg-white text-gray-600 border border-gray-200'
|
|
}`}
|
|
>
|
|
{f.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Liste */}
|
|
<div className="p-4 space-y-3">
|
|
{loading ? (
|
|
<p className="text-center text-gray-400 py-8">Chargement...</p>
|
|
) : decisions.length === 0 ? (
|
|
<div className="text-center py-12">
|
|
<p className="text-4xl mb-2">📌</p>
|
|
<p className="text-gray-500">Aucune décision {filtre === 'ouvertes' ? 'ouverte' : ''}</p>
|
|
</div>
|
|
) : (
|
|
decisions.map((d) => (
|
|
<div key={d.id} className="bg-white rounded-2xl p-4 shadow-sm">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex-1">
|
|
<p className="font-bold text-gray-800">{d.sujet}</p>
|
|
{d.description && (
|
|
<p className="text-sm text-gray-500 mt-1">{d.description}</p>
|
|
)}
|
|
<div className="flex flex-wrap items-center gap-2 mt-2">
|
|
<Badge statut={d.statut} />
|
|
{d.responsable_prenom && (
|
|
<span className="text-xs text-gray-400">→ {d.responsable_prenom}</span>
|
|
)}
|
|
<span className="text-xs text-gray-300">{d.date_decision}</span>
|
|
</div>
|
|
{d.proposeur && (
|
|
<p className="text-xs text-gray-400 mt-1">
|
|
Proposé par {d.proposeur}{d.secondeur ? `, secondé par ${d.secondeur}` : ''}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|