// Blog Management JavaScript let postsData = []; let postModal; document.addEventListener("DOMContentLoaded", function () { postModal = new bootstrap.Modal(document.getElementById("postModal")); checkAuth().then((authenticated) => { if (authenticated) { loadPosts(); } }); const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("action") === "create") { showCreatePost(); } // Auto-generate slug from title document.getElementById("postTitle")?.addEventListener("input", function () { if (!document.getElementById("postId").value) { document.getElementById("postSlug").value = slugify(this.value); } }); }); async function loadPosts() { try { const response = await fetch("/api/admin/blog", { credentials: "include" }); const data = await response.json(); if (data.success) { postsData = data.posts; renderPosts(postsData); } } catch (error) { console.error("Failed to load posts:", error); } } function renderPosts(posts) { const tbody = document.getElementById("postsTableBody"); if (posts.length === 0) { tbody.innerHTML = `

No blog posts found

`; return; } tbody.innerHTML = posts .map( (p) => ` ${p.id} ${escapeHtml(p.title)} ${escapeHtml(p.slug)} ${escapeHtml((p.excerpt || "").substring(0, 40))}... ${p.ispublished ? "Published" : "Draft"} ${formatDate(p.createdat)} ` ) .join(""); } function filterPosts() { const searchTerm = document.getElementById("searchInput").value.toLowerCase(); const filtered = postsData.filter( (p) => p.title.toLowerCase().includes(searchTerm) || p.slug.toLowerCase().includes(searchTerm) ); renderPosts(filtered); } function showCreatePost() { document.getElementById("modalTitle").textContent = "Create Blog Post"; document.getElementById("postForm").reset(); document.getElementById("postId").value = ""; document.getElementById("postPublished").checked = false; postModal.show(); } async function editPost(id) { try { const response = await fetch(`/api/admin/blog/${id}`, { credentials: "include", }); const data = await response.json(); if (data.success) { const post = data.post; document.getElementById("modalTitle").textContent = "Edit Blog Post"; document.getElementById("postId").value = post.id; document.getElementById("postTitle").value = post.title; document.getElementById("postSlug").value = post.slug; document.getElementById("postExcerpt").value = post.excerpt || ""; document.getElementById("postContent").value = post.content || ""; document.getElementById("postMetaTitle").value = post.metatitle || ""; document.getElementById("postMetaDescription").value = post.metadescription || ""; document.getElementById("postPublished").checked = post.ispublished; postModal.show(); } } catch (error) { console.error("Failed to load post:", error); showError("Failed to load post details"); } } async function savePost() { const id = document.getElementById("postId").value; const formData = { title: document.getElementById("postTitle").value, slug: document.getElementById("postSlug").value, excerpt: document.getElementById("postExcerpt").value, content: document.getElementById("postContent").value, metatitle: document.getElementById("postMetaTitle").value, metadescription: document.getElementById("postMetaDescription").value, ispublished: document.getElementById("postPublished").checked, }; if (!formData.title || !formData.slug || !formData.content) { showError("Please fill in all required fields"); return; } try { const url = id ? `/api/admin/blog/${id}` : "/api/admin/blog"; const method = id ? "PUT" : "POST"; const response = await fetch(url, { method: method, headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(formData), }); const data = await response.json(); if (data.success) { showSuccess( id ? "Post updated successfully" : "Post created successfully" ); postModal.hide(); loadPosts(); } else { showError(data.message || "Failed to save post"); } } catch (error) { console.error("Failed to save post:", error); showError("Failed to save post"); } } async function deletePost(id, title) { if (!confirm(`Are you sure you want to delete "${title}"?`)) return; try { const response = await fetch(`/api/admin/blog/${id}`, { method: "DELETE", credentials: "include", }); const data = await response.json(); if (data.success) { showSuccess("Post deleted successfully"); loadPosts(); } else { showError(data.message || "Failed to delete post"); } } catch (error) { console.error("Failed to delete post:", error); showError("Failed to delete post"); } } function slugify(text) { return text .toLowerCase() .replace(/[^\w\s-]/g, "") .replace(/[\s_-]+/g, "-") .replace(/^-+|-+$/g, ""); } async function logout() { try { const response = await fetch("/api/admin/logout", { method: "POST", credentials: "include", }); if (response.ok) window.location.href = "/admin/login.html"; } catch (error) { console.error("Logout failed:", error); } } function escapeHtml(text) { const map = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", }; return text.replace(/[&<>"']/g, (m) => map[m]); } function formatDate(dateString) { return new Date(dateString).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", }); } function showSuccess(message) { alert(message); } function showError(message) { alert("Error: " + message); }