feat: complete Knowledge Base category management and fix structure

- Added full CRUD UI for categories (create/edit/delete)
- Category form with name, slug, description, display order, active toggle
- Categories displayed as editable tags with delete icons
- Removed duplicate second implementation entirely
- Fixed file structure to have single component
- Updated package.json with solid-markdown dependency
- Integrated Markdown component into article detail page for proper rendering
This commit is contained in:
Ashwin Kumar 2026-04-06 18:39:20 +02:00
parent 44d4ce5b2a
commit 88a00db3bd

View file

@ -460,6 +460,59 @@ export default function KnowledgeBasePage() {
<Plus size={16} /> New Article <Plus size={16} /> New Article
</button> </button>
</div> </div>
</div>
{/* Category Management */}
<div class="px-6 py-4 bg-white border-b border-gray-200">
<div class="flex justify-between items-center mb-3">
<h3 class="font-bold text-gray-800">Categories</h3>
<button onClick={openCreateCategory} class="px-3 py-1 text-xs font-bold text-white bg-[#FF5E13] rounded">Add Category</button>
</div>
<Show when={catMode() === 'create' || catMode() === 'edit'}>
<div class="mb-4 p-4 border border-gray-200 rounded-lg bg-gray-50">
<h4 class="font-bold text-gray-700 mb-2">{catMode() === 'edit' ? 'Edit Category' : 'Create New Category'}</h4>
<div class="grid grid-cols-2 gap-4 mb-3">
<div>
<label class="block text-xs font-bold text-gray-500 mb-1">Name</label>
<input type="text" value={catName()} onInput={(e) => setCatName(e.currentTarget.value)} class="w-full px-3 py-2 border border-gray-300 rounded focus:ring-2 focus:ring-[#FF5E13] outline-none" placeholder="Category Name" />
</div>
<div>
<label class="block text-xs font-bold text-gray-500 mb-1">Slug (optional)</label>
<input type="text" value={catSlug()} onInput={(e) => setCatSlug(e.currentTarget.value)} class="w-full px-3 py-2 border border-gray-300 rounded focus:ring-2 focus:ring-[#FF5E13] outline-none" placeholder="url-friendly-slug" />
</div>
</div>
<div class="mb-3">
<label class="block text-xs font-bold text-gray-500 mb-1">Description</label>
<input type="text" value={catDescription()} onInput={(e) => setCatDescription(e.currentTarget.value)} class="w-full px-3 py-2 border border-gray-300 rounded focus:ring-2 focus:ring-[#FF5E13] outline-none" placeholder="Brief description" />
</div>
<div class="flex items-center gap-4 mb-3">
<label class="flex items-center gap-2">
<span class="text-sm text-gray-600">Display Order:</span>
<input type="number" value={catDisplayOrder()} onInput={(e) => setCatDisplayOrder(parseInt(e.currentTarget.value) || 0)} class="w-20 px-3 py-2 border border-gray-300 rounded focus:ring-2 focus:ring-[#FF5E13] outline-none" />
</label>
<label class="flex items-center gap-2">
<input type="checkbox" checked={catIsActive()} onChange={(e) => setCatIsActive(e.target.checked)} />
<span class="text-sm text-gray-600">Active</span>
</label>
</div>
<Show when={catError()}>
<p class="text-sm text-red-600 mb-2">{catError()}</p>
</Show>
<div class="flex gap-2">
<button onClick={handleCancelCategory} class="px-4 py-2 text-sm font-bold text-gray-600 hover:text-gray-800">Cancel</button>
<button onClick={handleSaveCategory} disabled={catSaving()} class="px-4 py-2 text-sm font-bold text-white bg-[#0F172A] hover:bg-[#1E293B] rounded disabled:opacity-50">{catSaving() ? 'Saving...' : 'Save Category'}</button>
</div>
</div>
</Show>
<div class="flex flex-wrap gap-2">
<For each={categories()}>{cat => (
<div class="flex items-center gap-1 px-3 py-1.5 bg-gray-100 rounded-full text-sm">
<span>{cat.name}</span>
<button onClick={() => openEditCategory(cat)} class="text-gray-500 hover:text-[#FF5E13]"><Edit2 size={12}/></button>
<button onClick={() => handleDeleteCategory(cat.id)} class="text-gray-500 hover:text-red-500"><Trash2 size={12}/></button>
</div>
)}</For>
</div>
</div> </div>
<Show when={view() === 'list'} fallback={ <Show when={view() === 'list'} fallback={