groupe-meditation/frontend/src/pages/RapportRSG.jsx
2026-03-04 14:01:00 -05:00

155 lines
6.8 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { api } from '../stores/api';
import PageHeader from '../components/PageHeader';
import SuccessCheck from '../components/SuccessCheck';
export default function RapportRSG() {
const [rapports, setRapports] = useState([]);
const [form, setForm] = useState({
reunion_dist: new Date().toISOString().slice(0, 10),
decisions_text: '',
infos_region: '',
sujets_groupe: '',
});
const [loading, setLoading] = useState(true);
const [success, setSuccess] = useState(false);
const [viewRapport, setViewRapport] = useState(null);
const [error, setError] = useState('');
useEffect(() => {
api.get('/rapports-rsg/').then((data) => {
setRapports(data);
setLoading(false);
}).catch(() => setLoading(false));
}, []);
const handleSubmit = async () => {
if (!form.decisions_text.trim() && !form.infos_region.trim() && !form.sujets_groupe.trim()) {
setError('Au moins une section doit être remplie');
return;
}
setError('');
try {
const decisionsList = form.decisions_text
.split('\n')
.map((d) => d.trim())
.filter((d) => d.length > 0);
await api.post('/rapports-rsg/', {
reunion_dist: form.reunion_dist,
decisions: decisionsList.length > 0 ? decisionsList : null,
infos_region: form.infos_region.trim() || null,
sujets_groupe: form.sujets_groupe.trim() || null,
});
setSuccess(true);
} catch (e) { setError(e.message); }
};
if (success) return <SuccessCheck message="Rapport RSG enregistré ✓" />;
// Vue lecture
if (viewRapport) {
return (
<div className="min-h-screen bg-gray-100">
<div className="bg-aa-blue text-white p-4 flex items-center gap-3">
<button onClick={() => setViewRapport(null)} className="text-2xl">←</button>
<div>
<h1 className="text-lg font-bold">Rapport RSG</h1>
<p className="text-blue-200 text-xs">Réunion du {viewRapport.reunion_dist}</p>
</div>
</div>
<div className="p-4 space-y-4">
<div className="bg-white rounded-2xl p-4 shadow-sm">
<p className="text-xs text-gray-400 mb-1">Rédigé par {viewRapport.redacteur_prenom}</p>
</div>
{viewRapport.decisions && viewRapport.decisions.length > 0 && (
<div className="bg-white rounded-2xl p-4 shadow-sm">
<h3 className="font-bold text-gray-700 mb-2">Décisions du district</h3>
{viewRapport.decisions.map((d, i) => (
<div key={i} className="py-2 border-b border-gray-100 last:border-0">
<p className="text-sm text-gray-800">• {d}</p>
</div>
))}
</div>
)}
{viewRapport.infos_region && (
<div className="bg-white rounded-2xl p-4 shadow-sm">
<h3 className="font-bold text-gray-700 mb-2">Informations de la région</h3>
<p className="text-sm text-gray-600 whitespace-pre-wrap">{viewRapport.infos_region}</p>
</div>
)}
{viewRapport.sujets_groupe && (
<div className="bg-white rounded-2xl p-4 shadow-sm">
<h3 className="font-bold text-gray-700 mb-2">Sujets pour le groupe</h3>
<p className="text-sm text-gray-600 whitespace-pre-wrap">{viewRapport.sujets_groupe}</p>
</div>
)}
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-100">
<PageHeader titre="Rapport du RSG" sousTitre="M3 — Réunion de district" />
<div className="p-4 space-y-4">
{/* Rapports existants */}
{rapports.length > 0 && (
<div className="bg-white rounded-2xl p-4 shadow-sm">
<h2 className="text-xs font-bold text-gray-400 uppercase tracking-wider mb-2">Rapports récents</h2>
{rapports.slice(0, 5).map((r) => (
<button key={r.id} onClick={() => setViewRapport(r)}
className="w-full flex items-center justify-between py-2 border-b border-gray-50 last:border-0 active:bg-gray-50">
<div>
<p className="font-medium text-sm text-gray-800">Réunion du {r.reunion_dist}</p>
<p className="text-xs text-gray-400">Par {r.redacteur_prenom}</p>
</div>
<span className="text-gray-300">→</span>
</button>
))}
</div>
)}
{/* Nouveau rapport */}
<div className="bg-white rounded-2xl p-4 shadow-sm">
<label className="text-xs text-gray-400 block mb-1">Date de la réunion de district</label>
<input type="date" value={form.reunion_dist}
onChange={(e) => setForm({ ...form, reunion_dist: e.target.value })}
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue" />
</div>
<div className="bg-white rounded-2xl p-4 shadow-sm">
<label className="text-xs text-gray-400 block mb-1">Décisions du district (une par ligne)</label>
<textarea value={form.decisions_text}
onChange={(e) => setForm({ ...form, decisions_text: e.target.value })} rows={4}
placeholder="Vote sur le budget annuel approuvé&#10;Nouveau format d'atelier proposé&#10;Date du prochain congrès confirmée"
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="bg-white rounded-2xl p-4 shadow-sm">
<label className="text-xs text-gray-400 block mb-1">Informations de la région 87</label>
<textarea value={form.infos_region}
onChange={(e) => setForm({ ...form, infos_region: e.target.value })} rows={3}
placeholder="Nouvelles de l'assemblée régionale, rapports..."
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="bg-white rounded-2xl p-4 shadow-sm">
<label className="text-xs text-gray-400 block mb-1">Sujets à rapporter au groupe</label>
<textarea value={form.sujets_groupe}
onChange={(e) => setForm({ ...form, sujets_groupe: e.target.value })} rows={3}
placeholder="Points à discuter à la prochaine réunion d'affaires..."
className="w-full p-3 bg-gray-50 rounded-xl border-0 focus:ring-2 focus:ring-aa-blue resize-none text-sm" />
</div>
{error && <p className="text-red-500 text-sm text-center bg-red-50 p-3 rounded-lg">{error}</p>}
<button onClick={handleSubmit}
className="w-full p-5 bg-blue-700 text-white rounded-2xl text-xl font-bold disabled:opacity-40 active:scale-[0.97] transition shadow-lg">
📨 Enregistrer le rapport
</button>
</div>
</div>
);
}