import { useState } from "react"; import { uploadImage, deleteImage } from "../../api/images"; import { useToast } from "../../context/ToastContext"; import FileDropzone from "../../components/FileDropzone"; import AuthImage from "../../components/AuthImage"; import StorageBar from "../../components/StorageBar"; import Button from "../../components/ui/Button"; import { EmptyState } from "../../components/ui/Misc"; import { ConfirmDialog } from "../../components/ui/Modal"; import Modal from "../../components/ui/Modal"; import { Field, Input } from "../../components/ui/Field"; import { IMAGE_ACCEPT } from "../../utils/constants"; import { formatBytes } from "../../utils/format"; export default function ImagesTab({ templateId, images, storage, reloadImages, reloadStorage, }) { const toast = useToast(); const [pendingFile, setPendingFile] = useState(null); const [caption, setCaption] = useState(""); const [uploading, setUploading] = useState(false); const [progress, setProgress] = useState(0); const [toDelete, setToDelete] = useState(null); const [deleting, setDeleting] = useState(false); const handleSelected = (file) => { setPendingFile(file); setCaption(""); }; const handleUpload = async () => { if (!pendingFile) return; setUploading(true); setProgress(0); try { await uploadImage(templateId, pendingFile, caption, setProgress); await Promise.all([reloadImages(), reloadStorage()]); toast.success("Imagen subida correctamente."); setPendingFile(null); setCaption(""); } catch (err) { toast.error(err.message); } finally { setUploading(false); setProgress(0); } }; const confirmDelete = async () => { setDeleting(true); try { await deleteImage(templateId, toDelete.id); await Promise.all([reloadImages(), reloadStorage()]); toast.success("Imagen eliminada."); setToDelete(null); } catch (err) { toast.error(err.message); } finally { setDeleting(false); } }; return (
{images.length === 0 ? (
) : (
{images.map((img) => (
{img.original_filename}
{formatBytes(img.size_bytes)} {img.caption ? ` · ${img.caption}` : ""}
))}
)}

Espacio

Consejo

Añade una descripción a cada imagen. La IA la usa para decidir a qué pregunta corresponde cada imagen al generar el examen.

{/* Modal de caption antes de subir */} !uploading && setPendingFile(null)} title="Subir imagen" footer={ <> } >

Archivo: {pendingFile?.name} ( {formatBytes(pendingFile?.size)})

setCaption(e.target.value)} placeholder="Ej. Diagrama del ciclo del agua" maxLength={500} /> {uploading && (
)} setToDelete(null)} />
); }