"use client"; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { useSession } from "next-auth/react"; import { useEditor, EditorContent } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import LinkExtension from '@tiptap/extension-link'; import ImageExtension from '@tiptap/extension-image'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Card, CardContent } from '@/components/ui/card'; import { Bold, Italic, List, ListOrdered, Link as LinkIcon, Image as ImageIcon, Loader2 } from 'lucide-react'; const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api'; interface BlogFormProps { initialData?: any; isEditing?: boolean; } export default function BlogForm({ initialData = null, isEditing = false }: BlogFormProps) { const router = useRouter(); const { data: session } = useSession(); const [isLoading, setIsLoading] = useState(false); // Form State const [title, setTitle] = useState(initialData?.title || ''); const [slug, setSlug] = useState(initialData?.slug || ''); const [excerpt, setExcerpt] = useState(initialData?.excerpt || ''); const [featuredImage, setFeaturedImage] = useState(initialData?.featuredImage || ''); const [status, setStatus] = useState(initialData?.status || 'DRAFT'); const [publishedAt, setPublishedAt] = useState(initialData?.publishedAt ? new Date(initialData.publishedAt).toISOString().slice(0, 16) : ''); const [tags, setTags] = useState(initialData?.tags ? JSON.parse(initialData.tags).join(', ') : ''); const editor = useEditor({ extensions: [ StarterKit, LinkExtension.configure({ openOnClick: false }), ImageExtension.configure({ inline: true }), ], content: initialData?.content || '

Start writing your post here...

', immediatelyRender: false, editorProps: { attributes: { class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none min-h-[400px] p-4 border rounded-md max-w-none', }, }, }); const setLink = () => { const previousUrl = editor?.getAttributes('link').href; const url = window.prompt('URL', previousUrl); if (url === null) return; if (url === '') { editor?.chain().focus().extendMarkRange('link').unsetLink().run(); return; } editor?.chain().focus().extendMarkRange('link').setLink({ href: url }).run(); }; const addImage = () => { const url = window.prompt('Image URL'); if (url) { editor?.chain().focus().setImage({ src: url }).run(); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); const content = editor?.getHTML(); const tagsArray = tags.split(',').map((t: string) => t.trim()).filter(Boolean); const payload = { title, slug: slug || undefined, content, excerpt, featuredImage, status, publishedAt: publishedAt ? new Date(publishedAt).toISOString() : null, tags: JSON.stringify(tagsArray) }; try { const url = isEditing && initialData?.id ? `${API_URL}/admin/blog/${initialData.id}` : `${API_URL}/admin/blog`; const method = isEditing ? 'PUT' : 'POST'; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${session?.user?.id}` }, body: JSON.stringify(payload) }); if (res.ok) { router.push('/admin/blog'); router.refresh(); } else { const data = await res.json(); alert(`Error: ${data.error || 'Failed to save post'}`); } } catch (error) { console.error("Save error:", error); alert("An unexpected error occurred while saving."); } finally { setIsLoading(false); } }; return (

{isEditing ? 'Edit Article' : 'New Article'}

{/* Main Content Area */}
setTitle(e.target.value)} placeholder="Enter an engaging title..." required className="text-lg font-medium" />
{editor && (
{/* TipTap Toolbar */}
{/* TipTap Editor */}
)}