import { useState, useCallback, useRef } from "react"; /** * Koenig expects `fileUploader.useFileUpload(type)` — a React hook it * calls internally for each card type ("image", "audio", "file", etc.). * * `makeFileUploader(csrfToken, uploadUrls)` returns the object Koenig wants: * { useFileUpload: (type) => { upload, progress, isLoading, errors, filesNumber } } * * `uploadUrls` is an object: { image, media, file } * For backwards compat, a plain string is treated as the image URL. */ const URL_KEY_MAP = { image: { urlKey: "image", responseKey: "images" }, audio: { urlKey: "media", responseKey: "media" }, video: { urlKey: "media", responseKey: "media" }, mediaThumbnail: { urlKey: "image", responseKey: "images" }, file: { urlKey: "file", responseKey: "files" }, }; export default function makeFileUploader(csrfToken, uploadUrls) { // Normalise: string → object with all keys pointing to same URL const urls = typeof uploadUrls === "string" ? { image: uploadUrls, media: uploadUrls, file: uploadUrls } : uploadUrls || {}; return { fileTypes: { image: { mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'] }, audio: { mimeTypes: ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/mp4', 'audio/aac'] }, video: { mimeTypes: ['video/mp4', 'video/webm', 'video/ogg'] }, mediaThumbnail: { mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] }, file: { mimeTypes: [] }, }, useFileUpload(type) { const mapping = URL_KEY_MAP[type] || URL_KEY_MAP.image; const [progress, setProgress] = useState(0); const [isLoading, setIsLoading] = useState(false); const [errors, setErrors] = useState([]); const [filesNumber, setFilesNumber] = useState(0); const csrfRef = useRef(csrfToken); const urlRef = useRef(urls[mapping.urlKey] || urls.image || "/editor-api/images/upload/"); const responseKeyRef = useRef(mapping.responseKey); const upload = useCallback(async (files) => { const fileList = Array.from(files); setFilesNumber(fileList.length); setIsLoading(true); setErrors([]); setProgress(0); const results = []; for (let i = 0; i < fileList.length; i++) { const file = fileList[i]; const formData = new FormData(); formData.append("file", file); try { const resp = await fetch(urlRef.current, { method: "POST", body: formData, headers: { "X-CSRFToken": csrfRef.current || "", }, }); if (!resp.ok) { const err = await resp.json().catch(() => ({})); const msg = err.errors?.[0]?.message || `Upload failed (${resp.status})`; setErrors((prev) => [ ...prev, { message: msg, fileName: file.name }, ]); continue; } const data = await resp.json(); const fileUrl = data[responseKeyRef.current]?.[0]?.url; if (fileUrl) { results.push({ url: fileUrl, fileName: file.name }); } } catch (e) { setErrors((prev) => [ ...prev, { message: e.message, fileName: file.name }, ]); } setProgress(Math.round(((i + 1) / fileList.length) * 100)); } setIsLoading(false); return results; }, []); return { upload, progress, isLoading, errors, filesNumber }; }, }; }