#84
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 33s
Build and Push Docker Images / build-frontend (push) Successful in 3m25s

This commit is contained in:
2026-01-26 21:52:24 +01:00
parent ca2020b9c6
commit c56fcfbd14
3 changed files with 100 additions and 141 deletions

View File

@@ -16,15 +16,18 @@ export const useWikiTree = () => {
const isLoading = useState<boolean>('wiki-loading', () => false)
const isSidebarOpen = useState<boolean>('wiki-sidebar-open', () => true)
// COMPUTED TREE
const tree = computed(() => {
// NEU: Suchbegriff State
const searchQuery = useState<string>('wiki-search-query', () => '')
// 1. Basis-Baum bauen (Hierarchie & Sortierung)
const baseTree = computed(() => {
const rawItems = items.value || []
if (!rawItems.length) return []
const roots: WikiPageItem[] = []
const lookup: Record<string, WikiPageItem> = {}
// Init Lookup
// Init Lookup (Shallow Copy um Originaldaten nicht zu mutieren)
rawItems.forEach(item => {
lookup[item.id] = { ...item, children: [] }
})
@@ -39,7 +42,7 @@ export const useWikiTree = () => {
}
})
// Sort: Folders first, then Alphabetical
// Sort Helper
const sortNodes = (nodes: WikiPageItem[]) => {
nodes.sort((a, b) => {
if (a.isFolder !== b.isFolder) return a.isFolder ? -1 : 1
@@ -54,47 +57,67 @@ export const useWikiTree = () => {
return roots
})
// ACTIONS
// 2. NEU: Gefilterter Baum (basiert auf baseTree + searchQuery)
const filteredTree = computed(() => {
const query = searchQuery.value.toLowerCase().trim()
// Wenn keine Suche: Gib originalen Baum zurück
if (!query) return baseTree.value
// Rekursive Filterfunktion
const filterNodes = (nodes: WikiPageItem[]): WikiPageItem[] => {
return nodes.reduce((acc: WikiPageItem[], node) => {
// Matcht der Knoten selbst?
const matchesSelf = node.title.toLowerCase().includes(query)
// Matchen Kinder? (Rekursion)
const filteredChildren = node.children ? filterNodes(node.children) : []
// Wenn selbst matcht ODER Kinder matchen -> behalten
if (matchesSelf || filteredChildren.length > 0) {
// Wir erstellen eine Kopie des Knotens mit den gefilterten Kindern
acc.push({
...node,
children: filteredChildren
})
}
return acc
}, [])
}
return filterNodes(baseTree.value)
})
// ACTIONS
const loadTree = async () => {
isLoading.value = true
try {
const data = await $api<WikiPageItem[]>('/api/wiki/tree', { method: 'GET' })
items.value = data
} catch (e) {
console.error('Wiki Tree Load Error', e)
} finally {
isLoading.value = false
}
} catch (e) { console.error(e) }
finally { isLoading.value = false }
}
// Rein API-basierte Funktion ohne UI-Logik
const createItem = async (title: string, parentId: string | null, isFolder: boolean) => {
try {
const newItem = await $api('/api/wiki', {
method: 'POST',
body: { title, parentId, isFolder }
})
const newItem = await $api('/api/wiki', { method: 'POST', body: { title, parentId, isFolder } })
await loadTree()
return newItem
} catch (e) {
throw e // Fehler weiterwerfen, damit UI reagieren kann
}
} catch (e) { throw e }
}
// Rein API-basierte Funktion ohne UI-Logik
const deleteItem = async (id: string) => {
try {
await $api(`/api/wiki/${id}`, { method: 'DELETE' })
await loadTree()
return true
} catch (e) {
throw e
}
} catch (e) { throw e }
}
return {
tree,
tree: filteredTree, // Wir geben jetzt immer den (evtl. gefilterten) Baum zurück
searchQuery, // Damit die UI das Input-Feld binden kann
items,
isLoading,
isSidebarOpen,