2026-03-04 14:01:00 -05:00
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
|
|
import { api } from '../stores/api';
|
2026-05-25 17:39:38 -04:00
|
|
|
import { useStore } from '../stores/store';
|
2026-03-04 14:01:00 -05:00
|
|
|
import PageHeader from '../components/PageHeader';
|
|
|
|
|
|
|
|
|
|
const STATUTS = {
|
2026-05-25 17:39:38 -04:00
|
|
|
proposee: { label: 'À seconder', cls: 'bg-yellow-100 text-yellow-700' },
|
|
|
|
|
secondee: { label: 'Secondée', cls: 'bg-blue-100 text-blue-700' },
|
|
|
|
|
adoptee: { label: 'Résolution', cls: 'bg-green-100 text-green-700' },
|
|
|
|
|
rejetee: { label: 'Rejetée', cls: 'bg-red-100 text-red-700' },
|
2026-03-04 14:01:00 -05:00
|
|
|
};
|
|
|
|
|
|
2026-05-25 17:39:38 -04:00
|
|
|
const TYPES = {
|
|
|
|
|
proposition: 'Proposition',
|
|
|
|
|
resolution: 'Résolution',
|
|
|
|
|
generale: 'Résolution',
|
|
|
|
|
nomination: 'Nomination',
|
|
|
|
|
contribution: 'Contribution',
|
|
|
|
|
};
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
export default function Decisions() {
|
2026-05-31 09:15:12 -04:00
|
|
|
const { estExecutif } = useStore();
|
2026-05-25 17:39:38 -04:00
|
|
|
const [propositions, setPropositions] = useState([]);
|
|
|
|
|
const [resolutions, setResolutions] = useState([]);
|
2026-05-26 08:15:28 -04:00
|
|
|
const [membres, setMembres] = useState([]);
|
2026-05-25 17:39:38 -04:00
|
|
|
const [tab, setTab] = useState('cours');
|
2026-03-04 14:01:00 -05:00
|
|
|
const [loading, setLoading] = useState(true);
|
2026-05-25 17:39:38 -04:00
|
|
|
const [error, setError] = useState('');
|
|
|
|
|
const [msg, setMsg] = useState('');
|
|
|
|
|
|
|
|
|
|
const [sujet, setSujet] = useState('');
|
|
|
|
|
const [description, setDescription] = useState('');
|
|
|
|
|
const [resolutionForm, setResolutionForm] = useState({});
|
2026-05-26 08:15:28 -04:00
|
|
|
const [seconderPour, setSeconderPour] = useState({});
|
|
|
|
|
const [decisionOuverte, setDecisionOuverte] = useState(null);
|
2026-05-25 17:39:38 -04:00
|
|
|
|
2026-05-31 09:15:12 -04:00
|
|
|
const peutExecutif = estExecutif;
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
const charger = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
2026-05-26 08:15:28 -04:00
|
|
|
const [props, res, membresActifs] = await Promise.all([
|
2026-05-25 17:39:38 -04:00
|
|
|
api.get('/propositions/?limite=100'),
|
|
|
|
|
api.get('/propositions/resolutions'),
|
2026-05-26 08:15:28 -04:00
|
|
|
api.get('/membres/actifs'),
|
2026-05-25 17:39:38 -04:00
|
|
|
]);
|
|
|
|
|
setPropositions(props);
|
|
|
|
|
setResolutions(res);
|
2026-05-26 08:15:28 -04:00
|
|
|
setMembres(membresActifs);
|
2026-05-25 17:39:38 -04:00
|
|
|
} catch (e) { setError(e.message); }
|
2026-03-04 14:01:00 -05:00
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-25 17:39:38 -04:00
|
|
|
useEffect(() => { charger(); }, []);
|
|
|
|
|
|
|
|
|
|
const flash = (m) => { setMsg(m); setTimeout(() => setMsg(''), 2500); };
|
|
|
|
|
|
|
|
|
|
const soumettre = async () => {
|
2026-05-26 08:15:28 -04:00
|
|
|
if (!sujet.trim()) { setError("L'objet est obligatoire"); return; }
|
2026-05-25 17:39:38 -04:00
|
|
|
setError('');
|
|
|
|
|
try {
|
|
|
|
|
await api.post('/propositions/', {
|
|
|
|
|
sujet: sujet.trim(),
|
|
|
|
|
description: description.trim() || null,
|
|
|
|
|
});
|
|
|
|
|
setSujet('');
|
|
|
|
|
setDescription('');
|
|
|
|
|
setTab('cours');
|
|
|
|
|
flash('Proposition soumise');
|
|
|
|
|
await charger();
|
|
|
|
|
} catch (e) { setError(e.message); }
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-26 08:15:28 -04:00
|
|
|
const seconder = async (id, membreId = '') => {
|
2026-05-25 17:39:38 -04:00
|
|
|
setError('');
|
|
|
|
|
try {
|
2026-05-31 10:59:41 -04:00
|
|
|
const proposition = propositions.find((p) => p.id === id);
|
2026-05-26 08:15:28 -04:00
|
|
|
const query = membreId ? `?membre_id=${membreId}` : '';
|
2026-05-31 10:59:41 -04:00
|
|
|
await api.post(`/propositions/${id}/seconder${query}`, null, { version: proposition?.modifie_le });
|
2026-05-25 17:39:38 -04:00
|
|
|
flash('Proposition secondée');
|
|
|
|
|
await charger();
|
|
|
|
|
} catch (e) { setError(e.message); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const mettreAJourResolution = (id, champ, valeur) => {
|
|
|
|
|
setResolutionForm({
|
|
|
|
|
...resolutionForm,
|
|
|
|
|
[id]: { ...(resolutionForm[id] || {}), [champ]: valeur },
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const transformer = async (id) => {
|
|
|
|
|
setError('');
|
|
|
|
|
const form = resolutionForm[id] || {};
|
|
|
|
|
const etantDonneQue = (form.etant_donne_que || '').trim();
|
|
|
|
|
const groupeADecideDe = (form.groupe_a_decide_de || '').trim();
|
|
|
|
|
if (!etantDonneQue || !groupeADecideDe) {
|
|
|
|
|
setError('Les sections "ÉTANT DONNÉ QUE" et "LE GROUPE A DÉCIDÉ DE" sont obligatoires');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
2026-05-31 10:59:41 -04:00
|
|
|
const proposition = propositions.find((p) => p.id === id);
|
2026-05-25 17:39:38 -04:00
|
|
|
await api.patch(`/propositions/${id}/voter`, {
|
|
|
|
|
statut: 'adoptee',
|
|
|
|
|
etant_donne_que: etantDonneQue,
|
|
|
|
|
groupe_a_decide_de: groupeADecideDe,
|
2026-05-31 10:59:41 -04:00
|
|
|
}, { version: proposition?.modifie_le });
|
2026-05-25 17:39:38 -04:00
|
|
|
setResolutionForm({ ...resolutionForm, [id]: { etant_donne_que: '', groupe_a_decide_de: '' } });
|
|
|
|
|
flash('Résolution créée');
|
|
|
|
|
await charger();
|
|
|
|
|
} catch (e) { setError(e.message); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const rejeter = async (id) => {
|
|
|
|
|
setError('');
|
2026-05-26 08:15:28 -04:00
|
|
|
const form = resolutionForm[id] || {};
|
|
|
|
|
const etantDonneQue = (form.etant_donne_que || '').trim();
|
|
|
|
|
if (!etantDonneQue) {
|
|
|
|
|
setError('La section "ÉTANT DONNÉ QUE" est obligatoire pour rejeter une proposition');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-05-25 17:39:38 -04:00
|
|
|
try {
|
2026-05-31 10:59:41 -04:00
|
|
|
const proposition = propositions.find((p) => p.id === id);
|
2026-05-26 08:15:28 -04:00
|
|
|
await api.patch(`/propositions/${id}/voter`, {
|
|
|
|
|
statut: 'rejetee',
|
|
|
|
|
etant_donne_que: etantDonneQue,
|
2026-05-31 10:59:41 -04:00
|
|
|
}, { version: proposition?.modifie_le });
|
2026-05-25 17:39:38 -04:00
|
|
|
flash('Proposition rejetée');
|
|
|
|
|
await charger();
|
|
|
|
|
} catch (e) { setError(e.message); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const enCours = propositions.filter((p) => ['proposee', 'secondee'].includes(p.statut));
|
|
|
|
|
|
|
|
|
|
if (loading) return <div className="flex items-center justify-center min-h-screen"><p className="text-gray-400">Chargement...</p></div>;
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen bg-gray-100">
|
2026-05-25 17:39:38 -04:00
|
|
|
<PageHeader titre="Gouvernance" sousTitre="Décisions du groupe" />
|
|
|
|
|
|
|
|
|
|
<div className="p-4 space-y-4">
|
|
|
|
|
{msg && <div className="bg-green-50 text-green-700 p-3 rounded-xl text-center text-sm font-medium">{msg}</div>}
|
|
|
|
|
{error && <div className="bg-red-50 text-red-600 p-3 rounded-xl text-center text-sm">{error}</div>}
|
2026-03-04 14:01:00 -05:00
|
|
|
|
|
|
|
|
<div className="flex gap-2">
|
|
|
|
|
{[
|
2026-05-25 17:39:38 -04:00
|
|
|
['cours', `En cours (${enCours.length})`],
|
|
|
|
|
['nouvelle', 'Soumettre'],
|
|
|
|
|
['historique', `Résolutions (${resolutions.length})`],
|
|
|
|
|
].map(([val, label]) => (
|
|
|
|
|
<button key={val} onClick={() => { setTab(val); setError(''); }}
|
|
|
|
|
className={`flex-1 py-2 rounded-xl text-sm font-bold transition ${
|
|
|
|
|
tab === val ? 'bg-aa-blue text-white' : 'bg-white text-gray-500'
|
|
|
|
|
}`}>
|
|
|
|
|
{label}
|
2026-03-04 14:01:00 -05:00
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-05-25 17:39:38 -04:00
|
|
|
{tab === 'cours' && (
|
|
|
|
|
enCours.length === 0 ? (
|
|
|
|
|
<div className="text-center py-12">
|
|
|
|
|
<p className="text-4xl mb-2">📌</p>
|
|
|
|
|
<p className="text-gray-500">Aucune décision en cours</p>
|
|
|
|
|
<button onClick={() => setTab('nouvelle')} className="mt-3 text-aa-blue font-bold text-sm">
|
|
|
|
|
Soumettre une proposition
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="space-y-3">
|
|
|
|
|
{enCours.map((p) => {
|
|
|
|
|
const statut = STATUTS[p.statut] || STATUTS.proposee;
|
|
|
|
|
const form = resolutionForm[p.id] || {};
|
|
|
|
|
const resolutionComplete = (form.etant_donne_que || '').trim() && (form.groupe_a_decide_de || '').trim();
|
2026-05-26 08:15:28 -04:00
|
|
|
const motifRejetPresent = (form.etant_donne_que || '').trim();
|
2026-05-25 17:39:38 -04:00
|
|
|
return (
|
|
|
|
|
<div key={p.id} className="bg-white rounded-2xl p-4 shadow-sm">
|
|
|
|
|
<div className="flex items-start justify-between gap-3">
|
|
|
|
|
<div className="min-w-0">
|
|
|
|
|
<p className="font-bold text-gray-800">{p.sujet}</p>
|
|
|
|
|
{p.description && <p className="text-sm text-gray-500 mt-1">{p.description}</p>}
|
|
|
|
|
</div>
|
|
|
|
|
<span className={`text-xs px-2 py-1 rounded-full font-medium whitespace-nowrap ${statut.cls}`}>
|
|
|
|
|
{statut.label}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-3 text-xs text-gray-400 space-y-1">
|
|
|
|
|
<p>Proposée par <span className="font-medium text-gray-600">{p.proposeur_prenom}</span></p>
|
|
|
|
|
{p.secondeur_prenom && <p>Secondée par <span className="font-medium text-gray-600">{p.secondeur_prenom}</span></p>}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{p.statut === 'proposee' && (
|
2026-05-26 08:15:28 -04:00
|
|
|
<div className="mt-3 space-y-2">
|
|
|
|
|
{peutExecutif && (
|
|
|
|
|
<textarea value={form.etant_donne_que || ''}
|
|
|
|
|
onChange={(e) => mettreAJourResolution(p.id, 'etant_donne_que', e.target.value)}
|
|
|
|
|
placeholder="ÉTANT DONNÉ QUE..."
|
|
|
|
|
rows={2}
|
|
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue resize-none text-sm" />
|
|
|
|
|
)}
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
|
|
|
{peutExecutif && (
|
|
|
|
|
<button onClick={() => rejeter(p.id)} disabled={!motifRejetPresent}
|
2026-05-25 17:39:38 -04:00
|
|
|
className="py-2 bg-red-50 text-red-700 rounded-xl text-sm font-bold border border-red-200 active:scale-[0.97] transition">
|
|
|
|
|
Rejeter
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<button onClick={() => seconder(p.id)}
|
2026-05-26 08:15:28 -04:00
|
|
|
className={`${peutExecutif ? '' : 'col-span-2'} py-2 bg-blue-50 text-blue-700 rounded-xl text-sm font-bold border border-blue-200 active:scale-[0.97] transition`}>
|
|
|
|
|
Je seconde
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{p.statut === 'proposee' && peutExecutif && (
|
|
|
|
|
<div className="mt-2 grid grid-cols-[1fr_auto] gap-2">
|
|
|
|
|
<select value={seconderPour[p.id] || ''} onChange={(e) => setSeconderPour({ ...seconderPour, [p.id]: e.target.value })}
|
|
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue text-sm">
|
|
|
|
|
<option value="">Seconder pour...</option>
|
|
|
|
|
{membres.map((m) => <option key={m.id} value={m.id}>{m.prenom}</option>)}
|
|
|
|
|
</select>
|
|
|
|
|
<button onClick={() => seconder(p.id, seconderPour[p.id])} disabled={!seconderPour[p.id]}
|
|
|
|
|
className="px-4 bg-blue-600 text-white rounded-xl text-sm font-bold disabled:opacity-40">
|
|
|
|
|
OK
|
2026-05-25 17:39:38 -04:00
|
|
|
</button>
|
|
|
|
|
</div>
|
2026-03-04 14:01:00 -05:00
|
|
|
)}
|
2026-05-25 17:39:38 -04:00
|
|
|
|
2026-05-26 08:15:28 -04:00
|
|
|
{p.statut === 'secondee' && peutExecutif && (
|
2026-05-25 17:39:38 -04:00
|
|
|
<div className="mt-3 space-y-3">
|
|
|
|
|
<div>
|
|
|
|
|
<label className="text-xs text-gray-400 block mb-1">ÉTANT DONNÉ QUE</label>
|
|
|
|
|
<textarea value={form.etant_donne_que || ''}
|
|
|
|
|
onChange={(e) => mettreAJourResolution(p.id, 'etant_donne_que', e.target.value)}
|
|
|
|
|
placeholder="Contexte et considérants de la résolution"
|
|
|
|
|
rows={3}
|
|
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue resize-none text-sm" />
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label className="text-xs text-gray-400 block mb-1">LE GROUPE A DÉCIDÉ DE</label>
|
|
|
|
|
<textarea value={form.groupe_a_decide_de || ''}
|
|
|
|
|
onChange={(e) => mettreAJourResolution(p.id, 'groupe_a_decide_de', e.target.value)}
|
|
|
|
|
placeholder="Décision adoptée par le groupe"
|
|
|
|
|
rows={3}
|
|
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue resize-none text-sm" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
2026-05-26 08:15:28 -04:00
|
|
|
<button onClick={() => rejeter(p.id)} disabled={!motifRejetPresent}
|
|
|
|
|
className="py-2 bg-red-50 text-red-700 rounded-xl text-sm font-bold border border-red-200 disabled:opacity-40 active:scale-[0.97] transition">
|
2026-05-25 17:39:38 -04:00
|
|
|
Rejeter
|
|
|
|
|
</button>
|
|
|
|
|
<button onClick={() => transformer(p.id)} disabled={!resolutionComplete}
|
|
|
|
|
className="py-2 bg-green-50 text-green-700 rounded-xl text-sm font-bold border border-green-200 disabled:opacity-40 active:scale-[0.97] transition">
|
|
|
|
|
Transformer
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{tab === 'nouvelle' && (
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
<div className="bg-white rounded-2xl p-4 shadow-sm">
|
2026-05-26 08:15:28 -04:00
|
|
|
<label className="text-xs text-gray-400 block mb-1">Objet</label>
|
2026-05-25 17:39:38 -04:00
|
|
|
<input type="text" value={sujet} onChange={(e) => setSujet(e.target.value)}
|
2026-05-26 08:15:28 -04:00
|
|
|
placeholder="Objet de la proposition"
|
2026-05-25 17:39:38 -04:00
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue"
|
|
|
|
|
autoFocus />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="bg-white rounded-2xl p-4 shadow-sm">
|
|
|
|
|
<label className="text-xs text-gray-400 block mb-1">Détails (optionnel)</label>
|
|
|
|
|
<textarea value={description} onChange={(e) => setDescription(e.target.value)}
|
|
|
|
|
placeholder="Contexte, justification, informations utiles"
|
|
|
|
|
rows={3}
|
|
|
|
|
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue resize-none" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<button onClick={soumettre} disabled={!sujet.trim()}
|
|
|
|
|
className="w-full p-5 bg-aa-blue text-white rounded-2xl text-lg font-bold disabled:opacity-40 active:scale-[0.97] transition shadow-lg">
|
|
|
|
|
Soumettre la proposition
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{tab === 'historique' && (
|
|
|
|
|
resolutions.length === 0 ? (
|
|
|
|
|
<div className="text-center py-12">
|
|
|
|
|
<p className="text-4xl mb-2">📜</p>
|
|
|
|
|
<p className="text-gray-500">Aucune résolution</p>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
2026-05-26 08:15:28 -04:00
|
|
|
<div className="space-y-3">
|
|
|
|
|
{resolutions.map((decision) => {
|
|
|
|
|
const ouverte = decisionOuverte === decision.id;
|
|
|
|
|
const statut = STATUTS[decision.statut] || STATUTS.adoptee;
|
|
|
|
|
return (
|
|
|
|
|
<div key={decision.id} className={`bg-white rounded-xl p-4 shadow-sm border ${ouverte ? 'border-aa-blue/30' : 'border-transparent'}`}>
|
|
|
|
|
<button type="button" onClick={() => setDecisionOuverte(ouverte ? null : decision.id)}
|
|
|
|
|
className="w-full text-left">
|
2026-05-25 17:39:38 -04:00
|
|
|
<div className="flex items-start justify-between gap-3">
|
2026-05-26 08:15:28 -04:00
|
|
|
<div className="min-w-0">
|
|
|
|
|
<p className="text-xs font-mono text-aa-blue font-bold">
|
|
|
|
|
{decision.numero_resolution || (decision.statut === 'rejetee' ? 'REJETÉE' : 'Résolution')}
|
|
|
|
|
</p>
|
|
|
|
|
<p className="font-bold text-gray-800">{decision.sujet}</p>
|
|
|
|
|
<p className="text-xs text-gray-400 mt-1">
|
|
|
|
|
{decision.date_adoption || decision.date_vote || decision.cree_le?.slice(0, 10) || 'Sans date'}
|
|
|
|
|
</p>
|
2026-05-25 17:39:38 -04:00
|
|
|
</div>
|
2026-05-26 08:15:28 -04:00
|
|
|
<span className={`text-xs px-2 py-1 rounded-full font-medium whitespace-nowrap ${statut.cls}`}>
|
|
|
|
|
{decision.statut === 'adoptee' ? 'Adoptée' : statut.label}
|
2026-05-25 17:39:38 -04:00
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-05-26 08:15:28 -04:00
|
|
|
</button>
|
|
|
|
|
{ouverte && (
|
|
|
|
|
<>
|
|
|
|
|
{decision.description && <p className="text-sm text-gray-500 mt-3">{decision.description}</p>}
|
2026-05-25 17:39:38 -04:00
|
|
|
<div className="mt-3 text-xs text-gray-400 space-y-1">
|
2026-05-26 09:05:58 -04:00
|
|
|
<p>Type : {TYPES[decision.type_decision] || decision.type_decision}</p>
|
2026-05-26 08:15:28 -04:00
|
|
|
<p>Date : {decision.date_adoption || decision.date_vote || decision.cree_le?.slice(0, 10) || '—'}</p>
|
|
|
|
|
<p>Proposée par {decision.proposeur_prenom}</p>
|
|
|
|
|
{decision.secondeur_prenom && <p>Secondée par {decision.secondeur_prenom}</p>}
|
2026-03-04 14:01:00 -05:00
|
|
|
</div>
|
2026-05-26 08:15:28 -04:00
|
|
|
{(decision.etant_donne_que || decision.groupe_a_decide_de || decision.note) && (
|
2026-05-25 17:39:38 -04:00
|
|
|
<div className="mt-3 bg-gray-50 rounded-xl p-3">
|
2026-05-26 08:15:28 -04:00
|
|
|
<p className="text-xs text-gray-400 mb-1">{decision.statut === 'rejetee' ? 'Motif conservé' : 'Texte de la résolution'}</p>
|
|
|
|
|
{decision.etant_donne_que && (
|
|
|
|
|
<p className="text-sm text-gray-700 whitespace-pre-wrap"><strong>ÉTANT DONNÉ QUE</strong>{'\n'}{decision.etant_donne_que}</p>
|
2026-05-25 17:39:38 -04:00
|
|
|
)}
|
2026-05-26 08:15:28 -04:00
|
|
|
{decision.groupe_a_decide_de && (
|
|
|
|
|
<p className="text-sm text-gray-700 whitespace-pre-wrap mt-3"><strong>LE GROUPE A DÉCIDÉ DE</strong>{'\n'}{decision.groupe_a_decide_de}</p>
|
2026-05-25 17:39:38 -04:00
|
|
|
)}
|
2026-05-26 08:15:28 -04:00
|
|
|
{!decision.etant_donne_que && !decision.groupe_a_decide_de && (
|
|
|
|
|
<p className="text-sm text-gray-700 whitespace-pre-wrap">{decision.note}</p>
|
2026-05-25 17:39:38 -04:00
|
|
|
)}
|
|
|
|
|
</div>
|
2026-03-04 14:01:00 -05:00
|
|
|
)}
|
2026-05-26 08:15:28 -04:00
|
|
|
</>
|
|
|
|
|
)}
|
2026-03-04 14:01:00 -05:00
|
|
|
</div>
|
2026-05-26 08:15:28 -04:00
|
|
|
);
|
|
|
|
|
})}
|
2026-03-04 14:01:00 -05:00
|
|
|
</div>
|
2026-05-25 17:39:38 -04:00
|
|
|
)
|
2026-03-04 14:01:00 -05:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|