From 95af9c27886d49652c6208bef3cadd2d07634908 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Fri, 20 Mar 2026 16:19:08 +0100 Subject: [PATCH] feat(management-parity): replace employee/kb alias routes with real solid pages --- src/routes/admin/employees.tsx | 8 +- src/routes/admin/employees/create.tsx | 20 +--- src/routes/admin/kb.tsx | 8 +- src/routes/admin/kb/articles.tsx | 10 +- src/routes/admin/kb/articles/[id].tsx | 76 ++++++++++-- src/routes/admin/kb/articles/[id]/edit.tsx | 133 ++++++++++++++++++++- src/routes/admin/kb/articles/new.tsx | 10 +- src/routes/admin/kb/categories.tsx | 10 +- 8 files changed, 219 insertions(+), 56 deletions(-) diff --git a/src/routes/admin/employees.tsx b/src/routes/admin/employees.tsx index 80fee41..03666be 100644 --- a/src/routes/admin/employees.tsx +++ b/src/routes/admin/employees.tsx @@ -58,7 +58,11 @@ function isActive(e: Employee): boolean { return s === 'ACTIVE' || s === 'TRUE' || s === '1'; } -export default function EmployeesPage() { +type EmployeesPageProps = { + initialView?: 'list' | 'create'; +}; + +export default function EmployeesPage(props: EmployeesPageProps = {}) { const navigate = useNavigate(); const [searchParams] = useSearchParams(); @@ -66,7 +70,7 @@ export default function EmployeesPage() { const [roles] = createResource(loadRoles); // tabs: list | create - const [view, setView] = createSignal<'list' | 'create'>('list'); + const [view, setView] = createSignal<'list' | 'create'>(props.initialView || 'list'); onMount(() => { if (searchParams.tab === 'create') { diff --git a/src/routes/admin/employees/create.tsx b/src/routes/admin/employees/create.tsx index e042261..cca7af6 100644 --- a/src/routes/admin/employees/create.tsx +++ b/src/routes/admin/employees/create.tsx @@ -1,19 +1,5 @@ -import { onMount } from 'solid-js'; -import { useNavigate } from '@solidjs/router'; -import AdminShell from '~/components/AdminShell'; +import EmployeesPage from '~/routes/admin/employees'; -export default function CreateEmployeeAliasPage() { - const navigate = useNavigate(); - - onMount(() => { - navigate('/admin/employees?tab=create', { replace: true }); - }); - - return ( - -
-

Redirecting to employee create form...

-
-
- ); +export default function CreateEmployeePage() { + return ; } diff --git a/src/routes/admin/kb.tsx b/src/routes/admin/kb.tsx index 48ee1de..23a0273 100644 --- a/src/routes/admin/kb.tsx +++ b/src/routes/admin/kb.tsx @@ -45,8 +45,12 @@ async function loadArticles(): Promise { } } -export default function KbPage() { - const [tab, setTab] = createSignal<'categories' | 'articles' | 'create-article'>('categories'); +type KbPageProps = { + initialTab?: 'categories' | 'articles' | 'create-article'; +}; + +export default function KbPage(props: KbPageProps = {}) { + const [tab, setTab] = createSignal<'categories' | 'articles' | 'create-article'>(props.initialTab || 'categories'); // Categories resource const [categories, { refetch: refetchCategories }] = createResource(loadCategories); diff --git a/src/routes/admin/kb/articles.tsx b/src/routes/admin/kb/articles.tsx index d2195ad..b17b7cd 100644 --- a/src/routes/admin/kb/articles.tsx +++ b/src/routes/admin/kb/articles.tsx @@ -1,9 +1,5 @@ -import { onMount } from 'solid-js'; -import { useNavigate } from '@solidjs/router'; -import AdminShell from '~/components/AdminShell'; +import KbPage from '~/routes/admin/kb'; -export default function KbArticlesAliasPage() { - const navigate = useNavigate(); - onMount(() => navigate('/admin/kb', { replace: true })); - return

Redirecting to knowledge base...

; +export default function KbArticlesPage() { + return ; } diff --git a/src/routes/admin/kb/articles/[id].tsx b/src/routes/admin/kb/articles/[id].tsx index 18b61c3..1cc37ce 100644 --- a/src/routes/admin/kb/articles/[id].tsx +++ b/src/routes/admin/kb/articles/[id].tsx @@ -1,17 +1,77 @@ -import { onMount } from 'solid-js'; -import { A, useNavigate, useParams } from '@solidjs/router'; +import { A, useParams } from '@solidjs/router'; +import { createResource, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; -export default function KbArticleAliasPage() { - const navigate = useNavigate(); +const API = '/api/gateway'; + +type KbArticle = { + id: string; + title: string; + slug?: string; + content?: string; + body?: string; + status?: string; + category?: string; + category_id?: string; + updated_at?: string; + created_at?: string; +}; + +async function loadArticle(id: string): Promise { + try { + const res = await fetch(`${API}/api/admin/kb/articles/${id}`); + if (!res.ok) return null; + return res.json(); + } catch { + return null; + } +} + +export default function KbArticleDetailPage() { const params = useParams(); - onMount(() => navigate('/admin/kb', { replace: true })); + const [article] = createResource(() => params.id, loadArticle); + return ( -
-

Redirecting article {params.id} to knowledge base module...

- +
+
+

KB Article Detail

+

Metadata and safe content preview for this article.

+
+
+ + +

Loading article...

+
+ + +

Article not found.

+
+ + +
+
+

Metadata

+
+

Title

{article()!.title || '—'}

+

Status

{article()!.status || '—'}

+

Slug

{article()!.slug || '—'}

+

Category

{article()!.category || article()!.category_id || '—'}

+

Created At

{article()!.created_at ? new Date(article()!.created_at!).toLocaleString() : '—'}

+

Updated At

{article()!.updated_at ? new Date(article()!.updated_at!).toLocaleString() : '—'}

+
+
+ +
+

Content

+
{article()!.content || article()!.body || 'No content'}
+
+
+
); } diff --git a/src/routes/admin/kb/articles/[id]/edit.tsx b/src/routes/admin/kb/articles/[id]/edit.tsx index ad7dc5e..d2bbb05 100644 --- a/src/routes/admin/kb/articles/[id]/edit.tsx +++ b/src/routes/admin/kb/articles/[id]/edit.tsx @@ -1,17 +1,138 @@ -import { onMount } from 'solid-js'; import { A, useNavigate, useParams } from '@solidjs/router'; +import { createEffect, createResource, createSignal, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; -export default function KbArticleEditAliasPage() { +const API = '/api/gateway'; + +type KbArticle = { + id: string; + title: string; + slug?: string; + content?: string; + body?: string; + status?: string; + category_id?: string; +}; + +async function loadArticle(id: string): Promise { + try { + const res = await fetch(`${API}/api/admin/kb/articles/${id}`); + if (!res.ok) return null; + return res.json(); + } catch { + return null; + } +} + +export default function KbArticleEditPage() { const navigate = useNavigate(); const params = useParams(); - onMount(() => navigate('/admin/kb', { replace: true })); + const [article] = createResource(() => params.id, loadArticle); + const [title, setTitle] = createSignal(''); + const [slug, setSlug] = createSignal(''); + const [categoryId, setCategoryId] = createSignal(''); + const [status, setStatus] = createSignal('DRAFT'); + const [content, setContent] = createSignal(''); + const [saving, setSaving] = createSignal(false); + const [error, setError] = createSignal(''); + const [loaded, setLoaded] = createSignal(false); + + createEffect(() => { + const value = article(); + if (!value || loaded()) return; + setTitle(value.title || ''); + setSlug(value.slug || ''); + setCategoryId(value.category_id || ''); + setStatus(value.status || 'DRAFT'); + setContent(value.content || value.body || ''); + setLoaded(true); + }); + + const save = async (e: Event) => { + e.preventDefault(); + try { + setSaving(true); + setError(''); + const res = await fetch(`${API}/api/admin/kb/articles/${params.id}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + title: title(), + slug: slug(), + category_id: categoryId() || null, + status: status(), + content: content(), + }), + }); + if (!res.ok) throw new Error('Failed to save article'); + navigate(`/admin/kb/articles/${params.id}`); + } catch (err: any) { + setError(err.message || 'Failed to save article'); + } finally { + setSaving(false); + } + }; + return ( -
-

Redirecting article edit {params.id} to knowledge base module...

- +
+
+

Edit KB Article

+

Update article metadata, status, and content.

+
+
+ + +

Loading article...

+
+ + +

Article not found.

+
+ + +
+
+
+ + setTitle(e.currentTarget.value)} required /> +
+
+ + setSlug(e.currentTarget.value)} /> +
+
+ + setCategoryId(e.currentTarget.value)} /> +
+
+ + +
+
+ +