2025-06-23 18:59:59 -06:00
|
|
|
import ImageUploader from '@/components/banner-uploader';
|
|
|
|
|
import Button from '@/components/button';
|
|
|
|
|
import SimpleInput from '@/components/input';
|
2025-08-14 21:59:38 -06:00
|
|
|
import FormularioCardPreview from '@/components/formulario/formulario-card-preview';
|
2025-06-23 18:59:59 -06:00
|
|
|
import { GetCuestionario } from '@/types/cuestionario';
|
2025-08-14 21:59:38 -06:00
|
|
|
import { GetEvento } from '@/types/evento';
|
2025-06-23 18:59:59 -06:00
|
|
|
import axiosInstance from '@/utils/api-config';
|
|
|
|
|
import { formatDateLocal } from '@/utils/date-utils';
|
|
|
|
|
import { getAxiosError } from '@/utils/errors-utils';
|
|
|
|
|
import MDEditor, { commands } from '@uiw/react-md-editor';
|
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import toast from 'react-hot-toast';
|
|
|
|
|
|
|
|
|
|
interface EditFormularioProps {
|
|
|
|
|
cuestionario: GetCuestionario;
|
2025-08-14 21:59:38 -06:00
|
|
|
evento: GetEvento | null;
|
2025-06-23 18:59:59 -06:00
|
|
|
handleChange: (field: keyof GetCuestionario, value: string | Date) => void;
|
|
|
|
|
handleOnChange: (eventoActualizado: GetCuestionario) => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function EditFormulario({
|
|
|
|
|
cuestionario,
|
2025-08-14 21:59:38 -06:00
|
|
|
evento,
|
2025-06-23 18:59:59 -06:00
|
|
|
handleChange,
|
|
|
|
|
}: EditFormularioProps) {
|
2025-09-09 19:24:35 -06:00
|
|
|
const tipo_usuario = sessionStorage.getItem('axxxd')?.replace(/"/g, '') || '';
|
2025-06-23 18:59:59 -06:00
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [nuevoBanner, setNuevoBanner] = useState<File | null>(null);
|
|
|
|
|
|
|
|
|
|
const handleOnSave = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
// 1. Subir nuevo banner si fue cambiado
|
|
|
|
|
if (nuevoBanner) {
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
formData.append('banner', nuevoBanner);
|
|
|
|
|
|
|
|
|
|
await axiosInstance.post(
|
|
|
|
|
`/cuestionario/${cuestionario.id_cuestionario}/banner`,
|
|
|
|
|
formData,
|
|
|
|
|
{
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Actualizar el evento (sin incluir 'banner')
|
|
|
|
|
const res = await axiosInstance.patch(
|
|
|
|
|
`/cuestionario/${cuestionario.id_cuestionario}`,
|
|
|
|
|
{
|
|
|
|
|
nombre_form: cuestionario.nombre_form,
|
|
|
|
|
descripcion: cuestionario.descripcion,
|
|
|
|
|
fecha_inicio: cuestionario.fecha_inicio,
|
|
|
|
|
fecha_fin: cuestionario.fecha_fin,
|
2025-06-24 20:34:04 -06:00
|
|
|
cupo_maximo: Number(cuestionario.cupo_maximo) || null,
|
2026-03-10 12:59:01 -06:00
|
|
|
mensaje_correo: cuestionario.mensaje_correo || null,
|
2025-06-23 18:59:59 -06:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log('Evento actualizado:', res.data);
|
|
|
|
|
|
|
|
|
|
toast.success('Evento actualizado correctamente');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const msg = getAxiosError(error);
|
|
|
|
|
toast.error(`Error al actualizar el evento: ${msg.message}`);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2025-08-14 21:59:38 -06:00
|
|
|
<div className="container-fluid my-4">
|
|
|
|
|
{/* Header */}
|
|
|
|
|
<div className="row mb-4">
|
|
|
|
|
<div className="col-12">
|
|
|
|
|
<div className="p-4 border rounded bg-light">
|
|
|
|
|
<h2 className="mb-2">Editar Información del Formulario</h2>
|
|
|
|
|
<p className="mb-0 text-muted">
|
|
|
|
|
Modifica los datos del formulario que desees actualizar y
|
|
|
|
|
confirmalos.
|
|
|
|
|
</p>
|
2025-08-12 20:00:21 -06:00
|
|
|
</div>
|
2025-08-14 21:59:38 -06:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-06-23 18:59:59 -06:00
|
|
|
|
2025-08-14 21:59:38 -06:00
|
|
|
<div className="row">
|
|
|
|
|
{/* Columna Izquierda - Formulario */}
|
|
|
|
|
<div className="col-xl-7 col-lg-6">
|
|
|
|
|
<div className="pe-lg-4">
|
|
|
|
|
<div className="p-4">
|
|
|
|
|
<div className="row">
|
|
|
|
|
{/* Banner */}
|
|
|
|
|
<div className="col-12">
|
|
|
|
|
<div className="mb-4">
|
|
|
|
|
<ImageUploader
|
|
|
|
|
label="Banner del formulario"
|
|
|
|
|
defaultBanner={
|
|
|
|
|
cuestionario.banner
|
|
|
|
|
? `${process.env.NEXT_PUBLIC_API_URL}/banners/${cuestionario.banner}`
|
|
|
|
|
: undefined
|
2025-08-12 20:00:21 -06:00
|
|
|
}
|
2025-08-14 21:59:38 -06:00
|
|
|
onChange={(file) => {
|
|
|
|
|
setNuevoBanner(file);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<p className="text-muted mt-2 small">
|
|
|
|
|
<strong>
|
|
|
|
|
<i className="bi bi-info-circle-fill me-2"></i>
|
|
|
|
|
Esta es la imagen que se usara para la carta de
|
|
|
|
|
presentación del formulario.
|
|
|
|
|
</strong>
|
|
|
|
|
<br />
|
|
|
|
|
<strong>
|
|
|
|
|
<i className="bi bi-image me-2"></i>
|
|
|
|
|
Dimensiones recomendadas: 1200x600 píxeles.
|
|
|
|
|
</strong>
|
|
|
|
|
<br />
|
|
|
|
|
<strong>
|
|
|
|
|
<i className="bi bi-file-earmark-image me-2"></i>
|
|
|
|
|
Formatos soportados: PNG, JPG, JPEG.
|
|
|
|
|
</strong>
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
{/* Alert sobre imagen por defecto */}
|
|
|
|
|
{!cuestionario.banner && !nuevoBanner && evento?.banner && (
|
|
|
|
|
<div className="alert alert-info mt-3">
|
|
|
|
|
<i className="bi bi-info-circle me-2"></i>
|
|
|
|
|
<strong>Imagen por defecto:</strong> Si no seleccionas
|
|
|
|
|
una imagen específica para este formulario, se utilizará
|
|
|
|
|
automáticamente la imagen del evento.
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-08-12 20:00:21 -06:00
|
|
|
</div>
|
|
|
|
|
|
2025-08-14 21:59:38 -06:00
|
|
|
{/* Detalles del formulario */}
|
|
|
|
|
<div className="col-12">
|
|
|
|
|
<h4 className="mb-3">Detalles del Formulario</h4>
|
|
|
|
|
|
2025-08-12 20:00:21 -06:00
|
|
|
<SimpleInput
|
2025-08-14 21:59:38 -06:00
|
|
|
label="Nombre del formulario"
|
|
|
|
|
required
|
|
|
|
|
value={cuestionario.nombre_form}
|
2025-08-12 20:00:21 -06:00
|
|
|
onChange={(e) =>
|
2025-08-14 21:59:38 -06:00
|
|
|
handleChange('nombre_form', e.target.value)
|
2025-08-12 20:00:21 -06:00
|
|
|
}
|
|
|
|
|
/>
|
2025-06-23 18:59:59 -06:00
|
|
|
|
2026-03-10 12:59:01 -06:00
|
|
|
<SimpleInput
|
|
|
|
|
label="Mensaje de correo"
|
|
|
|
|
value={cuestionario.mensaje_correo ?? ''}
|
|
|
|
|
onChange={(e) =>
|
|
|
|
|
handleChange('mensaje_correo', e.target.value)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
|
2025-08-12 20:00:21 -06:00
|
|
|
<SimpleInput
|
2025-08-14 21:59:38 -06:00
|
|
|
label="Cupo máximo (Si no se requiere, dejar en blanco)"
|
|
|
|
|
type="number"
|
|
|
|
|
value={cuestionario.cupo_maximo ?? ''}
|
2025-08-12 20:00:21 -06:00
|
|
|
onChange={(e) =>
|
2025-08-14 21:59:38 -06:00
|
|
|
handleChange(
|
|
|
|
|
'cupo_maximo',
|
|
|
|
|
e.target.value ? e.target.value : ''
|
|
|
|
|
)
|
2025-08-12 20:00:21 -06:00
|
|
|
}
|
|
|
|
|
/>
|
2025-08-14 21:59:38 -06:00
|
|
|
|
|
|
|
|
<div className="mb-4">
|
|
|
|
|
<label className="form-label">
|
|
|
|
|
Descripción del formulario
|
|
|
|
|
</label>
|
|
|
|
|
<div data-color-mode="light">
|
|
|
|
|
<MDEditor
|
|
|
|
|
value={cuestionario.descripcion ?? ''}
|
|
|
|
|
onChange={(value) => {
|
|
|
|
|
const texto = value || '';
|
|
|
|
|
if (texto.length <= 500) {
|
|
|
|
|
handleChange(
|
|
|
|
|
'descripcion' as keyof GetCuestionario,
|
|
|
|
|
texto
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
height={200}
|
|
|
|
|
commands={[commands.bold, commands.italic, commands.hr]}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="row">
|
|
|
|
|
<div className="col-md-6">
|
|
|
|
|
<SimpleInput
|
|
|
|
|
label="Fecha de inicio"
|
|
|
|
|
type="datetime-local"
|
|
|
|
|
className={{ container: 'mb-3' }}
|
|
|
|
|
value={formatDateLocal(
|
|
|
|
|
new Date(cuestionario.fecha_inicio)
|
|
|
|
|
)}
|
|
|
|
|
onChange={(e) =>
|
|
|
|
|
handleChange('fecha_inicio', new Date(e.target.value))
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="col-md-6">
|
|
|
|
|
<SimpleInput
|
|
|
|
|
label="Fecha de fin"
|
|
|
|
|
type="datetime-local"
|
|
|
|
|
className={{ container: 'mb-3' }}
|
|
|
|
|
value={formatDateLocal(
|
|
|
|
|
new Date(cuestionario.fecha_fin)
|
|
|
|
|
)}
|
|
|
|
|
onChange={(e) =>
|
|
|
|
|
handleChange('fecha_fin', new Date(e.target.value))
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-12 20:00:21 -06:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-14 21:59:38 -06:00
|
|
|
|
|
|
|
|
{/* Botón de guardar */}
|
2025-09-09 19:24:35 -06:00
|
|
|
{tipo_usuario === "administrador" && (
|
|
|
|
|
<div className="d-flex justify-content-end mt-4">
|
|
|
|
|
<Button icon="save" disabled={loading} onClick={handleOnSave}>
|
|
|
|
|
{loading ? 'Guardando...' : 'Guardar Cambios'}
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-08-12 20:00:21 -06:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-08-14 21:59:38 -06:00
|
|
|
{/* Columna Derecha - Preview */}
|
|
|
|
|
<div className="col-xl-5 col-lg-6">
|
|
|
|
|
<div className="ps-lg-4">
|
|
|
|
|
<div className="sticky-top" style={{ top: '20px' }}>
|
|
|
|
|
<h4 className="mb-3 d-none d-lg-block">Preview del Formulario</h4>
|
|
|
|
|
<div className="d-lg-none mt-4">
|
|
|
|
|
<h4 className="mb-3">Preview del Formulario</h4>
|
|
|
|
|
</div>
|
|
|
|
|
<FormularioCardPreview
|
|
|
|
|
cuestionario={cuestionario}
|
|
|
|
|
evento={evento}
|
|
|
|
|
nuevoBanner={nuevoBanner}
|
|
|
|
|
/>
|
|
|
|
|
<div className="alert alert-info text-center mt-3">
|
|
|
|
|
<strong>Vista previa:</strong> Así se verá tu formulario en las
|
|
|
|
|
listas de formularios.
|
|
|
|
|
</div>
|
2025-08-12 20:00:21 -06:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-06-23 18:59:59 -06:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|