feat: Refactor carousel component and add new event card

- Updated ClientCarousel to accept props for dynamic image rendering.
- Changed CarouselProps interface to export for better type usage.
- Enhanced Carousel component to handle default images and improved styling.
- Introduced EventoCard component for displaying event details with dynamic data.
- Added MarkdownRenderer for rendering markdown content in EventoCard.
- Removed old Formulario component and replaced it with FormularioRegistro for better structure.
- Implemented prefetching logic in FormularioRegistro to auto-fill user data based on account info.
- Created PrefetchAbiertaCorta component for handling short answer questions with pre-filled data.
- Added useGetApi hook for simplified API data fetching.
- Updated plantillas data to include validation types for new form fields.
- Introduced new types for event and questionnaire handling in TypeScript.
- Enhanced styles for better UI/UX, including carousel controls and required field indicators.
This commit is contained in:
miguel
2025-06-16 18:25:12 -06:00
parent e275b33131
commit f00bd8ac5e
21 changed files with 2110 additions and 599 deletions
-416
View File
@@ -1,416 +0,0 @@
'use client';
import React, { useEffect, useState } from 'react';
import { CuestionarioSeccion } from '@/types/responder-formulario';
import RadioOptionGroup, { RadioOption } from '@/components/radio-option-group';
import Input from '@/components/input';
import Button from '@/components/button';
import { validarRespuesta } from '@/utils/validador';
import toast from 'react-hot-toast';
import axiosInstance from '@/utils/api-config';
import { useRouter } from 'next/navigation';
import { getAxiosError } from '@/utils/errors-utils';
interface GetAlumnoResponse {
id_ncuenta: number;
nombre: string;
apellidos: string;
carrera: string;
genero: 'M' | 'F';
}
export default function Formulario({
id_formulario,
secciones,
}: {
id_formulario: number;
secciones: CuestionarioSeccion[];
}) {
const router = useRouter();
const [esDeFES, setEsDeFES] = useState<boolean | null>(null);
const [cuenta, setCuenta] = useState('');
const [datosAuto, setDatosAuto] = useState<null | {
nombre: string;
apellidos: string;
correo: string;
genero: 'M' | 'F';
carrera: string;
}>(null);
const [respuestas, setRespuestas] = useState<Record<string, string>>({});
const [isSubmitting, setIsSubmitting] = useState(false); // New state for submission
const actualizarRespuesta = (idPregunta: string, valor: string) => {
setRespuestas((prev) => ({ ...prev, [idPregunta]: valor }));
};
useEffect(() => {
if (esDeFES && cuenta.length === 9) {
(async () => {
try {
setDatosAuto(null);
const { data } = await axiosInstance.get<GetAlumnoResponse>(
`/alumnos/${cuenta}`
);
console.log('Datos del alumno:', data);
if (data) {
setDatosAuto({
nombre: data.nombre.toString(),
apellidos: data.apellidos.toString(),
correo: data.id_ncuenta + '@pcpuma.acatlan.unam.mx',
genero: data.genero,
carrera: data.carrera,
});
}
} catch (err) {
const msg = getAxiosError(err);
toast.error(msg.message);
setDatosAuto(null);
}
})();
}
}, [cuenta, esDeFES]);
useEffect(() => {
if (esDeFES && datosAuto) {
const nuevasRespuestas: Record<string, string> = {};
secciones.forEach((seccion) => {
seccion.preguntas.forEach(({ pregunta }) => {
const id = pregunta.id_pregunta;
if (pregunta.validacion === 'nombre') {
nuevasRespuestas[`pregunta_${id}`] = pregunta.pregunta
.toLowerCase()
.includes('apellido')
? datosAuto.apellidos.toString()
: datosAuto.nombre.toString();
}
if (pregunta.validacion === 'correo') {
nuevasRespuestas[`pregunta_${id}`] = datosAuto.correo;
}
if (pregunta.validacion === 'cuenta_alumno') {
nuevasRespuestas[`pregunta_${id}`] = cuenta;
}
if (
pregunta.pregunta
.toLowerCase()
.includes('institución de procedencia')
) {
nuevasRespuestas[`pregunta_${id}`] = 'FES Acatlán';
}
if (pregunta.pregunta.toLowerCase().includes('carrera')) {
nuevasRespuestas[`pregunta_${id}`] = datosAuto.carrera;
}
});
});
setRespuestas((prev) => ({
...prev,
...nuevasRespuestas,
}));
}
}, [datosAuto, esDeFES, cuenta, secciones]);
// Encuentra preguntas por texto o validación
const todasPreguntas = secciones.flatMap((s) =>
s.preguntas.map((p) => p.pregunta)
);
const preguntaFES = todasPreguntas.find(
(p) => p.pregunta === '¿Eres parte de la comunidad de la FES Acatlán?'
);
const preguntaCuenta = todasPreguntas.find(
(p) => p.validacion === 'cuenta_alumno'
);
const preguntasRestantes = todasPreguntas.filter(
(p) =>
![preguntaFES?.id_pregunta, preguntaCuenta?.id_pregunta].includes(
p.id_pregunta
)
);
const respuestaFES = respuestas[`pregunta_${preguntaFES?.id_pregunta}`];
const formatearRespuestas = async () => {
if (!validarRespuestasObligatorias()) return;
const respuestasArray = Object.entries(respuestas).flatMap(
([key, valor]) => {
const idNumerico = Number(key.replace('pregunta_', ''));
const pregunta = secciones
.flatMap((s) => s.preguntas)
.find((p) => p.pregunta.id_pregunta === idNumerico);
const tipo = pregunta?.pregunta.tipo_pregunta.tipo_pregunta;
// Si es múltiple, convertir cada valor individual si corresponde
if (Array.isArray(valor)) {
return valor.map((v) => ({
id_pregunta: idNumerico,
valor: tipo === 'Cerrada' || tipo === 'Multiple' ? Number(v) : v,
}));
}
return [
{
id_pregunta: idNumerico,
valor: tipo === 'Cerrada' ? Number(valor) : valor,
},
];
}
);
const correoEntry = respuestasArray.find(
(r) =>
typeof r.valor === 'string' &&
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r.valor)
);
const resultado = {
id_formulario: Number(id_formulario),
correo: correoEntry?.valor || 'correo@no-encontrado.com',
respuestas: respuestasArray,
fecha_envio: new Date().toISOString(),
};
console.log('Resultado a enviar:', resultado);
setIsSubmitting(true);
toast
.promise(
axiosInstance.post('/cuestionario-respondido/submit', resultado),
{
loading: 'Enviando formulario...',
success: 'Formulario enviado con éxito!',
error: 'Error al enviar el formulario.',
}
)
.then(() => router.push('/'))
.finally(() => setIsSubmitting(false));
};
const validarRespuestasObligatorias = (): boolean => {
const faltantes: number[] = [];
const errores: { id: number; mensaje: string }[] = [];
secciones.forEach((seccion) => {
seccion.preguntas.forEach(({ pregunta }) => {
const id = pregunta.id_pregunta;
const valor = respuestas[`pregunta_${id}`];
const tipo = pregunta.tipo_pregunta.tipo_pregunta;
const validacion = pregunta.validacion;
console.log('Validando pregunta:', pregunta.pregunta, ' ---------- ');
console.table({
id,
valor,
tipo,
validacion,
});
const respondida =
(tipo === 'Abierta' &&
typeof valor === 'string' &&
valor.trim() !== '') ||
(tipo === 'Cerrada' && valor !== undefined) ||
(tipo === 'Multiple' && Array.isArray(valor) && valor.length > 0);
if (!respondida && pregunta.obligatoria) {
faltantes.push(id);
}
if (tipo === 'Abierta' && validacion && typeof valor === 'string') {
const resultado = validarRespuesta(valor, validacion);
if (!resultado.valido) {
errores.push({ id, mensaje: resultado.mensaje });
}
}
});
});
if (faltantes.length > 0) {
console.log('Faltan preguntas obligatorias:', faltantes);
toast.error('Responde todas las preguntas obligatorias antes de enviar.');
return false;
}
if (errores.length > 0) {
toast.error(
`Corrige las respuestas con error de formato:\n${errores
.map((e) => `${e.mensaje}`)
.join('\n')}`
);
return false;
}
return true;
};
return (
<form className="container py-4">
{/* Pregunta inicial */}
{preguntaFES && (
<div className="mb-4">
<label className="form-label">{preguntaFES.pregunta}</label>
<RadioOptionGroup
name="comunidad_fes"
options={preguntaFES.opciones.map((op) => ({
label: op.opcion.opcion,
value: op.id_opcion,
}))}
selectedValue={respuestaFES ? Number(respuestaFES) : undefined}
onChange={(opt) => {
const id = opt.value;
const value = opt?.label ?? '';
setEsDeFES(value === 'Si'); // Se actualiza esDeFES con el texto
setCuenta('');
setDatosAuto(null);
actualizarRespuesta(
`pregunta_${preguntaFES.id_pregunta}`,
String(id)
);
}}
/>
</div>
)}
{/* Si dijo que sí, pedir número de cuenta */}
{esDeFES && preguntaCuenta && (
<Input
key={preguntaCuenta.id_pregunta}
label={preguntaCuenta.pregunta}
name={`pregunta_${preguntaCuenta.id_pregunta}`}
value={cuenta}
maxLength={10}
onChange={(e) => {
const value = e.target.value;
setCuenta(value);
actualizarRespuesta(
`pregunta_${preguntaCuenta.id_pregunta}`,
value
); // ✅ Guarda la respuesta
}}
/>
)}
{/* Si ya tiene datos o dijo que no es de la FES, mostrar el resto */}
{(esDeFES === false || (esDeFES && datosAuto)) &&
preguntasRestantes.map((p) => {
if (p.tipo_pregunta.tipo_pregunta === 'Abierta') {
let defaultValue = '';
let disabled = false;
if (esDeFES && datosAuto) {
if (p.validacion === 'nombre') {
defaultValue = p.pregunta.toLowerCase().includes('apellido')
? datosAuto.apellidos
: datosAuto.nombre;
disabled = true;
}
if (p.validacion === 'correo') {
defaultValue = datosAuto.correo;
disabled = true;
}
if (p.validacion === 'cuenta_alumno') {
defaultValue = cuenta;
disabled = true;
}
if (
p.pregunta.toLowerCase().includes('institución de procedencia')
) {
defaultValue = 'FES Acatlán';
disabled = true;
}
if (p.pregunta.toLowerCase().includes('carrera')) {
defaultValue = datosAuto.carrera;
disabled = true;
}
}
return (
<React.Fragment key={p.id_pregunta}>
<Input
label={p.pregunta}
name={`pregunta_${p.id_pregunta}`}
defaultValue={defaultValue}
disabled={disabled}
onChange={(e) => {
console.log('Respuesta:', e.target.value);
actualizarRespuesta(
`pregunta_${p.id_pregunta}`,
e.target.value
);
}}
/>
{p.validacion === 'correo' && (
<div className="alert alert-info">
Este es el correo donde enviaremos la validación de registro{' '}
</div>
)}
</React.Fragment>
);
}
if (p.tipo_pregunta.tipo_pregunta === 'Cerrada') {
const opciones: RadioOption<number>[] = p.opciones.map((op) => ({
label: op.opcion.opcion,
value: op.id_opcion,
}));
let respuestaActual = respuestas[`pregunta_${p.id_pregunta}`];
// Si es de FES y hay datos automáticos, intentar preseleccionar género
if (
esDeFES &&
datosAuto &&
!respuestaActual &&
p.pregunta.toLowerCase().includes('género')
) {
const generoTexto =
datosAuto.genero === 'M' ? 'Masculino' : 'Femenino';
const opcionGenero = p.opciones.find(
(op) =>
op.opcion.opcion.toLowerCase() === generoTexto.toLowerCase()
);
if (opcionGenero) {
respuestaActual = String(opcionGenero.id_opcion);
actualizarRespuesta(
`pregunta_${p.id_pregunta}`,
String(respuestaActual)
);
}
}
return (
<div key={p.id_pregunta}>
<label className="form-label">{p.pregunta}</label>
<RadioOptionGroup
name={`pregunta_${p.id_pregunta}`}
options={opciones}
selectedValue={
respuestaActual ? Number(respuestaActual) : undefined
}
onChange={(opt) =>
actualizarRespuesta(
`pregunta_${p.id_pregunta}`,
String(opt.value)
)
}
/>
</div>
);
}
return null;
})}
{/* Botón de enviar */}
<Button onClick={formatearRespuestas} disabled={isSubmitting}>
{isSubmitting ? 'Enviando...' : 'Enviar'}
</Button>
</form>
);
}
@@ -0,0 +1,471 @@
import React, { useState, useEffect } from 'react';
import MarkdownRenderer from '@/components/markdown-render';
import { useGetApi } from '@/hooks/use-get-api';
import { GetCuestionario } from '@/types/evento';
import SimpleInput from '@/components/input';
import RadioOptionGroup, { RadioOption } from '@/components/radio-option-group';
import axiosInstance from '@/utils/api-config';
import PrefetchAbiertaCorta from './prefetch-abierta-corta';
import Button from '@/components/button';
import toast from 'react-hot-toast';
import { useRouter } from 'next/navigation';
import { getAxiosError } from '@/utils/errors-utils';
type UsuarioData = {
nombre: string;
apellidos: string;
correo: string;
genero: 'M' | 'F';
carrera: string;
};
const confirmativeOption = ['Sí', 'Si', 'Si, claro', 'Claro que sí'];
const negativeOption = ['No', 'No, gracias', 'No, de momento'];
type RespuestaFormulario = Record<string, string | number>; // id_pregunta: respuesta
export default function FormularioRegistro({
id_cuestionario,
}: {
id_cuestionario: number;
}) {
// ------------------------
// Estados
// ------------------------
const [isComunidad, setIsComunidad] = useState<RadioOption<number>>();
const [respuestas, setRespuestas] = useState<RespuestaFormulario>({});
const [cuentaInfo, setCuentaInfo] = useState<UsuarioData | null>(null);
const [isSending, setIsSending] = useState(false);
const router = useRouter();
// ------------------------
// Carga del cuestionario
// ------------------------
const { data, error } = useGetApi<GetCuestionario>(
`/cuestionario/${id_cuestionario}/formulario`
);
// ------------------------
// Extracción de preguntas clave
// ------------------------
const preguntas = data?.cuestionario.secciones.flatMap((seccion) =>
seccion.preguntas.map((pregunta) => pregunta.pregunta)
);
const preguntaComunidad = preguntas?.find(
(pregunta) =>
pregunta.validacion === 'comunidad_alumno' ||
pregunta.validacion === 'comunidad_trabajador'
);
const preguntaCuenta = preguntas?.find(
(pregunta) =>
pregunta.validacion === 'cuenta_alumno' ||
pregunta.validacion === 'cuenta_trabajador'
);
// ------------------------
// Efecto: buscar información de cuenta
// ------------------------
useEffect(() => {
const cuenta = respuestas[preguntaCuenta?.id_pregunta ?? ''];
const esCuentaAlumno = preguntaCuenta?.validacion === 'cuenta_alumno';
const esCuentaTrabajador =
preguntaCuenta?.validacion === 'cuenta_trabajador';
const puedeBuscar =
cuenta &&
typeof cuenta === 'string' &&
((esCuentaAlumno && cuenta.length === 9) || esCuentaTrabajador);
const fetchCuentaInfo = async () => {
try {
const endpoint = esCuentaAlumno
? `/alumnos/${cuenta}`
: `/trabajadores/${cuenta}`;
console.log('Buscando información de cuenta:', endpoint);
// Usar datos fake para pruebas
setCuentaInfo({
nombre: 'Juan',
apellidos: 'Pérez',
correo: '421010301@pcpuma.acatlan.unam.mx',
genero: 'M',
carrera: 'Ingeniería',
});
} catch (error) {
console.error('Error al obtener datos de cuenta:', error);
setCuentaInfo(null);
}
};
if (puedeBuscar) {
fetchCuentaInfo();
} else {
setCuentaInfo(null);
}
}, [respuestas[preguntaCuenta?.id_pregunta ?? '']]);
// ------------------------
// Efecto: precargar respuestas si hay cuentaInfo
// ------------------------
useEffect(() => {
if (!cuentaInfo) {
if (preguntas) {
const idsPrefetch = preguntas
.filter((pregunta) =>
[
'nombre',
'apellidos',
'correo',
'institucion',
'carrera',
'genero',
].includes(pregunta.validacion)
)
.map((pregunta) => pregunta.id_pregunta);
setRespuestas((prev) => {
const nuevas = { ...prev };
idsPrefetch.forEach((id) => {
delete nuevas[id];
});
return nuevas;
});
}
return;
}
const nuevasRespuestas: RespuestaFormulario = {};
if (preguntas) {
for (const pregunta of preguntas) {
const id = pregunta.id_pregunta;
switch (pregunta.validacion) {
case 'nombre':
nuevasRespuestas[id] = cuentaInfo.nombre;
break;
case 'apellidos':
nuevasRespuestas[id] = cuentaInfo.apellidos;
break;
case 'correo':
nuevasRespuestas[id] = cuentaInfo.correo;
break;
case 'institucion':
nuevasRespuestas[id] = 'FES Acatlán';
break;
case 'carrera':
nuevasRespuestas[id] = cuentaInfo.carrera;
break;
case 'genero':
const generoTexto =
cuentaInfo.genero === 'M' ? 'Masculino' : 'Femenino';
const opcion = pregunta.opciones?.find(
(op) =>
op.opcion.opcion.toLowerCase() === generoTexto.toLowerCase()
);
if (opcion) {
nuevasRespuestas[id] = String(opcion.id_opcion);
}
break;
}
}
setRespuestas((prev) => ({
...prev,
...nuevasRespuestas,
}));
}
}, [cuentaInfo]);
// ------------------------
// Funciones auxiliares
// ------------------------
const actualizarRespuesta = (idPregunta: string, valor: string) => {
setRespuestas((prev) => ({ ...prev, [idPregunta]: valor }));
};
const handleOnSubmit = async () => {
setIsSending(true);
if (!data?.cuestionario.id_cuestionario) {
alert('No se ha cargado correctamente el formulario');
return;
}
const preguntasObligatorias =
data?.cuestionario.secciones.flatMap((seccion) =>
seccion.preguntas
.filter((pregunta) => pregunta.pregunta.obligatoria)
.map((pregunta) => pregunta.pregunta)
) || [];
const faltantes = preguntasObligatorias.filter(
(pregunta) =>
respuestas[pregunta.id_pregunta] === undefined ||
respuestas[pregunta.id_pregunta] === '' ||
respuestas[pregunta.id_pregunta] === null
);
if (faltantes.length > 0) {
toast.error('Por favor responde todas las preguntas obligatorias.');
return;
}
// Buscar un posible correo en las respuestas si no hay cuentaInfo
let correo = cuentaInfo?.correo;
if (!correo) {
// Buscar en las respuestas una que parezca correo
const correoRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
for (const valor of Object.values(respuestas)) {
if (typeof valor === 'string' && correoRegex.test(valor)) {
correo = valor;
break;
}
}
}
const payload = {
id_cuestionario: id_cuestionario,
correo: correo || '',
fecha_envio: new Date().toISOString(),
respuestas: Object.entries(respuestas).map(([id_pregunta, valor]) => ({
id_pregunta: Number(id_pregunta),
valor: isNaN(Number(valor)) ? valor : Number(valor),
})),
};
console.log('Payload para enviar:', payload);
try {
const res = await axiosInstance.post(
'/cuestionario-respondido/submit',
payload
);
toast.success(res.data.message || 'Formulario enviado correctamente');
} catch (error) {
console.log(getAxiosError(error));
toast.error('Hubo un error al enviar el formulario');
} finally {
// Redirigir al usuario después de enviar el formulario
router.push('/');
}
};
// ------------------------
// Condición para mostrar el formulario
// ------------------------
const mostrarFormularioRestante =
(isComunidad &&
confirmativeOption.includes(isComunidad.label) &&
!!cuentaInfo) ||
(isComunidad && negativeOption.includes(isComunidad.label));
if (error) {
console.error('Error al cargar el cuestionario:', error);
return <div>Error al cargar el cuestionario</div>;
}
return (
<div>
<hr />
<h2 className="text-xl font-bold">{data?.cuestionario.nombre_form}</h2>
{data?.cuestionario.descripcion && (
<MarkdownRenderer markdown={data.cuestionario.descripcion} />
)}
{preguntaComunidad && (
<div className="my-4">
<label
className={`form-label ${
preguntaComunidad.obligatoria ? 'required' : ''
}`}
>
{preguntaComunidad.pregunta}
</label>
<RadioOptionGroup
name="comunidad"
options={preguntaComunidad.opciones.map((op) => ({
label: op.opcion.opcion,
value: op.id_opcion,
}))}
selectedValue={isComunidad?.value}
onChange={(opt) => {
console.log('Opción comunidad seleccionada:', opt);
setIsComunidad(opt);
actualizarRespuesta(
preguntaComunidad.id_pregunta.toString(),
String(opt.value)
);
}}
/>
</div>
)}
{isComunidad &&
confirmativeOption.includes(isComunidad?.label) &&
preguntaCuenta && (
<div className="my-4">
<label
className={`form-label ${
preguntaCuenta.obligatoria ? 'required' : ''
}`}
>
{preguntaCuenta.pregunta}
</label>
<SimpleInput
type="text"
name="cuenta"
placeholder="Ingrese su cuenta"
maxLength={10}
value={respuestas[preguntaCuenta.id_pregunta] || ''}
onChange={(e) =>
setRespuestas((prev) => ({
...prev,
[preguntaCuenta.id_pregunta]: e.target.value,
}))
}
/>
</div>
)}
{mostrarFormularioRestante &&
data?.cuestionario.secciones.map((seccion, i) => (
<div key={i}>
{seccion.preguntas.map((pregunta) => {
// Evitar renderizar las preguntas ya manejadas
if (
pregunta.pregunta.id_pregunta ===
preguntaComunidad?.id_pregunta ||
pregunta.pregunta.id_pregunta === preguntaCuenta?.id_pregunta
)
return null;
if (
pregunta.pregunta.tipo_pregunta.tipo_pregunta ===
'Abierta (Respuesta corta)'
) {
return (
<PrefetchAbiertaCorta
key={pregunta.pregunta.id_pregunta}
obligatorio={pregunta.pregunta.obligatoria}
idPregunta={pregunta.pregunta.id_pregunta}
enunciado={pregunta.pregunta.pregunta}
validacion={pregunta.pregunta.validacion}
respuestas={respuestas}
cuentaInfo={cuentaInfo}
isComunidad={isComunidad?.label}
onChange={actualizarRespuesta}
/>
);
}
if (
pregunta.pregunta.tipo_pregunta.tipo_pregunta ===
'Abierta (Parrafo)'
) {
return (
<div key={pregunta.pregunta.id_pregunta} className="my-4">
<label
className={`form-label ${
pregunta.pregunta.obligatoria ? 'required' : ''
}`}
>
{pregunta.pregunta.pregunta}
</label>
<SimpleInput
type="textarea"
name={`respuesta_${pregunta.pregunta.id_pregunta}`}
placeholder="Ingrese una respuesta"
value={respuestas[pregunta.pregunta.id_pregunta] || ''}
onChange={(e) =>
setRespuestas((prev) => ({
...prev,
[pregunta.pregunta.id_pregunta]: e.target.value,
}))
}
/>
</div>
);
}
if (pregunta.pregunta.tipo_pregunta.tipo_pregunta === 'Cerrada') {
const opciones: RadioOption<number>[] =
pregunta.pregunta.opciones.map((op) => ({
label: op.opcion.opcion,
value: op.id_opcion,
}));
let respuestaActual =
respuestas[`${pregunta.pregunta.id_pregunta}`];
if (
confirmativeOption.includes(isComunidad?.label) &&
cuentaInfo &&
respuestaActual === undefined // solo si no ha respondido
) {
if (pregunta.pregunta.validacion === 'genero') {
const generoTexto =
cuentaInfo.genero === 'M' ? 'Masculino' : 'Femenino';
const opcionGenero = pregunta.pregunta.opciones.find(
(op) =>
op.opcion.opcion.toLowerCase() ===
generoTexto.toLowerCase()
);
if (opcionGenero) {
respuestaActual = String(opcionGenero.id_opcion);
}
}
}
return (
<div key={pregunta.pregunta.id_pregunta}>
<label
className={`form-label ${
pregunta.pregunta.obligatoria ? 'required' : ''
}`}
>
{pregunta.pregunta.pregunta}
</label>
<RadioOptionGroup
name={`pregunta_${pregunta.pregunta.id_pregunta}`}
options={opciones}
selectedValue={
respuestaActual ? Number(respuestaActual) : undefined
}
onChange={(opt) => {
actualizarRespuesta(
`${pregunta.pregunta.id_pregunta}`,
String(opt.value)
);
}}
/>
</div>
);
}
return (
<div key={pregunta.pregunta.id_pregunta} className="my-4">
<label
className={`form-label ${
pregunta.pregunta.obligatoria ? 'required' : ''
}`}
>
{pregunta.pregunta.pregunta}
</label>
</div>
);
})}
</div>
))}
<Button
className="btn btn-primary"
onClick={handleOnSubmit}
disabled={!mostrarFormularioRestante}
>
{isSending ? 'Enviando...' : 'Enviar Formulario'}
</Button>
</div>
);
}
@@ -0,0 +1,75 @@
import React from 'react';
import SimpleInput from '@/components/input';
type Props = {
idPregunta: number;
enunciado: string;
obligatorio?: boolean;
validacion?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
respuestas: Record<string, any>;
cuentaInfo: {
nombre: string;
apellidos: string;
correo: string;
genero: 'M' | 'F';
carrera: string;
} | null;
isComunidad: string | undefined;
onChange: (id: string, valor: string) => void;
};
const confirmativeOption = ['Sí', 'Si', 'Si, claro', 'Claro que sí'];
export default function PrefetchAbiertaCorta({
idPregunta,
enunciado,
validacion,
respuestas,
cuentaInfo,
isComunidad,
obligatorio,
onChange,
}: Props) {
let defaultValue = '';
let disabled = false;
if (confirmativeOption.includes(isComunidad ?? '') && cuentaInfo) {
if (validacion === 'nombre') {
defaultValue = cuentaInfo.nombre;
disabled = true;
}
if (validacion === 'apellidos') {
defaultValue = cuentaInfo.apellidos;
disabled = true;
}
if (validacion === 'correo') {
defaultValue = cuentaInfo.correo;
disabled = true;
}
if (validacion === 'institucion') {
defaultValue = 'FES Acatlán';
disabled = true;
}
if (validacion === 'carrera') {
defaultValue = cuentaInfo.carrera;
disabled = true;
}
}
return (
<div className="my-4">
<label className={`form-label ${obligatorio ? 'required' : ''}`}>
{enunciado}
</label>
<SimpleInput
type="text"
name={`respuesta_${idPregunta}`}
placeholder="Ingrese una respuesta"
value={respuestas[idPregunta] ?? defaultValue}
disabled={disabled}
onChange={(e) => onChange(idPregunta.toString(), e.target.value)}
/>
</div>
);
}