"use client"; import { useState, useCallback } from "react"; import { clientFetch } from "@/lib/api"; import { toast } from "sonner"; import { BlogPost, PostStatus, ContentFormat, UserRole } from "@/lib/types"; import { CreatePostForm } from "./create-post-form"; import { Badge } from "@/components/ui/badge"; 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 { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Eye, Loader2, Pencil, Trash2, X, Check, ExternalLink } from "lucide-react"; import Link from "next/link"; interface Props { initialPosts: BlogPost[]; userRole: UserRole; } export function PostsTable({ initialPosts, userRole }: Props) { const [posts, setPosts] = useState(initialPosts); const [editingId, setEditingId] = useState(null); const [loading, setLoading] = useState(false); const refreshPosts = useCallback(async () => { try { const data = await clientFetch<{ posts: BlogPost[]; total: number }>( "/blog-posts?pageSize=50" ); setPosts(data.posts); } catch { /* ignore */ } }, []); const handleDelete = async (id: string) => { setLoading(true); try { await clientFetch(`/blog-posts/${id}`, { method: "DELETE" }); toast.success("Post deleted."); setPosts((prev) => prev.filter((p) => p.id !== id)); } catch (err: unknown) { toast.error(err instanceof Error ? err.message : "Delete failed"); } finally { setLoading(false); } }; const handleUpdate = async ( e: React.FormEvent, id: string ) => { e.preventDefault(); const fd = new FormData(e.currentTarget); const body: Record = { title: fd.get("title"), slug: fd.get("slug") || undefined, excerpt: fd.get("excerpt") || undefined, content: fd.get("content"), contentFormat: fd.get("contentFormat"), status: fd.get("status"), isFeatured: fd.get("isFeatured") === "true", categories: fd.get("categories") || undefined, tags: fd.get("tags") || undefined, featuredImageUrl: fd.get("featuredImageUrl") || undefined, featuredImageAlt: fd.get("featuredImageAlt") || undefined, }; setLoading(true); try { await clientFetch(`/blog-posts/${id}`, { method: "PATCH", body: JSON.stringify(body), }); toast.success("Post updated!"); setEditingId(null); await refreshPosts(); } catch (err: unknown) { toast.error(err instanceof Error ? err.message : "Update failed"); } finally { setLoading(false); } }; const statusColor: Record = { [PostStatus.PUBLISHED]: "bg-emerald-100 text-emerald-800 border-emerald-200", [PostStatus.DRAFT]: "bg-zinc-100 text-zinc-700 border-zinc-200", [PostStatus.ARCHIVED]: "bg-amber-100 text-amber-800 border-amber-200", }; return (
{/* Create form for ADMIN/MANAGER */} {(userRole === UserRole.ADMIN || userRole === UserRole.MANAGER) && ( )} {/* Posts list */} {posts.length === 0 ? (
No posts yet.
) : (
{posts.map((post) => (
{editingId === post.id && userRole === UserRole.ADMIN ? ( /* ── Edit form ─────────────────────────────────────────── */
handleUpdate(e, post.id)} className="space-y-3" >
Editing post