feat(phase-4): frontend data layer — API client (13 new functions), folders store, documents store extensions, routes
- Extended listDocuments to accept folderId, q, sort, order query params - Added 6 folder API functions: listFolders, createFolder, getFolder, renameFolder, deleteFolder, moveDocument - Added 4 share API functions: createShare, listShares, deleteShare, getSharedWithMe - Added 2 preference API functions: getMyPreferences, updateMyPreferences - Added getDocumentContentUrl helper (returns URL string, no fetch) - Created useFoldersStore with full CRUD, navigation state, and breadcrumb support - Extended useDocumentsStore with currentFolderId, searchQuery, sortField, sortOrder refs - Added debounced searchQuery watcher (300ms, 2-char minimum, T-04-08-03) - Added shareDocument, revokeShare, listShares actions to documents store - Added /folders/:folderId and /shared routes with requiresAuth guard
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import * as api from '../api/client.js'
|
||||
|
||||
export const useFoldersStore = defineStore('folders', () => {
|
||||
const folders = ref([])
|
||||
const currentFolderId = ref(null)
|
||||
const breadcrumb = ref([])
|
||||
const loading = ref(false)
|
||||
const error = ref(null)
|
||||
|
||||
async function fetchFolders(parentId = null) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const data = await api.listFolders(parentId)
|
||||
folders.value = data
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to load folders'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function createFolder(name, parentId = null) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const folder = await api.createFolder(name, parentId)
|
||||
folders.value.push(folder)
|
||||
return folder
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to create folder'
|
||||
throw e
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function renameFolder(folderId, name) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const updated = await api.renameFolder(folderId, name)
|
||||
const idx = folders.value.findIndex(f => f.id === folderId)
|
||||
if (idx !== -1) folders.value[idx] = updated
|
||||
return updated
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to rename folder'
|
||||
throw e
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFolder(folderId) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
await api.deleteFolder(folderId)
|
||||
folders.value = folders.value.filter(f => f.id !== folderId)
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to delete folder'
|
||||
throw e
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function navigateTo(folderId) {
|
||||
currentFolderId.value = folderId
|
||||
if (folderId != null) {
|
||||
try {
|
||||
const data = await api.getFolder(folderId)
|
||||
breadcrumb.value = data.breadcrumb || []
|
||||
} catch (e) {
|
||||
breadcrumb.value = []
|
||||
}
|
||||
} else {
|
||||
breadcrumb.value = []
|
||||
}
|
||||
}
|
||||
|
||||
return { folders, currentFolderId, breadcrumb, loading, error, fetchFolders, createFolder, renameFolder, deleteFolder, navigateTo }
|
||||
})
|
||||
Reference in New Issue
Block a user