Files
Inventory_frontend/app/composables/useMachineDetailDocuments.ts

147 lines
4.3 KiB
TypeScript

/**
* Machine detail — document management sub-composable.
*
* Handles document loading, upload, delete and preview state.
*/
import { ref, computed } from 'vue'
import { useDocuments } from '~/composables/useDocuments'
import { canPreviewDocument } from '~/utils/documentPreview'
type AnyRecord = Record<string, unknown>
interface MachineDetailDocumentsDeps {
machine: Ref<AnyRecord | null>
}
export function useMachineDetailDocuments(deps: MachineDetailDocumentsDeps) {
const { machine } = deps
const {
uploadDocuments,
deleteDocument,
loadDocumentsByMachine,
loadDocumentsByProduct,
} = useDocuments()
// ---------------------------------------------------------------------------
// State
// ---------------------------------------------------------------------------
const machineDocumentFiles = ref<File[]>([])
const machineDocumentsUploading = ref(false)
const machineDocumentsLoaded = ref(false)
const previewDocument = ref<AnyRecord | null>(null)
const previewVisible = ref(false)
// ---------------------------------------------------------------------------
// Computed
// ---------------------------------------------------------------------------
const machineDocumentsList = computed(
() => ((machine.value as AnyRecord)?.documents as AnyRecord[]) || [],
)
// ---------------------------------------------------------------------------
// Methods
// ---------------------------------------------------------------------------
const refreshMachineDocuments = async () => {
if (!machine.value?.id) return
const result: any = await loadDocumentsByMachine(machine.value.id as string, { updateStore: false })
if (result.success && machine.value) {
machine.value.documents = result.data || []
machineDocumentsLoaded.value = true
}
}
const handleMachineFilesAdded = async (files: File[]) => {
if (!files.length || !machine.value?.id) return
machineDocumentsUploading.value = true
try {
const result: any = await uploadDocuments(
{ files, context: { machineId: machine.value.id } } as any,
{ updateStore: false },
)
if (result.success && machine.value) {
const newDocs = (result.data as AnyRecord[]) || []
machine.value.documents = [
...newDocs,
...((machine.value.documents as AnyRecord[]) || []),
]
machineDocumentFiles.value = []
}
} finally {
machineDocumentsUploading.value = false
}
}
const removeMachineDocument = async (documentId: string) => {
if (!documentId) return
const result: any = await deleteDocument(documentId, { updateStore: false })
if (result.success && machine.value) {
machine.value.documents = ((machine.value.documents as AnyRecord[]) || []).filter(
(doc) => doc.id !== documentId,
)
}
}
const openPreview = (doc: AnyRecord) => {
if (!canPreviewDocument(doc)) return
previewDocument.value = doc
previewVisible.value = true
}
const closePreview = () => {
previewVisible.value = false
previewDocument.value = null
}
const loadProductDocuments = async (machineProductLinks: AnyRecord[]) => {
const productIds = machineProductLinks
.map((link) => {
const p = link.product as AnyRecord | string | null
if (typeof p === 'string') return p.split('/').pop() || null
return (p as AnyRecord)?.id as string | null
})
.filter((id): id is string => !!id)
const results = await Promise.allSettled(
productIds.map(async (id) => {
const result: any = await loadDocumentsByProduct(id, { updateStore: false })
if (result.success && Array.isArray(result.data)) {
return { id, docs: result.data as AnyRecord[] }
}
return { id, docs: [] }
}),
)
const map = new Map<string, AnyRecord[]>()
results.forEach((r) => {
if (r.status === 'fulfilled' && r.value.docs.length) {
map.set(r.value.id, r.value.docs)
}
})
return map
}
return {
// State
machineDocumentFiles,
machineDocumentsUploading,
machineDocumentsLoaded,
previewDocument,
previewVisible,
// Computed
machineDocumentsList,
// Methods
refreshMachineDocuments,
handleMachineFilesAdded,
removeMachineDocument,
openPreview,
closePreview,
loadProductDocuments,
}
}