"use client"; import { useTransition, useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { createBlogPost, updateBlogPost } from '@/app/actions/actualites'; import { Loader2, ArrowLeft, Save, Calendar, CheckCircle2, FileText, Archive, Link as LinkIcon, Plus, Trash2, FileJson } from 'lucide-react'; import Link from 'next/link'; import { toast } from 'react-hot-toast'; import RichTextEditor from './RichTextEditor'; import ImageUploader from './ImageUploader'; import TagInput from './TagInput'; import { ContentStatus } from '@prisma/client'; import { getAllTags } from '@/app/actions/taxonomies'; interface Props { initialData?: { id: string; title: string; excerpt: string; content: string; author: string; imageUrl: string; slug?: string | null; tags?: string[]; metaTitle?: string | null; metaDescription?: string | null; publishedAt?: Date | string | null; status?: ContentStatus; coverPosition?: string | null; coverZoom?: number | null; sources?: any; }; } export default function BlogForm({ initialData }: Props) { const router = useRouter(); const [isPending, startTransition] = useTransition(); // JSON prefill state const [currentData, setCurrentData] = useState(initialData || {}); const [jsonString, setJsonString] = useState(''); const [showJsonInput, setShowJsonInput] = useState(false); const [jsonError, setJsonError] = useState(null); // Form input states const [content, setContent] = useState(initialData?.content || ''); const [imageUrl, setImageUrl] = useState(initialData?.imageUrl || ''); const [coverPosition, setCoverPosition] = useState(initialData?.coverPosition || '50% 50%'); const [coverZoom, setCoverZoom] = useState(initialData?.coverZoom || 1); const [tags, setTags] = useState(initialData?.tags || []); const [allExistingTags, setAllExistingTags] = useState([]); const [publishedAtValue, setPublishedAtValue] = useState( initialData?.publishedAt ? new Date(initialData.publishedAt).toISOString().slice(0, 16) : new Date().toISOString().slice(0, 16) ); const [sources, setSources] = useState<{ title: string; url: string }[]>( Array.isArray(initialData?.sources) ? initialData.sources : [] ); const isPublished = new Date(publishedAtValue) <= new Date(); useEffect(() => { getAllTags().then(setAllExistingTags); }, []); const handleApplyJson = () => { try { if (!jsonString.trim()) { throw new Error("Veuillez coller un code JSON."); } const parsed = JSON.parse(jsonString); // Extract new combined tags const newTags = Array.isArray(parsed.tags) ? [...parsed.tags] : [...tags]; if (parsed.type && !newTags.includes(parsed.type)) { newTags.push(parsed.type); } // Update states to prefill rich components if (parsed.content) setContent(parsed.content); if (parsed.imageUrl) setImageUrl(parsed.imageUrl); setTags(newTags); if (Array.isArray(parsed.sources)) { setSources(parsed.sources); } // Update currentData to reset defaultValues on native inputs via form key remount setCurrentData({ ...currentData, title: parsed.title || currentData.title || '', excerpt: parsed.excerpt || currentData.excerpt || '', author: parsed.author || currentData.author || 'Rédaction Afrohub', slug: parsed.slug || currentData.slug || '', metaTitle: parsed.metaTitle || currentData.metaTitle || '', metaDescription: parsed.metaDescription || currentData.metaDescription || '', _prefillKey: Date.now() // Force form remount }); setJsonError(null); setShowJsonInput(false); setJsonString(''); toast.success("Champs pré-remplis avec le JSON !"); } catch (err: any) { setJsonError("Format JSON invalide. Vérifiez la syntaxe : " + (err.message || '')); } }; const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); const formData = new FormData(event.currentTarget); const publishedAtStr = formData.get('publishedAt') as string; const data = { title: formData.get('title') as string, slug: formData.get('slug') as string, excerpt: formData.get('excerpt') as string, content: content, author: formData.get('author') as string, imageUrl: imageUrl, // Use state value tags: tags, // Use state value metaTitle: formData.get('metaTitle') as string, metaDescription: formData.get('metaDescription') as string, publishedAt: publishedAtStr ? new Date(publishedAtStr) : undefined, status: formData.get('status') as ContentStatus, coverPosition: coverPosition, coverZoom: coverZoom, sources: sources, }; if (!data.imageUrl) { toast.error("Une image est requise"); return; } startTransition(async () => { const result = initialData ? await updateBlogPost(initialData.id, data) : await createBlogPost(data); if (result.success) { toast.success(initialData ? "Article mis à jour" : "Article créé avec succès"); router.push('/actualites'); router.refresh(); } else { toast.error(result.error || "Une erreur est survenue"); } }); }; return (

{initialData ? 'Modifier l\'article' : 'Nouvel Article'}

{/* PREFILL JSON SECTION */}
{showJsonInput && (

Collez le code JSON généré par Gemini pour remplir instantanément le titre, l'extrait, le contenu HTML, l'auteur, l'image, le slug, les tags SEO, et les sources.

{jsonError && (
{jsonError}
)}