137 lines
3.8 KiB
TypeScript
137 lines
3.8 KiB
TypeScript
/**
|
|
* Reactive document management for entity items (ComponentItem, PieceItem).
|
|
*
|
|
* Handles document CRUD operations, preview modal state, and lazy loading.
|
|
* Display helpers (formatSize, shouldInlinePdf, etc.) are imported from
|
|
* shared/utils/documentDisplayUtils.ts.
|
|
*/
|
|
|
|
import { ref, computed, watch } from 'vue'
|
|
import { useDocuments } from '~/composables/useDocuments'
|
|
import { canPreviewDocument } from '~/utils/documentPreview'
|
|
|
|
export interface EntityDocumentsDeps {
|
|
entity: () => any
|
|
entityType: 'composant' | 'piece'
|
|
}
|
|
|
|
export function useEntityDocuments(deps: EntityDocumentsDeps) {
|
|
const { entity, entityType } = deps
|
|
const { uploadDocuments, deleteDocument, updateDocument } = useDocuments()
|
|
|
|
const loadDocumentsFn = entityType === 'composant'
|
|
? useDocuments().loadDocumentsByComponent
|
|
: useDocuments().loadDocumentsByPiece
|
|
|
|
const selectedFiles = ref<File[]>([])
|
|
const uploadingDocuments = ref(false)
|
|
const loadingDocuments = ref(false)
|
|
const documentsLoaded = ref(!!(entity().documents && entity().documents.length))
|
|
|
|
const documents = computed(() => entity().documents || [])
|
|
|
|
// Preview modal state
|
|
const previewDocument = ref<any>(null)
|
|
const previewVisible = ref(false)
|
|
|
|
const openPreview = (doc: any) => {
|
|
if (!canPreviewDocument(doc)) return
|
|
previewDocument.value = doc
|
|
previewVisible.value = true
|
|
}
|
|
|
|
const closePreview = () => {
|
|
previewVisible.value = false
|
|
previewDocument.value = null
|
|
}
|
|
|
|
// Document watchers
|
|
watch(
|
|
() => entity().documents,
|
|
(docs: any) => {
|
|
documentsLoaded.value = !!(docs && docs.length)
|
|
},
|
|
)
|
|
|
|
// CRUD operations
|
|
const refreshDocuments = async () => {
|
|
const e = entity()
|
|
if (!e?.id || e._structurePiece) return
|
|
loadingDocuments.value = true
|
|
try {
|
|
const result: any = await loadDocumentsFn(e.id, { updateStore: false })
|
|
if (result.success) {
|
|
e.documents = result.data || []
|
|
documentsLoaded.value = true
|
|
}
|
|
} finally {
|
|
loadingDocuments.value = false
|
|
}
|
|
}
|
|
|
|
const ensureDocumentsLoaded = async () => {
|
|
if (documentsLoaded.value || !entity()?.id) return
|
|
await refreshDocuments()
|
|
}
|
|
|
|
const handleFilesAdded = async (files: File[]) => {
|
|
const e = entity()
|
|
if (!files.length || !e?.id) return
|
|
uploadingDocuments.value = true
|
|
try {
|
|
const contextKey = entityType === 'composant' ? 'composantId' : 'pieceId'
|
|
const result: any = await uploadDocuments(
|
|
{ files, context: { [contextKey]: e.id } } as any,
|
|
{ updateStore: false } as any,
|
|
)
|
|
if (result.success) {
|
|
const newDocs = result.data || []
|
|
e.documents = [...newDocs, ...(e.documents || [])]
|
|
documentsLoaded.value = true
|
|
selectedFiles.value = []
|
|
}
|
|
} finally {
|
|
uploadingDocuments.value = false
|
|
}
|
|
}
|
|
|
|
const removeDocument = async (documentId: string) => {
|
|
if (!documentId) return
|
|
const result: any = await deleteDocument(documentId, { updateStore: false } as any)
|
|
if (result.success) {
|
|
const e = entity()
|
|
e.documents = (e.documents || []).filter((doc: any) => doc.id !== documentId)
|
|
}
|
|
}
|
|
|
|
const editDocument = async (id: string, data: { name?: string; type?: string }) => {
|
|
const result: any = await updateDocument(id, data)
|
|
if (result.success) {
|
|
const e = entity()
|
|
const docs = e.documents || []
|
|
const index = docs.findIndex((doc: any) => doc.id === id)
|
|
if (index !== -1) {
|
|
docs[index] = { ...docs[index], ...data }
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
return {
|
|
documents,
|
|
selectedFiles,
|
|
uploadingDocuments,
|
|
loadingDocuments,
|
|
documentsLoaded,
|
|
previewDocument,
|
|
previewVisible,
|
|
openPreview,
|
|
closePreview,
|
|
refreshDocuments,
|
|
ensureDocumentsLoaded,
|
|
handleFilesAdded,
|
|
removeDocument,
|
|
editDocument,
|
|
}
|
|
}
|