Files
csv/frontend/src/pages/HelpRequests.jsx
T
2026-08-23 09:06:32 +00:00

136 lines
6.1 KiB
React

import { useState, useEffect } from "react";
import api from "../api";
import { useAuth } from "../contexts/AuthContext";
export default function HelpRequests() {
const { user } = useAuth();
const [requests, setRequests] = useState([]);
const [showForm, setShowForm] = useState(false);
const [form, setForm] = useState({ title: "", description: "", category: "autre", urgent: false, image: "" });
const [editingId, setEditingId] = useState(null);
const [uploading, setUploading] = useState(false);
const load = () => {
api.get("/help").then((r) => setRequests(r.data)).catch(() => {});
};
useEffect(() => { load(); }, []);
const handleDelete = async (id) => {
if (!confirm("Supprimer cette demande ?")) return;
try {
await api.delete("/help/" + id);
load();
} catch (err) { alert(err.response?.data?.error || "Erreur"); }
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
if (editingId) {
await api.put("/help/" + editingId, form);
} else {
await api.post("/help", form);
}
setShowForm(false);
setEditingId(null);
setForm({ title: "", description: "", category: "autre", urgent: false, image: "" });
setEditingId(null);
load();
} catch (err) { alert(err.response?.data?.error || "Erreur"); }
};
const handleEdit = (r) => {
setForm({ title: r.title, description: r.description, category: r.category, urgent: r.urgent === 1, image: r.image || "" });
setEditingId(r.id);
setShowForm(true);
};
const handleImageUpload = async (e) => {
const file = e.target.files[0];
if (!file) return;
setUploading(true);
const fd = new FormData();
fd.append("file", file);
try {
const res = await api.post("/upload", fd, { headers: { "Content-Type": "multipart/form-data" } });
setForm({ ...form, image: res.data.url });
} catch (err) { alert("Erreur upload"); }
setUploading(false);
};
const categoryLabels = { course: "Courses", bricolage: "Bricolage", jardinage: "Jardinage", transport: "Transport", numerique: "Numérique", autre: "Autre" };
return (
<div className="max-w-4xl mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-2xl font-bold">Entraide</h1>
<p className="text-sm text-gray-500">Demander ou proposer de l'aide aux habitants</p>
</div>
{user && (
<button onClick={() => { setShowForm(!showForm); setEditingId(null); setForm({ title: "", description: "", category: "autre", urgent: false, image: "" }); }} className="bg-csv-600 text-white px-4 py-2 rounded-lg text-sm hover:bg-csv-700">
{showForm ? "Annuler" : "Demander de l'aide"}
</button>
)}
</div>
{showForm && (
<form onSubmit={handleSubmit} className="border rounded-lg p-4 mb-6 space-y-3 bg-white">
<input placeholder="Titre *" required value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })}
className="w-full border rounded px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-csv-500" />
<textarea placeholder="Description *" required rows={3} value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })}
className="w-full border rounded px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-csv-500" />
<div className="flex gap-3 items-center">
<select value={form.category} onChange={(e) => setForm({ ...form, category: e.target.value })}
className="border rounded px-3 py-2 text-sm outline-none">
{Object.entries(categoryLabels).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
</select>
<label className="flex items-center gap-2 text-sm">
<input type="checkbox" checked={form.urgent} onChange={(e) => setForm({ ...form, urgent: e.target.checked })} />
Urgent
</label>
</div>
{form.image && <img src={form.image} alt="" className="h-20 rounded" />}
<div>
<input type="file" accept="image/*" onChange={handleImageUpload} className="text-sm" />
{uploading && <span className="text-xs text-gray-400 ml-2">Upload...</span>}
</div>
<button type="submit" className="bg-csv-600 text-white px-4 py-2 rounded text-sm hover:bg-csv-700">
{editingId ? "Mettre a jour" : "Publier"}
</button>
</form>
)}
{requests.length === 0 ? (
<p className="text-gray-400 text-center py-8">Aucune demande d'aide pour le moment.</p>
) : (
<div className="space-y-3">
{requests.map((r) => (
<div key={r.id} className={"border rounded-lg p-4 bg-white " + (r.urgent ? "border-red-300" : "")}>
{r.image && <img src={r.image} alt={r.title} className="w-full h-36 object-cover rounded mb-2" />}
<div className="flex items-start gap-3">
{r.urgent && <span className="bg-red-500 text-white text-xs px-2 py-0.5 rounded-full mt-0.5">Urgent</span>}
<div className="flex-1">
<h3 className="font-semibold">{r.title}</h3>
<p className="text-sm text-gray-600 mt-1">{r.description}</p>
<div className="flex gap-3 mt-2 text-xs text-gray-400">
<span className="bg-gray-100 px-2 py-0.5 rounded">{categoryLabels[r.category] || r.category}</span>
<span>par {r.author_name}</span>
{r.author_phone && <span>&#128222; {r.author_phone}</span>}
{user && r.author_id === user.id && (
<>
<button onClick={() => handleEdit(r)} className="text-blue-500 hover:text-blue-700 ml-auto mr-2">Modifier</button>
<button onClick={() => handleDelete(r.id)} className="text-red-500 hover:text-red-700">Supprimer</button>
</>
)}
</div>
</div>
</div>
</div>
))}
</div>
)}
</div>
);
}