Files
Inventory/frontend/app/composables/useDocuments.ts
r-dev 201485552a fix(ui) : remove legacy edit pages and history composables, unify create/edit forms
Consolidate create and edit pages into single create pages with edit mode support.
Remove obsolete catalog pages, history composables, and fix remaining code review issues.
Include migration to relink orphaned custom fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:19:50 +02:00

328 lines
9.7 KiB
TypeScript

import { ref } from 'vue'
import { useApi } from './useApi'
import { useToast } from './useToast'
import { extractCollection, extractTotal } from '~/shared/utils/apiHelpers'
export interface Document {
id: string
name: string
filename: string
mimeType: string
size: number
fileUrl: string
downloadUrl: string
type?: string
/** @deprecated Legacy Base64 data URI — use fileUrl instead */
path?: string
createdAt?: string
siteId?: string
machineId?: string
composantId?: string
productId?: string
pieceId?: string
site?: { id: string; name?: string } | null
machine?: { id: string; name?: string } | null
composant?: { id: string; name?: string } | null
piece?: { id: string; name?: string } | null
product?: { id: string; name?: string } | null
}
export interface UploadContext {
siteId?: string
machineId?: string
composantId?: string
productId?: string
pieceId?: string
type?: string
}
export interface DocumentResult {
success: boolean
data?: Document | Document[]
error?: string
}
interface LoadDocumentsOptions {
search?: string
page?: number
itemsPerPage?: number
orderBy?: string
orderDir?: 'asc' | 'desc'
attachmentFilter?: string
type?: string
force?: boolean
}
const documents = ref<Document[]>([])
const total = ref(0)
const loading = ref(false)
const loaded = ref(false)
export function useDocuments() {
const { get, patch, postFormData, delete: del } = useApi()
const { showError, showSuccess } = useToast()
const loadFromEndpoint = async (
endpoint: string,
{ updateStore = false, itemsPerPage }: { updateStore?: boolean; itemsPerPage?: number } = {},
): Promise<DocumentResult> => {
loading.value = true
try {
const url = itemsPerPage ? `${endpoint}${endpoint.includes('?') ? '&' : '?'}itemsPerPage=${itemsPerPage}` : endpoint
const result = await get(url)
if (result.success) {
const data = extractCollection(result.data)
if (updateStore) {
documents.value = data
}
return { success: true, data }
}
if (result.error) {
showError(result.error)
}
return result as DocumentResult
} catch (error) {
const err = error as Error
console.error(`Erreur lors du chargement des documents (${endpoint}):`, error)
showError('Impossible de charger les documents')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const loadDocuments = async (options: LoadDocumentsOptions = {}): Promise<DocumentResult> => {
const {
search = '',
page = 1,
itemsPerPage = 30,
orderBy = 'createdAt',
orderDir = 'desc',
attachmentFilter = 'all',
type = 'all',
force = false,
} = options
if (!force && loaded.value && !search && page === 1 && attachmentFilter === 'all' && type === 'all') {
return { success: true, data: documents.value }
}
if (loading.value) {
return { success: true, data: documents.value }
}
loading.value = true
try {
const params = new URLSearchParams()
params.set('itemsPerPage', String(itemsPerPage))
params.set('page', String(page))
if (search && search.trim()) {
params.set('name', search.trim())
}
if (attachmentFilter && attachmentFilter !== 'all') {
params.set(`exists[${attachmentFilter}]`, 'true')
}
if (type && type !== 'all') {
params.set('type', type)
}
params.set(`order[${orderBy}]`, orderDir)
const result = await get(`/documents?${params.toString()}`)
if (result.success) {
const items = extractCollection(result.data)
documents.value = items
total.value = extractTotal(result.data, items.length)
loaded.value = true
return { success: true, data: items }
}
if (result.error) {
showError(result.error)
}
return result as DocumentResult
} catch (error) {
const err = error as Error
console.error('Erreur lors du chargement des documents:', error)
showError('Impossible de charger les documents')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const loadDocumentsBySite = async (
siteId: string,
options: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!siteId) {
return { success: false, error: 'Aucun site sélectionné' }
}
return loadFromEndpoint(`/documents/site/${siteId}`, { updateStore: options.updateStore ?? false })
}
const loadDocumentsByMachine = async (
machineId: string,
options: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!machineId) {
return { success: false, error: 'Aucune machine sélectionnée' }
}
return loadFromEndpoint(`/documents/machine/${machineId}`, { updateStore: options.updateStore ?? false })
}
const loadDocumentsByComponent = async (
componentId: string,
options: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!componentId) {
return { success: false, error: 'Aucun composant sélectionné' }
}
return loadFromEndpoint(`/documents/composant/${componentId}`, { updateStore: options.updateStore ?? false })
}
const loadDocumentsByProduct = async (
productId: string,
options: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!productId) {
return { success: false, error: 'Aucun produit sélectionné' }
}
return loadFromEndpoint(`/documents/product/${productId}`, { updateStore: options.updateStore ?? false })
}
const loadDocumentsByPiece = async (
pieceId: string,
options: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!pieceId) {
return { success: false, error: 'Aucune pièce sélectionnée' }
}
return loadFromEndpoint(`/documents/piece/${pieceId}`, { updateStore: options.updateStore ?? false })
}
const uploadDocuments = async (
{ files, context = {} }: { files: File[]; context?: UploadContext },
{ updateStore = false }: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!files.length) {
return { success: false, error: 'Aucun fichier sélectionné' }
}
loading.value = true
const created: Document[] = []
try {
for (const file of files) {
const formData = new FormData()
formData.append('file', file)
formData.append('name', file.name)
if (context.type) formData.append('type', context.type)
if (context.siteId) formData.append('siteId', context.siteId)
if (context.machineId) formData.append('machineId', context.machineId)
if (context.composantId) formData.append('composantId', context.composantId)
if (context.productId) formData.append('productId', context.productId)
if (context.pieceId) formData.append('pieceId', context.pieceId)
const result = await postFormData('/documents', formData)
if (result.success) {
created.push(result.data as Document)
showSuccess(`Document "${file.name}" ajouté`)
} else if (result.error) {
showError(`Erreur sur ${file.name} : ${result.error}`)
}
}
if (created.length) {
if (updateStore) {
documents.value = [...created, ...documents.value]
}
return { success: true, data: created }
}
return { success: false, error: 'Aucun document ajouté' }
} catch (error) {
const err = error as Error
console.error("Erreur lors de l'upload des documents:", error)
showError("Échec de l'ajout des documents")
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const deleteDocument = async (
id: string | number,
{ updateStore = false }: { updateStore?: boolean } = {},
): Promise<DocumentResult> => {
if (!id) {
return { success: false, error: 'Identifiant manquant' }
}
loading.value = true
try {
const result = await del(`/documents/${id}`)
if (result.success) {
if (updateStore) {
documents.value = documents.value.filter((doc) => doc.id !== id)
}
showSuccess('Document supprimé')
}
return result as DocumentResult
} catch (error) {
const err = error as Error
console.error('Erreur lors de la suppression du document:', error)
showError('Impossible de supprimer le document')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
const updateDocument = async (
id: string,
data: { name?: string; type?: string },
): Promise<DocumentResult> => {
loading.value = true
try {
const result = await patch(`/documents/${id}`, data)
if (result.success && result.data) {
const updated = result.data as Document
const index = documents.value.findIndex((doc) => doc.id === id)
if (index !== -1) {
documents.value[index] = { ...documents.value[index], ...updated }
}
showSuccess('Document mis à jour')
return { success: true, data: updated }
}
if (result.error) showError(result.error)
return result as DocumentResult
} catch (error) {
const err = error as Error
showError('Impossible de mettre à jour le document')
return { success: false, error: err.message }
} finally {
loading.value = false
}
}
return {
documents,
total,
loading,
loaded,
loadDocuments,
loadDocumentsBySite,
loadDocumentsByMachine,
loadDocumentsByComponent,
loadDocumentsByPiece,
loadDocumentsByProduct,
uploadDocuments,
updateDocument,
deleteDocument,
}
}