Interactive Customer Service Knowledge Base
Find answers to common questions and support issues.
Categories
Articles
Welcome to the Knowledge Base
Select an article from the left to view its content here.
Category:
All Articles
| Title | Category | Actions |
|---|
Add New Article
No articles found.
`; return; } articlesList.innerHTML = articlesToRender.map(article => `${article.title}` ).join(''); }; const displayArticle = (articleId) => { const article = KB_ARTICLES.find(a => a.id === articleId); if (!article) { initialMessage.classList.remove('hidden'); articleContentWrapper.classList.add('hidden'); activeArticleId = null; return; } activeArticleId = articleId; document.querySelectorAll('.article-link').forEach(link => link.classList.remove('active')); const activeLink = document.querySelector(`.article-link[data-id='${articleId}']`); if(activeLink) activeLink.classList.add('active'); initialMessage.classList.add('hidden'); articleContentWrapper.classList.remove('hidden'); articleTitle.textContent = article.title; articleCategory.textContent = article.category; articleContent.innerHTML = article.content; }; const filterAndRenderArticles = () => { const searchTerm = searchInput.value.toLowerCase(); const activeCategoryBtn = categoriesContainer.querySelector('.category-btn.active'); const activeCategory = activeCategoryBtn ? activeCategoryBtn.dataset.category : 'All'; let filteredArticles = KB_ARTICLES; if (activeCategory !== 'All') filteredArticles = filteredArticles.filter(a => a.category === activeCategory); if (searchTerm) filteredArticles = filteredArticles.filter(a => a.title.toLowerCase().includes(searchTerm) || a.content.toLowerCase().includes(searchTerm)); renderArticles(filteredArticles); }; // --- CRUD & FORM LOGIC --- const resetForm = () => { editingArticleId = null; formHeader.textContent = "Add New Article"; formTitle.value = ''; formCategory.value = ''; formContent.value = ''; cancelBtn.classList.add('hidden'); }; const populateFormForEdit = (articleId) => { const article = KB_ARTICLES.find(a => a.id === articleId); if (article) { editingArticleId = article.id; formHeader.textContent = "Edit Article"; formTitle.value = article.title; formCategory.value = article.category; formContent.value = article.content; cancelBtn.classList.remove('hidden'); } }; const handleSave = () => { const title = formTitle.value.trim(); const category = formCategory.value.trim(); const content = formContent.value.trim(); if (!title || !category || !content) { alert('Please fill all fields.'); return; } if (editingArticleId) { // Update const index = KB_ARTICLES.findIndex(a => a.id === editingArticleId); if (index > -1) { KB_ARTICLES[index] = { ...KB_ARTICLES[index], title, category, content }; } } else { // Create const newId = KB_ARTICLES.length > 0 ? Math.max(...KB_ARTICLES.map(a => a.id)) + 1 : 1; KB_ARTICLES.push({ id: newId, title, category, content }); } resetForm(); renderAll(); // If the updated article was being viewed, refresh its content if(activeArticleId && activeArticleId === editingArticleId) displayArticle(activeArticleId); }; const handleDelete = (articleId) => { if (confirm('Are you sure you want to delete this article?')) { KB_ARTICLES = KB_ARTICLES.filter(a => a.id !== articleId); if (activeArticleId === articleId) { displayArticle(null); // Clear view if deleted article was active } renderAll(); } }; // --- EVENT HANDLERS --- const handleCategoryClick = (e) => { if (e.target.classList.contains('category-btn')) { categoriesContainer.querySelectorAll('.category-btn').forEach(btn => btn.classList.remove('active')); e.target.classList.add('active'); filterAndRenderArticles(); } }; const handleArticleClick = (e) => { e.preventDefault(); const link = e.target.closest('.article-link'); if (link) displayArticle(parseInt(link.dataset.id)); }; const handleManageTableClick = (e) => { const target = e.target; const id = parseInt(target.closest('tr')?.querySelector('.edit-btn, .delete-btn')?.dataset.id); if (target.classList.contains('edit-btn')) populateFormForEdit(id); if (target.classList.contains('delete-btn')) handleDelete(id); }; const generatePDF = () => { if (!activeArticleId) return; const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-content'); pdfContent.querySelector('#pdf-button-container')?.classList.add('hidden'); html2canvas(pdfContent, { scale: 2, useCORS: true }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pdfWidth - 20; const imgHeight = (canvas.height * imgWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight); const safeTitle = articleTitle.textContent.replace(/[^a-z0-9]/gi, '_').toLowerCase(); pdf.save(`kb-${safeTitle}.pdf`); pdfContent.querySelector('#pdf-button-container')?.classList.remove('hidden'); }); }; // --- ATTACH LISTENERS --- // Nav prevBtn.addEventListener('click', () => showTab('kb')); nextBtn.addEventListener('click', () => showTab('manage')); tabButtons.kb.addEventListener('click', () => showTab('kb')); tabButtons.manage.addEventListener('click', () => showTab('manage')); // KB View searchInput.addEventListener('input', filterAndRenderArticles); categoriesContainer.addEventListener('click', handleCategoryClick); articlesList.addEventListener('click', handleArticleClick); downloadPdfBtn.addEventListener('click', generatePDF); // Manage View manageTableBody.addEventListener('click', handleManageTableClick); saveBtn.addEventListener('click', handleSave); cancelBtn.addEventListener('click', resetForm); // --- INITIALIZATION --- renderAll(); });