"use client" import { useState, useEffect, useCallback } from "react" import { useSession } from "next-auth/react" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" import { Card, CardContent } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog" import { Plus, Pencil, Trash2, Star, CheckCircle, XCircle, Loader2 } from "lucide-react" const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:5000/api" type Testimonial = { id: string clientName: string company: string | null content: string rating: number imageUrl: string | null approved: boolean createdAt: string } type FormData = { clientName: string company: string content: string rating: number imageUrl: string } const emptyForm: FormData = { clientName: "", company: "", content: "", rating: 5, imageUrl: "", } export default function AdminTestimonialsPage() { const { data: session, status } = useSession() const router = useRouter() const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [formError, setFormError] = useState("") const [dialogOpen, setDialogOpen] = useState(false) const [editingId, setEditingId] = useState(null) const [form, setForm] = useState(emptyForm) const [deleteId, setDeleteId] = useState(null) const [deleteName, setDeleteName] = useState("") useEffect(() => { if (status === "unauthenticated") router.push("/admin/login") }, [status, router]) const fetchItems = useCallback(async () => { try { const res = await fetch(`${API_URL}/admin/testimonials`, { headers: { Authorization: `Bearer ${(session as any)?.accessToken || "session"}` }, credentials: "include", }) if (res.ok) { const data = await res.json() setItems(data) } } catch (err) { console.error("Failed to fetch testimonials:", err) } finally { setLoading(false) } }, [session]) useEffect(() => { if (status === "authenticated") fetchItems() }, [status, fetchItems]) const openCreate = () => { setEditingId(null) setForm(emptyForm) setFormError("") setDialogOpen(true) } const openEdit = (item: Testimonial) => { setEditingId(item.id) setForm({ clientName: item.clientName, company: item.company || "", content: item.content, rating: item.rating, imageUrl: item.imageUrl || "", }) setFormError("") setDialogOpen(true) } const handleSubmit = async () => { if (!form.clientName.trim()) return setFormError("Client name is required") if (!form.content.trim()) return setFormError("Testimonial content is required") if (form.rating < 1 || form.rating > 5) return setFormError("Rating must be between 1 and 5") setSaving(true) setFormError("") try { const url = editingId ? `${API_URL}/admin/testimonials/${editingId}` : `${API_URL}/admin/testimonials` const res = await fetch(url, { method: editingId ? "PATCH" : "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${(session as any)?.accessToken || "session"}`, }, credentials: "include", body: JSON.stringify({ clientName: form.clientName.trim(), company: form.company.trim() || null, content: form.content.trim(), rating: form.rating, imageUrl: form.imageUrl.trim() || null, }), }) const data = await res.json() if (!res.ok) { setFormError(data.error || "Something went wrong") return } setDialogOpen(false) fetchItems() } catch (err) { setFormError("Network error. Please try again.") } finally { setSaving(false) } } const handleToggle = async (id: string) => { try { await fetch(`${API_URL}/admin/testimonials/${id}/toggle`, { method: "PATCH", headers: { Authorization: `Bearer ${(session as any)?.accessToken || "session"}` }, credentials: "include", }) fetchItems() } catch (err) { console.error("Toggle failed:", err) } } const handleDelete = async () => { if (!deleteId) return try { await fetch(`${API_URL}/admin/testimonials/${deleteId}`, { method: "DELETE", headers: { Authorization: `Bearer ${(session as any)?.accessToken || "session"}` }, credentials: "include", }) setDeleteId(null) fetchItems() } catch (err) { console.error("Delete failed:", err) } } if (status === "loading" || loading) { return (
) } return (
{/* Header */}

Testimonials

Manage client testimonials and approval status

{/* Testimonials list */} {items.length === 0 ? (

No testimonials yet.

) : (
{items.map((item) => (

{item.clientName}

{item.company && ( {item.company} )} {/* Approval badge */} {item.approved ? ( Approved ) : ( Pending )}

“{item.content}”

{[...Array(5)].map((_, j) => ( ))} {new Date(item.createdAt).toLocaleDateString()}
))}
)} {/* Create/Edit Dialog */} {editingId ? "Edit Testimonial" : "New Testimonial"} {editingId ? "Update the testimonial details." : "Add a new client testimonial."}
setForm((p) => ({ ...p, clientName: e.target.value }))} placeholder="Jane Doe" />
setForm((p) => ({ ...p, company: e.target.value }))} placeholder="Acme Inc." />