"use client" import { FormEvent, useEffect, useState } from "react" import { useRouter } from "next/navigation" type CollectionInfo = { name: string; count: number } type DocumentRow = Record const API_BASE = "http://127.0.0.1:5000" export default function AdminDatabasePage() { const router = useRouter() const [ready, setReady] = useState(false) const [collections, setCollections] = useState([]) const [selectedCollection, setSelectedCollection] = useState("") const [documents, setDocuments] = useState([]) const [search, setSearch] = useState("") const [loadingCollections, setLoadingCollections] = useState(false) const [loadingDocuments, setLoadingDocuments] = useState(false) const [saving, setSaving] = useState(false) const [message, setMessage] = useState("") const [pagination, setPagination] = useState({ page: 1, limit: 25, total: 0, pages: 1 }) const [createJson, setCreateJson] = useState('{\n "key": "value"\n}') const [editDocId, setEditDocId] = useState("") const [editJson, setEditJson] = useState("{}") const getToken = () => localStorage.getItem("admin_token") const headers = () => { const token = getToken() return token ? { "Content-Type": "application/json", Authorization: `Bearer ${token}` } : { "Content-Type": "application/json" } } const ensureAuth = async () => { const token = getToken() if (!token) { router.push("/admin/login") return false } const resp = await fetch(`${API_BASE}/api/admin/test`, { headers: headers() }) if (!resp.ok) { localStorage.removeItem("admin_token") router.push("/admin/login") return false } return true } const fetchOverview = async () => { setLoadingCollections(true) setMessage("") try { const resp = await fetch(`${API_BASE}/api/admin/database/overview`, { headers: headers() }) if (resp.ok) { const data = await resp.json() const list = Array.isArray(data.collections) ? data.collections : [] setCollections(list) if (list.length > 0 && !selectedCollection) { setSelectedCollection(list[0].name) await fetchDocuments(list[0].name, 1) } } else { const data = await resp.json().catch(() => ({})) setMessage(String(data.error || "Failed to load collections.")) } } catch { setMessage("Network error while loading collections.") } finally { setLoadingCollections(false) } } const fetchDocuments = async (collection: string, page = 1, nextSearch = search) => { if (!collection) return setLoadingDocuments(true) setMessage("") try { const params = new URLSearchParams({ page: String(page), limit: String(pagination.limit) }) if (nextSearch.trim()) params.set("search", nextSearch.trim()) const resp = await fetch(`${API_BASE}/api/admin/database/collections/${encodeURIComponent(collection)}?${params.toString()}`, { headers: headers() }) if (resp.ok) { const data = await resp.json() setDocuments(Array.isArray(data.documents) ? data.documents : []) if (data.pagination) setPagination(data.pagination) } else { const data = await resp.json().catch(() => ({})) setMessage(String(data.error || "Failed to load documents.")) setDocuments([]) } } catch { setMessage("Network error while loading documents.") setDocuments([]) } finally { setLoadingDocuments(false) } } const createDocument = async (e: FormEvent) => { e.preventDefault() if (!selectedCollection) return setSaving(true) setMessage("") try { const payload = JSON.parse(createJson) const resp = await fetch(`${API_BASE}/api/admin/database/collections/${encodeURIComponent(selectedCollection)}`, { method: "POST", headers: headers(), body: JSON.stringify(payload), }) const data = await resp.json().catch(() => ({})) if (!resp.ok) { setMessage(String(data.error || "Failed to create document.")) return } setMessage("Document created successfully.") await fetchOverview() await fetchDocuments(selectedCollection, 1) } catch { setMessage("Invalid JSON for create payload.") } finally { setSaving(false) } } const startEditDocument = (doc: DocumentRow) => { const id = String(doc._id || "") if (!id) { setMessage("Selected document has no _id.") return } const clone = { ...doc } delete clone._id setEditDocId(id) setEditJson(JSON.stringify(clone, null, 2)) } const saveEditDocument = async (e: FormEvent) => { e.preventDefault() if (!selectedCollection || !editDocId) return setSaving(true) setMessage("") try { const payload = JSON.parse(editJson) const resp = await fetch( `${API_BASE}/api/admin/database/collections/${encodeURIComponent(selectedCollection)}/${encodeURIComponent(editDocId)}`, { method: "PUT", headers: headers(), body: JSON.stringify(payload), }, ) const data = await resp.json().catch(() => ({})) if (!resp.ok) { setMessage(String(data.error || "Failed to update document.")) return } setMessage("Document updated successfully.") setEditDocId("") setEditJson("{}") await fetchDocuments(selectedCollection, pagination.page) } catch { setMessage("Invalid JSON for update payload.") } finally { setSaving(false) } } const deleteDocument = async (docId: string) => { if (!selectedCollection || !docId) return setSaving(true) setMessage("") try { const resp = await fetch( `${API_BASE}/api/admin/database/collections/${encodeURIComponent(selectedCollection)}/${encodeURIComponent(docId)}`, { method: "DELETE", headers: headers(), }, ) const data = await resp.json().catch(() => ({})) if (!resp.ok) { setMessage(String(data.error || "Failed to delete document.")) return } setMessage("Document deleted successfully.") await fetchOverview() await fetchDocuments(selectedCollection, 1) } catch { setMessage("Network error while deleting document.") } finally { setSaving(false) } } useEffect(() => { const init = async () => { const ok = await ensureAuth() if (!ok) return setReady(true) await fetchOverview() } init() }, []) if (!ready) { return (

Loading database explorer...

) } return (

Database Explorer

Browse all collections and perform create, update, and delete actions on documents.

Create Document

Collection: {selectedCollection || "None selected"}