"use client"; import Image from "next/image"; import { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import type { GalleryImage } from "@/generated/prisma/client"; import { isUploadAssetPath } from "@/lib/image-url"; import { ADMIN_API } from "@/lib/constants"; export function AdminGallery() { const router = useRouter(); const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [uploading, setUploading] = useState(false); const [editingId, setEditingId] = useState(null); const [form, setForm] = useState({ imageUrl: "", alt: "", sortOrder: "0", }); const load = useCallback(async () => { const res = await fetch(`${ADMIN_API}/gallery`, { credentials: "include" }); if (res.status === 401) { router.replace("/admin/login"); return; } const data = await res.json(); setItems(Array.isArray(data) ? data : []); setLoading(false); }, [router]); useEffect(() => { load(); }, [load]); function resetForm() { setEditingId(null); setForm({ imageUrl: "", alt: "", sortOrder: "0" }); } function startEdit(g: GalleryImage) { setEditingId(g.id); setForm({ imageUrl: g.imageUrl, alt: g.alt, sortOrder: String(g.sortOrder), }); } async function uploadFile(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (!file) return; setUploading(true); try { const fd = new FormData(); fd.append("file", file); const res = await fetch(`${ADMIN_API}/upload`, { method: "POST", body: fd, credentials: "include", }); const data = await res.json().catch(() => ({})); if (!res.ok) { alert(typeof data.error === "string" ? data.error : "Échec de l’envoi"); return; } if (data.url) setForm((f) => ({ ...f, imageUrl: data.url })); } finally { setUploading(false); e.target.value = ""; } } async function onSubmit(e: React.FormEvent) { e.preventDefault(); const sortOrder = parseInt(form.sortOrder, 10); if (Number.isNaN(sortOrder)) return; setSaving(true); try { const body = { imageUrl: form.imageUrl.trim() || null, alt: form.alt.trim(), sortOrder, }; if (editingId) { const res = await fetch(`${ADMIN_API}/gallery/${editingId}`, { method: "PUT", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(body), }); if (res.status === 401) { router.replace("/admin/login"); return; } if (!res.ok) { const err = await res.json().catch(() => ({})); alert(typeof err.error === "string" ? err.error : "Erreur"); return; } } else { const res = await fetch(`${ADMIN_API}/gallery`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(body), }); if (res.status === 401) { router.replace("/admin/login"); return; } if (!res.ok) { const err = await res.json().catch(() => ({})); alert(typeof err.error === "string" ? err.error : "Erreur"); return; } } resetForm(); await load(); } finally { setSaving(false); } } async function remove(id: string) { if (!confirm("Supprimer cette photo de la galerie ?")) return; const res = await fetch(`${ADMIN_API}/gallery/${id}`, { method: "DELETE", credentials: "include", }); if (res.status === 401) { router.replace("/admin/login"); return; } if (editingId === id) resetForm(); await load(); } async function logout() { const res = await fetch(`${ADMIN_API}/auth/logout`, { method: "POST", credentials: "include", }); if (res.ok) { window.location.href = "/admin/login"; return; } router.replace("/admin/login"); router.refresh(); } return (

Galerie du site

Ordre d’affichage (nombre le plus petit en premier). Sur la page d’accueil, jusqu’à 3 photos visibles ; défilement toutes les 5 s si plus de 3 images.

Voir le site

{editingId ? "Modifier la photo" : "Ajouter une photo"}

Image
ou chemin / URL ci-dessous
setForm((f) => ({ ...f, imageUrl: e.target.value })) } required placeholder="/uploads/… ou https://…" autoComplete="off" className="rounded-2xl border border-chocolat/15 bg-cream/50 px-4 py-2.5 text-sm outline-none ring-gaufre/40 focus:ring-2" /> {form.imageUrl.trim() ? (
{form.imageUrl.startsWith("http") ? ( // eslint-disable-next-line @next/next/no-img-element ) : ( )}
) : null}
{editingId && ( )}
{loading ? (

Chargement…

) : (
    {items.map((g) => (
  • {g.imageUrl.startsWith("http") ? ( // eslint-disable-next-line @next/next/no-img-element ) : ( )}

    {g.alt}

    {g.imageUrl}

    Ordre : {g.sortOrder}

  • ))} {items.length === 0 && (
  • Aucune image. Ajoutez-en une ci-dessus.
  • )}
)}
); }