import { ref } from 'vue' import type { AnyObject } from '~/shared/composables/useApi' /** * Réponse JSON-LD de POST /api/uploaded_documents (groupe `uploaded_document:read`). * Seul l'IRI (`@id`) est exploité pour le poser sur la relation cible. */ export interface UploadedDocumentResponse { '@id': string originalFilename?: string mimeType?: string } /** * Upload d'un document générique vers l'infra partagée (ERP-154) : * POST /api/uploaded_documents en multipart/form-data, champ « file », via * `useApi()` (cookie JWT, parsing Hydra/erreurs). Renvoie l'IRI du document créé, * à poser sur la relation cible (ex: `carrier.dischargeDocument` — RG-4.02). * * Les erreurs (MIME hors whitelist / fichier trop volumineux → 422) sont relayées * (rethrow) à l'appelant pour un affichage inline sous le champ. `toast: false` par * défaut : pas de toast fourre-tout, le formulaire mappe le message au bon champ. */ export function useUpload() { // Indicateur d'upload en cours (désactivation UI / spinner éventuel). const uploading = ref(false) /** * Envoie `file` et renvoie l'IRI du `UploadedDocument` créé. * @throws relaie l'erreur réseau / 422 (MIME, taille) à l'appelant. */ async function upload(file: File, options: { toast?: boolean } = {}): Promise { const formData = new FormData() formData.append('file', file) uploading.value = true try { // useApi() détecte le FormData et n'impose pas de Content-Type JSON : // le navigateur pose lui-même la frontière multipart. const doc = await useApi().post( '/uploaded_documents', formData as unknown as AnyObject, { toast: options.toast ?? false }, ) return doc['@id'] } finally { uploading.value = false } } return { uploading, upload } }