Refactor AdminFormPage and Formulario components to remove unused state and improve form handling; update plantilla data structure to include new fields.
This commit is contained in:
@@ -14,14 +14,14 @@ import {
|
|||||||
SeccionFormulario,
|
SeccionFormulario,
|
||||||
} from '@/types/crear-formulario';
|
} from '@/types/crear-formulario';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
export default function AdminFormPage() {
|
export default function AdminFormPage() {
|
||||||
|
const router = useRouter();
|
||||||
const [nombreFormulario, setNombreFormulario] = useState('');
|
const [nombreFormulario, setNombreFormulario] = useState('');
|
||||||
const [descripcion, setDescripcion] = useState('');
|
const [descripcion, setDescripcion] = useState('');
|
||||||
const [secciones, setSecciones] = useState<SeccionFormulario[]>([]);
|
const [secciones, setSecciones] = useState<SeccionFormulario[]>([]);
|
||||||
const [paginaActual, setPaginaActual] = useState(1);
|
const [paginaActual, setPaginaActual] = useState(1);
|
||||||
const [bannerPreview, setBannerPreview] = useState<string | null>(null);
|
|
||||||
const [tipoCuestionario, setTipoCuestionario] = useState<number | null>(null);
|
|
||||||
const [fechaInicio, setFechaInicio] = useState<string | null>(null);
|
const [fechaInicio, setFechaInicio] = useState<string | null>(null);
|
||||||
const [fechaFin, setFechaFin] = useState<string | null>(null);
|
const [fechaFin, setFechaFin] = useState<string | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -154,7 +154,7 @@ export default function AdminFormPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const guardarFormulario = async () => {
|
const guardarFormulario = async () => {
|
||||||
if (!fechaInicio || !fechaFin || !tipoCuestionario) {
|
if (!fechaInicio || !fechaFin || !nombreFormulario) {
|
||||||
alert('Todos los campos obligatorios deben estar llenos');
|
alert('Todos los campos obligatorios deben estar llenos');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -169,22 +169,26 @@ export default function AdminFormPage() {
|
|||||||
descripcion,
|
descripcion,
|
||||||
fecha_inicio: formatearFecha(fechaInicio, 'inicio'),
|
fecha_inicio: formatearFecha(fechaInicio, 'inicio'),
|
||||||
fecha_fin: formatearFecha(fechaFin, 'fin'),
|
fecha_fin: formatearFecha(fechaFin, 'fin'),
|
||||||
id_tipo_cuestionario: tipoCuestionario,
|
|
||||||
evento: nombreFormulario, // temporalmente igual al nombre del form
|
evento: nombreFormulario, // temporalmente igual al nombre del form
|
||||||
secciones,
|
secciones,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Formulario a guardar:', formData);
|
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await toast
|
await toast
|
||||||
.promise(axiosInstance.post('/cuestionario', formData), {
|
.promise(
|
||||||
loading: 'Guardando formulario...',
|
axiosInstance.post('/cuestionario', {
|
||||||
success: 'Formulario guardado exitosamente!',
|
...formData,
|
||||||
error: 'Error al guardar el formulario.',
|
id_tipo_cuestionario: 1,
|
||||||
})
|
}),
|
||||||
|
{
|
||||||
|
loading: 'Guardando formulario...',
|
||||||
|
success: 'Formulario guardado exitosamente!',
|
||||||
|
error: 'Error al guardar el formulario.',
|
||||||
|
}
|
||||||
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log('Formulario guardado:', res.data);
|
console.log('Formulario guardado:', res.data);
|
||||||
|
router.push(`/administrador/formulario/${res.data.id_cuestionario}`);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error al guardar el formulario:', error);
|
console.error('Error al guardar el formulario:', error);
|
||||||
@@ -194,17 +198,6 @@ export default function AdminFormPage() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBannerChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const file = e.target.files?.[0] || null;
|
|
||||||
if (file) {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => setBannerPreview(reader.result as string);
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
} else {
|
|
||||||
setBannerPreview(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const seccionActual = secciones[paginaActual - 1];
|
const seccionActual = secciones[paginaActual - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -224,14 +217,12 @@ export default function AdminFormPage() {
|
|||||||
descripcion,
|
descripcion,
|
||||||
fecha_inicio,
|
fecha_inicio,
|
||||||
fecha_fin,
|
fecha_fin,
|
||||||
id_tipo_cuestionario,
|
|
||||||
secciones,
|
secciones,
|
||||||
} = plantilla.datos;
|
} = plantilla.datos;
|
||||||
setNombreFormulario(nombre_form);
|
setNombreFormulario(nombre_form);
|
||||||
setDescripcion(descripcion);
|
setDescripcion(descripcion);
|
||||||
setFechaInicio(fecha_inicio.slice(0, 10));
|
setFechaInicio(fecha_inicio.slice(0, 10));
|
||||||
setFechaFin(fecha_fin.slice(0, 10));
|
setFechaFin(fecha_fin.slice(0, 10));
|
||||||
setTipoCuestionario(id_tipo_cuestionario);
|
|
||||||
setSecciones(
|
setSecciones(
|
||||||
secciones.map((seccion) => ({
|
secciones.map((seccion) => ({
|
||||||
...seccion,
|
...seccion,
|
||||||
@@ -259,82 +250,52 @@ export default function AdminFormPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="alert alert-info">
|
||||||
<label className="form-label">Banner del formulario</label>
|
<Input
|
||||||
<input
|
label="Nombre del formulario"
|
||||||
type="file"
|
value={nombreFormulario}
|
||||||
accept="image/*"
|
onChange={(e) => setNombreFormulario(e.target.value)}
|
||||||
className="form-control mb-2"
|
placeholder="Ingrese el nombre del formulario"
|
||||||
onChange={handleBannerChange}
|
|
||||||
/>
|
/>
|
||||||
{bannerPreview && (
|
|
||||||
<div className="text-center">
|
<div className="mb-3">
|
||||||
<Image
|
<label className="form-label">Descripción</label>
|
||||||
src={bannerPreview}
|
<textarea
|
||||||
width={1000}
|
className="form-control bg-white"
|
||||||
height={300}
|
rows={3}
|
||||||
alt="Ejemplo de banner"
|
value={descripcion}
|
||||||
className="rounded-4 shadow-sm"
|
onChange={(e) => setDescripcion(e.target.value)}
|
||||||
style={{
|
/>
|
||||||
objectFit: 'cover',
|
</div>
|
||||||
objectPosition: 'center',
|
|
||||||
}}
|
<div className="row">
|
||||||
|
<p className="mb-0 h2">Fechas de inicio y fin del formulario</p>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Input
|
||||||
|
label="Fecha de inicio"
|
||||||
|
type="date"
|
||||||
|
value={fechaInicio || ''}
|
||||||
|
onChange={(e) => setFechaInicio(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Input
|
||||||
|
label="Fecha de fin"
|
||||||
|
type="date"
|
||||||
|
value={fechaFin || ''}
|
||||||
|
onChange={(e) => setFechaFin(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
label="Tipo de cuestionario"
|
|
||||||
options={[
|
|
||||||
{ label: 'Seleccione un tipo', value: '' },
|
|
||||||
{ label: 'Tipo 1', value: 1 },
|
|
||||||
{ label: 'Tipo 2', value: 2 },
|
|
||||||
{ label: 'Tipo 3', value: 3 },
|
|
||||||
]}
|
|
||||||
value={tipoCuestionario?.toString() || ''}
|
|
||||||
onChange={(e) => setTipoCuestionario(Number(e.target.value))}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
label="Nombre del formulario"
|
|
||||||
value={nombreFormulario}
|
|
||||||
onChange={(e) => setNombreFormulario(e.target.value)}
|
|
||||||
placeholder="Ingrese el nombre del formulario"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
|
||||||
<label className="form-label">Descripción</label>
|
|
||||||
<textarea
|
|
||||||
className="form-control bg-white"
|
|
||||||
rows={3}
|
|
||||||
value={descripcion}
|
|
||||||
onChange={(e) => setDescripcion(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row alert alert-info">
|
|
||||||
<p className="mb-0 h2">Fechas de inicio y fin del formulario</p>
|
|
||||||
<div className="col-md-6">
|
|
||||||
<Input
|
|
||||||
label="Fecha de inicio"
|
|
||||||
type="date"
|
|
||||||
value={fechaInicio || ''}
|
|
||||||
onChange={(e) => setFechaInicio(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-6">
|
|
||||||
<Input
|
|
||||||
label="Fecha de fin"
|
|
||||||
type="date"
|
|
||||||
value={fechaFin || ''}
|
|
||||||
onChange={(e) => setFechaFin(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<Button outline onClick={agregarSeccion} icon="plus">
|
<Button
|
||||||
|
outline
|
||||||
|
onClick={agregarSeccion}
|
||||||
|
icon="plus"
|
||||||
|
className="mb-3 w-100"
|
||||||
|
>
|
||||||
Agregar Sección
|
Agregar Sección
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import axiosInstance from '@/utils/api-config';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { getAxiosError } from '@/utils/errors-utils';
|
import { getAxiosError } from '@/utils/errors-utils';
|
||||||
|
|
||||||
interface DatosAlumno {
|
interface GetAlumnoResponse {
|
||||||
id_ncuenta: number;
|
id_ncuenta: number;
|
||||||
nombre: string;
|
nombre: string;
|
||||||
apellidos: string;
|
apellidos: string;
|
||||||
@@ -34,6 +34,7 @@ export default function Formulario({
|
|||||||
apellidos: string;
|
apellidos: string;
|
||||||
correo: string;
|
correo: string;
|
||||||
genero: 'M' | 'F';
|
genero: 'M' | 'F';
|
||||||
|
carrera: string;
|
||||||
}>(null);
|
}>(null);
|
||||||
const [respuestas, setRespuestas] = useState<Record<string, string>>({});
|
const [respuestas, setRespuestas] = useState<Record<string, string>>({});
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false); // New state for submission
|
const [isSubmitting, setIsSubmitting] = useState(false); // New state for submission
|
||||||
@@ -47,7 +48,7 @@ export default function Formulario({
|
|||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
setDatosAuto(null);
|
setDatosAuto(null);
|
||||||
const { data } = await axiosInstance.get<DatosAlumno>(
|
const { data } = await axiosInstance.get<GetAlumnoResponse>(
|
||||||
`/alumnos/${cuenta}`
|
`/alumnos/${cuenta}`
|
||||||
);
|
);
|
||||||
console.log('Datos del alumno:', data);
|
console.log('Datos del alumno:', data);
|
||||||
@@ -57,6 +58,7 @@ export default function Formulario({
|
|||||||
apellidos: data.apellidos.toString(),
|
apellidos: data.apellidos.toString(),
|
||||||
correo: data.id_ncuenta + '@pcpuma.acatlan.unam.mx',
|
correo: data.id_ncuenta + '@pcpuma.acatlan.unam.mx',
|
||||||
genero: data.genero,
|
genero: data.genero,
|
||||||
|
carrera: data.carrera,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -99,6 +101,10 @@ export default function Formulario({
|
|||||||
) {
|
) {
|
||||||
nuevasRespuestas[`pregunta_${id}`] = 'FES Acatlán';
|
nuevasRespuestas[`pregunta_${id}`] = 'FES Acatlán';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pregunta.pregunta.toLowerCase().includes('carrera')) {
|
||||||
|
nuevasRespuestas[`pregunta_${id}`] = datosAuto.carrera;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -188,8 +194,6 @@ export default function Formulario({
|
|||||||
const validarRespuestasObligatorias = (): boolean => {
|
const validarRespuestasObligatorias = (): boolean => {
|
||||||
const faltantes: number[] = [];
|
const faltantes: number[] = [];
|
||||||
const errores: { id: number; mensaje: string }[] = [];
|
const errores: { id: number; mensaje: string }[] = [];
|
||||||
console.log(secciones);
|
|
||||||
console.log('Validando respuestas:', respuestas);
|
|
||||||
|
|
||||||
secciones.forEach((seccion) => {
|
secciones.forEach((seccion) => {
|
||||||
seccion.preguntas.forEach(({ pregunta }) => {
|
seccion.preguntas.forEach(({ pregunta }) => {
|
||||||
@@ -198,7 +202,7 @@ export default function Formulario({
|
|||||||
const tipo = pregunta.tipo_pregunta.tipo_pregunta;
|
const tipo = pregunta.tipo_pregunta.tipo_pregunta;
|
||||||
const validacion = pregunta.validacion;
|
const validacion = pregunta.validacion;
|
||||||
|
|
||||||
console.log('Validando pregunta:', pregunta.pregunta);
|
console.log('Validando pregunta:', pregunta.pregunta, ' ---------- ');
|
||||||
console.table({
|
console.table({
|
||||||
id,
|
id,
|
||||||
valor,
|
valor,
|
||||||
@@ -320,6 +324,10 @@ export default function Formulario({
|
|||||||
defaultValue = 'FES Acatlán';
|
defaultValue = 'FES Acatlán';
|
||||||
disabled = true;
|
disabled = true;
|
||||||
}
|
}
|
||||||
|
if (p.pregunta.toLowerCase().includes('carrera')) {
|
||||||
|
defaultValue = datosAuto.carrera;
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -329,12 +337,13 @@ export default function Formulario({
|
|||||||
name={`pregunta_${p.id_pregunta}`}
|
name={`pregunta_${p.id_pregunta}`}
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
|
console.log('Respuesta:', e.target.value);
|
||||||
actualizarRespuesta(
|
actualizarRespuesta(
|
||||||
`pregunta_${p.id_pregunta}`,
|
`pregunta_${p.id_pregunta}`,
|
||||||
e.target.value
|
e.target.value
|
||||||
)
|
);
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
{p.validacion === 'correo' && (
|
{p.validacion === 'correo' && (
|
||||||
<div className="alert alert-info">
|
<div className="alert alert-info">
|
||||||
|
|||||||
+10
-6
@@ -13,12 +13,10 @@ export const plantillasDisponibles: Plantilla[] = [
|
|||||||
nombre: 'Registro para la Feria',
|
nombre: 'Registro para la Feria',
|
||||||
id: 'feria-sexualidad',
|
id: 'feria-sexualidad',
|
||||||
datos: {
|
datos: {
|
||||||
nombre_form: 'Registro para la Feria de la Sexualidad - FES Acatlán',
|
nombre_form: '',
|
||||||
descripcion:
|
descripcion: '',
|
||||||
'La Feria de la Sexualidad “Placer sí, Responsabilidad también” es un espacio lúdico seguro e informativo dirigido a toda la comunidad universitaria. Regístrate y confirma tu asistencia, así podrás obtener tu constancia de asistencia.',
|
fecha_inicio: '',
|
||||||
fecha_inicio: '2025-03-07T00:00:01',
|
fecha_fin: '',
|
||||||
fecha_fin: '2025-03-18T23:59:59',
|
|
||||||
id_tipo_cuestionario: 1,
|
|
||||||
evento: 'Feria de la Sexualidad',
|
evento: 'Feria de la Sexualidad',
|
||||||
secciones: [
|
secciones: [
|
||||||
{
|
{
|
||||||
@@ -76,6 +74,12 @@ export const plantillasDisponibles: Plantilla[] = [
|
|||||||
obligatoria: true,
|
obligatoria: true,
|
||||||
limite: 250,
|
limite: 250,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
titulo: 'Carrera',
|
||||||
|
tipo: 'Abierta',
|
||||||
|
obligatoria: true,
|
||||||
|
limite: 250,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
Vendored
-1
@@ -3,7 +3,6 @@ export interface FormularioCreacion {
|
|||||||
descripcion: string;
|
descripcion: string;
|
||||||
fecha_inicio: string; // ISO 8601 date string
|
fecha_inicio: string; // ISO 8601 date string
|
||||||
fecha_fin: string;
|
fecha_fin: string;
|
||||||
id_tipo_cuestionario: number;
|
|
||||||
evento: string;
|
evento: string;
|
||||||
secciones: SeccionFormulario[];
|
secciones: SeccionFormulario[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user