Modificaciones en las vistas de las cargas masivas

This commit is contained in:
santiago
2025-10-02 16:03:28 -06:00
parent 8f2ee27711
commit fee9d92ed7
2 changed files with 173 additions and 115 deletions
@@ -1,49 +1,70 @@
'use client'
import axiosInstance from "@/utils/api-config";
import React, { useState } from "react";
import { Button, Form } from "react-bootstrap";
import { Button, Form, ProgressBar } from "react-bootstrap";
import { FaUpload } from "react-icons/fa";
export default function CargaMasiva() {
const [xlsx, setXlsx] = useState<File | null>(null)
const [xlsx, setXlsx] = useState<File | null>(null);
const [progress, setProgress] = useState<number>(0);
const [loading, setLoading] = useState<boolean>(false);
const validarExt = (file: File | null) => {
if (!file) return
const extPermitidas = /(.xlsx)$/i
if (!file) return;
const extPermitidas = /(.xlsx)$/i;
if (!extPermitidas.exec(file.name)) {
console.assert({ message: "Asegurate de ingresar un archivo .xlsx"})
setXlsx(null)
console.error("Asegúrate de ingresar un archivo .xlsx");
setXlsx(null);
} else {
setXlsx(file)
setXlsx(file);
}
}
};
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0] || null;
validarExt(file);
}
};
const enviarCargaMasiva = async () => {
if (!xlsx) return;
const formData = new FormData();
formData.append("file", xlsx);
formData.append("file", xlsx);
try {
setLoading(true);
setProgress(0);
const res = await axiosInstance.post(
"/cuestionario/carga-masiva",
formData,
{
headers: { "Content-Type": "multipart/form-data" }
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: (event) => {
if (event.total) {
const porcentaje = Math.round(
(event.loaded * 100) / event.total
);
setProgress(porcentaje);
}
},
}
);
//Falta hacer validacion
console.log("Carga masiva exitosa", res.data);
setTimeout(() => {
setProgress(100);
setLoading(false);
}, 500);
} catch (error) {
console.error("Carga masiva fallida", error);
setLoading(false);
setProgress(0);
}
};
return (
<div className="container-fluid my-4">
<div className="row mb-4">
@@ -51,7 +72,7 @@ export default function CargaMasiva() {
<div className="p-4 border rounded bg-light">
<h2 className="mb-2">Carga Masiva de Eventos</h2>
<p className="mb-0 text-muted">
Sube tu archivo excel para poder crear los ventos.
Sube tu archivo excel para poder crear los eventos.
</p>
</div>
</div>
@@ -66,28 +87,47 @@ export default function CargaMasiva() {
>
<FaUpload size={40} className="mb-2" />
<p className="mb-1">
{xlsx?.name || 'Arrastra aquí tu archivo o da click aquí para buscar'}
{xlsx?.name ||
"Arrastra aquí tu archivo o da click aquí para buscar"}
</p>
<p className="is-size-6">Tamaño máximo 20MB</p>
<p className="is-size-7">Si al momento de elegir uin archivo este no se selecciona, haga click en cancelar en la ventana emergente e intente de nuevo.</p>
<p className="is-size-7">
Si al momento de elegir un archivo este no se selecciona,
haga click en cancelar en la ventana emergente e intente de
nuevo.
</p>
</div>
<input
<input
id="xlsxInput"
type="file"
type="file"
accept=".xlsx"
style={{ display: 'none'}}
style={{ display: "none" }}
onChange={handleFileChange}
/>
/>
</Form.Group>
<div className="d-flex gap-2">
<div className="d-flex gap-2 mt-3">
<Button
variant="info"
disabled={!xlsx}
onClick={enviarCargaMasiva}>
Enviar archivo
</Button>
variant="outline-primary"
disabled={!xlsx || loading}
onClick={enviarCargaMasiva}
>
{loading ? "Subiendo..." : "Enviar archivo"}
</Button>
</div>
{/* Barra de progreso */}
{loading && (
<div className="mt-3">
<ProgressBar
now={progress}
label={`${progress}%`}
animated
striped
variant="info"
/>
</div>
)}
</div>
);
}
@@ -2,7 +2,9 @@
import React, { useState } from "react";
import axios from "axios";
import { Image } from "react-bootstrap";
import { Button, Image } from "react-bootstrap";
import { FaUpload } from "react-icons/fa";
import axiosInstance from "@/utils/api-config";
//Para poder subir las imagenes
interface UploadedImage {
@@ -35,110 +37,126 @@ export default function BannerUpload() {
});
try {
setLoading(true);
setProgress(0);
setLoading(true);
setProgress(0);
const res = await axios.post("/cuestionario/banners/bulk", formData, {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: (progressEvent) => {
if (progressEvent.total) {
setProgress(
Math.round((progressEvent.loaded * 100) / progressEvent.total)
);
}
},
});
const res = await axiosInstance.post("/cuestionario/banners/bulk", formData, {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: (progressEvent) => {
if (progressEvent.total) {
setProgress(
Math.round((progressEvent.loaded * 100) / progressEvent.total)
);
}
},
});
setUploaded(res.data);
alert("Banners subidos correctamente ✅");
setFiles([]);
//Falta hacer validacion
setUploaded(res.data);
alert("Banners subidos correctamente ✅");
setFiles([]);
} catch (error) {
console.error(error);
alert(error || "Error al subir archivos");
console.error(error);
alert(error || "Error al subir archivos");
} finally {
setLoading(false);
setLoading(false);
}
};
return (
<div className="p-6 max-w-2xl mx-auto bg-white rounded-xl shadow-md">
<h2 className="text-2xl font-bold mb-4 text-gray-800">Subir Banners</h2>
<div className="container-fluid my-4">
<div className="row mb-4">
<div className="col-12">
<div className="p-4 border rounded bg-light">
<h2 className="mb-2">Subir Banners</h2>
<p className="mb-0 text-muted">
Arrastra o selecciona imágenes para subir tus banners (jpg, png, webp).
</p>
</div>
</div>
</div>
{/* Área Drag & Drop */}
<label className="flex flex-col items-center justify-center w-full h-40 border-2 border-dashed border-gray-400 rounded-lg cursor-pointer hover:border-blue-500 transition">
<span className="text-gray-500">Arrastra o haz clic para subir</span>
<input
type="file"
multiple
accept=".jpg,.jpeg,.png,.webp"
onChange={handleFileChange}
className="hidden"
{/* Área Drag & Drop */}
<div
className="border p-4 text-center rounded"
style={{ cursor: "pointer" }}
onClick={() => document.getElementById("bannerInput")?.click()}
>
<FaUpload size={40} className="mb-2 text-muted" />
<p className="mb-1">
Arrastra aquí tus imágenes o haz clic para buscar
</p>
<p className="is-size-6">Tamaño máximo 20MB</p>
</div>
<input
id="bannerInput"
type="file"
accept=".jpg,.jpeg,.png,.webp"
multiple
style={{ display: "none" }}
onChange={handleFileChange}
/>
{/* Previsualización */}
{files.length > 0 && (
<div className="d-flex flex-wrap gap-3 mt-4">
{files.map((file, i) => (
<div
key={i}
className="border rounded overflow-hidden shadow-sm"
style={{ width: "350px", height: "350px" }}
>
<img
src={URL.createObjectURL(file)}
alt={file.name}
className="img-fluid h-75 w-100 object-fit-cover"
/>
</label>
{/* Falta corregir el tamaño de la imagen */}
{/* Previsualización de imágenes */}
{files.length > 0 && (
<div className="grid grid-cols-3 gap-4 mt-4">
{files.map((file, i) => (
<div
key={i}
className="relative border rounded-lg overflow-hidden shadow-sm"
style={{ width: "350px", height: "350px" }}
>
<Image
src={URL.createObjectURL(file)}
alt={file.name}
className="w-full h-28 object-cover"
/>
<p className="text-xs text-center truncate p-1">{file.name}</p>
</div>
))}
<p className="small text-center bg-light p-2 m-0">{file.name}</p>
</div>
)}
))}
</div>
)}
{/* Botón Subir */}
<button
onClick={handleUpload}
disabled={loading}
className="w-full mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50"
{/* Botón */}
<div className="d-flex gap-2 mt-3">
<Button
variant="outline-primary"
disabled={loading}
onClick={handleUpload}
>
{loading ? "Subiendo..." : "Subir Banners"}
</button>
{loading ? "Subiendo..." : "Subir Banners"}
</Button>
</div>
{/* Barra de progreso */}
{loading && (
<div className="w-full bg-gray-200 rounded-full h-3 mt-3">
<div
className="bg-blue-600 h-3 rounded-full"
style={{ width: `${progress}%` }}
></div>
</div>
)}
{/* Barra de progreso */}
{loading && (
<div className="progress mt-3" style={{ height: "8px" }}>
<div
className="progress-bar progress-bar-striped bg-primary"
role="progressbar"
style={{ width: `${progress}%` }}
></div>
</div>
)}
{/* Archivos subidos */}
{uploaded.length > 0 && (
<div className="mt-6">
<h3 className="font-semibold mb-2 text-gray-700">Archivos subidos:</h3>
<ul className="space-y-1">
{uploaded.map((file, i) => (
<li
key={i}
className="flex justify-between items-center text-sm bg-gray-100 px-3 py-2 rounded"
>
<span>{file.originalName}</span>
<a
href={`/${file.path}`}
target="_blank"
className="text-blue-600 hover:underline"
>
Ver
</a>
</li>
))}
</ul>
</div>
)}
{/* Archivos subidos */}
{uploaded.length > 0 && (
<div className="mt-4">
<h5 className="mb-2 text-muted">Archivos subidos:</h5>
<ul className="list-group">
{uploaded.map((file, i) => (
<li key={i} className="list-group-item d-flex justify-content-between align-items-center">
<span>{file.originalName}</span>
<a href={`/${file.path}`} target="_blank" className="text-primary">
Ver
</a>
</li>
))}
</ul>
</div>
)}
</div>
);
}