diff --git a/client-v3/src/components/MarkdownRenderer.vue b/client-v3/src/components/MarkdownRenderer.vue new file mode 100644 index 00000000..6be9a16d --- /dev/null +++ b/client-v3/src/components/MarkdownRenderer.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/client-v3/src/router/index.ts b/client-v3/src/router/index.ts index e4b2ede1..ca5ec386 100644 --- a/client-v3/src/router/index.ts +++ b/client-v3/src/router/index.ts @@ -22,7 +22,7 @@ const router = createRouter({ { path: '/about', name: 'about', - component: PlaceholderView, + component: () => import('@/views/AboutView.vue'), meta: { requiresAuth: false }, }, { @@ -124,14 +124,14 @@ const router = createRouter({ }, { path: '/help', - component: PlaceholderView, + component: () => import('@/views/HelpView.vue'), meta: { requiresAuth: false }, children: [ - { path: '', redirect: 'getting-started' }, + { path: '', redirect: '/help/getting-started' }, { name: 'help-doc', path: ':slug(.*)', - component: PlaceholderView, + component: () => import('@/views/help/HelpDocView.vue'), meta: { requiresAuth: false }, }, ], @@ -144,7 +144,7 @@ const router = createRouter({ }, { path: '/:pathMatch(.*)*', - redirect: '/404', + component: NotFoundView, }, ], }); diff --git a/client-v3/src/stores/help.ts b/client-v3/src/stores/help.ts new file mode 100644 index 00000000..c76ba219 --- /dev/null +++ b/client-v3/src/stores/help.ts @@ -0,0 +1,109 @@ +import log from 'loglevel'; +import Fuse from 'fuse.js'; +import { defineStore } from 'pinia'; + +interface HelpManifestEntry { + title: string; + slug: string; + path: string; + category: string; +} + +interface HelpState { + manifest: HelpManifestEntry[]; + documents: Record; + currentDocument: string | null; + loading: boolean; + error: string | null; + searchIndex: Fuse | null; + searchResults: HelpManifestEntry[]; +} + +export const useHelpStore = defineStore('help', { + state: (): HelpState => ({ + manifest: [], + documents: {}, + currentDocument: null, + loading: false, + error: null, + searchIndex: null, + searchResults: [], + }), + + getters: { + documentationManifest: (state) => state.manifest, + currentDocumentContent: (state) => + state.currentDocument ? state.documents[state.currentDocument] : null, + isLoading: (state) => state.loading, + searchResults: (state) => state.searchResults, + }, + + actions: { + async loadManifest() { + try { + const response = await fetch('/docs/manifest.json'); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + + const manifest: HelpManifestEntry[] = await response.json(); + this.manifest = manifest; + this.searchIndex = new Fuse(manifest, { + keys: ['title', 'path'], + threshold: 0.3, + includeScore: true, + }); + log.info(`Loaded documentation manifest with ${manifest.length} documents`); + } catch (error) { + log.error('Failed to load documentation manifest:', error); + this.error = 'Failed to load documentation manifest'; + } + }, + + async loadDocument(slug: string) { + if (this.documents[slug]) { + this.currentDocument = slug; + this.error = null; + return; + } + + this.loading = true; + const doc = this.manifest.find((d) => d.slug === slug); + + if (!doc) { + this.error = 'Document not found'; + this.loading = false; + return; + } + + try { + const response = await fetch(`/docs/${doc.path}`); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + + const content = await response.text(); + this.documents[slug] = content; + this.currentDocument = slug; + this.error = null; + } catch (error) { + log.error('Failed to load documentation:', error); + this.error = 'Failed to load documentation'; + } finally { + this.loading = false; + } + }, + + searchDocuments(query: string) { + if (!this.searchIndex) { + log.warn('Search index not initialized'); + return; + } + if (!query || query.trim() === '') { + this.searchResults = []; + return; + } + this.searchResults = this.searchIndex.search(query).map((r) => r.item); + }, + + clearSearch() { + this.searchResults = []; + }, + }, +}); diff --git a/client-v3/src/views/AboutView.vue b/client-v3/src/views/AboutView.vue new file mode 100644 index 00000000..6d38acfc --- /dev/null +++ b/client-v3/src/views/AboutView.vue @@ -0,0 +1,17 @@ + + + diff --git a/client-v3/src/views/HelpView.vue b/client-v3/src/views/HelpView.vue new file mode 100644 index 00000000..84c895a1 --- /dev/null +++ b/client-v3/src/views/HelpView.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/client-v3/src/views/HomeView.vue b/client-v3/src/views/HomeView.vue index 6f4002a6..9710f7df 100644 --- a/client-v3/src/views/HomeView.vue +++ b/client-v3/src/views/HomeView.vue @@ -1,24 +1,37 @@ - diff --git a/client-v3/src/views/help/HelpDocView.vue b/client-v3/src/views/help/HelpDocView.vue new file mode 100644 index 00000000..6bf9d584 --- /dev/null +++ b/client-v3/src/views/help/HelpDocView.vue @@ -0,0 +1,47 @@ + + +