"use client"; import React, { useEffect, useState } from "react"; import { AdminHeader, AlertBanner, Modal, ConfirmDeleteModal, getClientToken } from "../_components/AdminComponents"; import { adminGetResearchProjects, adminCreateResearchProject, adminUpdateResearchProject, adminDeleteResearchProject, AdminResearchProject, } from "../../../lib/adminApi"; export default function AdminResearchProjectsPage() { const [projects, setProjects] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [successMsg, setSuccessMsg] = useState(null); // Form State const [isModalOpen, setIsModalOpen] = useState(false); const [editingProject, setEditingProject] = useState(null); const [formData, setFormData] = useState({ slug: "", title: "", abstract: "", keywords: "", organization: "", standards_org: "", period: "", funder: "", }); const [isSubmitting, setIsSubmitting] = useState(false); // Delete State const [deletingId, setDeletingId] = useState(null); const loadProjects = async () => { try { setIsLoading(true); setError(null); const data = await adminGetResearchProjects(); setProjects(data); } catch (err: any) { setError(err?.message || "Failed to load research projects."); } finally { setIsLoading(false); } }; useEffect(() => { loadProjects(); }, []); const handleOpenCreate = () => { setEditingProject(null); setFormData({ slug: "", title: "", abstract: "", keywords: "", organization: "", standards_org: "", period: "", funder: "", }); setIsModalOpen(true); }; const handleOpenEdit = (p: AdminResearchProject) => { setEditingProject(p); setFormData({ slug: p.slug, title: p.title, abstract: p.abstract, keywords: (p.keywords || []).join(", "), organization: p.organization || "", standards_org: p.standards_org || "", period: p.period || "", funder: p.funder || "", }); setIsModalOpen(true); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const token = getClientToken(); if (!token) { setError("Unauthorized. Please log in."); return; } const kwArray = formData.keywords .split(",") .map((k) => k.trim()) .filter(Boolean); const payload = { slug: formData.slug.trim(), title: formData.title.trim(), abstract: formData.abstract.trim(), keywords: kwArray, organization: formData.organization.trim() || undefined, standards_org: formData.standards_org.trim() || undefined, period: formData.period.trim() || undefined, funder: formData.funder.trim() || undefined, }; setIsSubmitting(true); setError(null); try { if (editingProject) { await adminUpdateResearchProject(token, editingProject.id, payload); setSuccessMsg(`Project "${payload.title}" updated successfully.`); } else { await adminCreateResearchProject(token, payload); setSuccessMsg(`Project "${payload.title}" created successfully.`); } setIsModalOpen(false); await loadProjects(); } catch (err: any) { setError(err?.message || "Failed to save project."); } finally { setIsSubmitting(false); } }; const handleConfirmDelete = async () => { if (!deletingId) return; const token = getClientToken(); if (!token) { setError("Unauthorized. Please log in."); return; } setIsSubmitting(true); try { await adminDeleteResearchProject(token, deletingId); setSuccessMsg("Project deleted successfully."); setDeletingId(null); await loadProjects(); } catch (err: any) { setError(err?.message || "Failed to delete project."); } finally { setIsSubmitting(false); } }; return (
+ Add New Project } /> {error && setError(null)} />} {successMsg && setSuccessMsg(null)} />} {isLoading ? (
Loading projects...
) : (
{projects.length === 0 ? ( ) : ( projects.map((p) => ( )) )}
ID Slug Title Organization / Period Actions
No research projects found.
{p.id} {p.slug}
{p.title}
{p.abstract}
{p.organization || p.standards_org || "—"}
{p.period || "—"}
)} {/* Create / Edit Modal */} setIsModalOpen(false)} >
setFormData({ ...formData, slug: e.target.value })} placeholder="e.g. ccis" required className="w-full px-3 py-2 text-sm border border-line rounded bg-ivory text-ink focus:outline-none focus:ring-1 focus:ring-cobalt" />
setFormData({ ...formData, title: e.target.value })} placeholder="Project title" required className="w-full px-3 py-2 text-sm border border-line rounded bg-ivory text-ink focus:outline-none focus:ring-1 focus:ring-cobalt" />