cuestionario validado, alerta de respuestas faltantes, ocultar preguntas, v2 en reportes
This commit is contained in:
@@ -14,6 +14,20 @@
|
||||
</b-select>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Version:">
|
||||
<b-select v-model="version" expanded>
|
||||
<option value="" disabled>Seleccione una version:</option>
|
||||
|
||||
<option value="v1">v1</option>
|
||||
|
||||
<option value="v2">
|
||||
v2
|
||||
</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
|
||||
|
||||
|
||||
<b-field label="Año:">
|
||||
<b-select v-model="selectedYear" expanded>
|
||||
<option value="" disabled>Seleccione un año:</option>
|
||||
@@ -51,6 +65,7 @@ export default {
|
||||
return {
|
||||
selectedCuestionario: '',
|
||||
selectedYear: '',
|
||||
version:''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -58,16 +73,24 @@ export default {
|
||||
this.updateIsLoading(true)
|
||||
axios
|
||||
.get(
|
||||
`${process.env.api}/${this.selectedCuestionario}?year=${this.selectedYear}`,
|
||||
this.admin.token
|
||||
`${process.env.api}/${this.selectedCuestionario}`, {
|
||||
params: {
|
||||
year: this.selectedYear,
|
||||
version: this.version,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.admin.token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
fileDownload(
|
||||
res.data,
|
||||
`${this.selectedYear}_${this.selectedCuestionario}.csv`
|
||||
`${this.selectedYear}_${this.selectedCuestionario}_${this.version}.csv`
|
||||
)
|
||||
this.selectedYear = ''
|
||||
this.selectedCuestionario = ''
|
||||
this.version = ''
|
||||
this.updateIsLoading(false)
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,951 @@
|
||||
<template>
|
||||
<div class="container mt-5">
|
||||
<!-- <h1 class="text-center mb-4">{{ formulario.titulo }}</h1>
|
||||
<p class="text-center">{{ formulario.descripcion }}</p> -->
|
||||
|
||||
|
||||
<div >
|
||||
<div v-for="(item, index) in sortedItems" :key="item.id || item.idTabla" class="mb-4 mt-6">
|
||||
<div v-if="item.tipo" class="mt-6">
|
||||
|
||||
<label :for="item.id" class="form-label">{{ item.numeroPregunta }}. {{ item.texto }}</label>
|
||||
|
||||
<div v-if="item.tipo === 'seleccionUnica'" :key="item.id">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<!-- :id="item.id" -->
|
||||
<b-radio
|
||||
v-model="respuestas[item.id]"
|
||||
:key="item.id + '-' + opcion"
|
||||
:native-value="opcion"
|
||||
type="is-info"
|
||||
@change="updateRespuestas(item.id, opcion)"
|
||||
>
|
||||
{{ opcion }}
|
||||
</b-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="item.tipo === 'seleccionMultiple'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<input
|
||||
class="checkb"
|
||||
type="checkbox"
|
||||
:value="opcion"
|
||||
|
||||
|
||||
:checked="respuestas[item.id].includes(opcion)"
|
||||
@change="toggleSelection(item.id, opcion, $event)"
|
||||
|
||||
/>
|
||||
{{ opcion }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- v-model="respuestas[item.id]" -->
|
||||
<div v-if="item.tipo === 'texto'">
|
||||
<b-input
|
||||
:id="item.id"
|
||||
v-model="respuestas[item.id]"
|
||||
placeholder="Escribe tu respuesta aquí"
|
||||
></b-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- <h3 class="mb-3">{{ item.numeroPregunta }}. {{ item.preguntaTabla }}</h3>
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">{{ item.subPreguntaTabla }}</h5>
|
||||
-->
|
||||
|
||||
<template v-if="index === 0 || item.numeroPregunta !== sortedItems[index - 1].numeroPregunta">
|
||||
<h3 class="mb-3">
|
||||
{{ item.numeroPregunta }}. {{ item.preguntaTabla }}
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<!-- Subtítulo (h5) siempre que exista -->
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">
|
||||
{{ item.subPreguntaTabla }}
|
||||
</h5>
|
||||
|
||||
<table class="table table-bordered text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th v-for="opcion in item.renglones[0].opciones" :key="opcion">{{ opcion }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="renglon in item.renglones" :key="renglon.idRenglon">
|
||||
<td>{{ renglon.textoRenglon }}</td>
|
||||
<td v-for="opcion in renglon.opciones" :key="opcion">
|
||||
<input
|
||||
type="radio"
|
||||
:name="`tabla-${item.idTabla}-renglon-${renglon.idRenglon}`"
|
||||
:value="opcion"
|
||||
v-model="respuestas[item.idTabla][renglon.idRenglon]"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="my-6 mb-6 has-text-centered">
|
||||
<b-field class="centro">
|
||||
<button
|
||||
class="button is-success is-medium"
|
||||
@click="() => { submitForm() }"
|
||||
:disabled="!isFormComplete"
|
||||
>
|
||||
Enviar
|
||||
</button>
|
||||
</b-field>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import Buefy from 'buefy'
|
||||
import 'buefy/dist/buefy.css'
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
respuestas: {}, // Inicialización para almacenar las respuestas
|
||||
|
||||
formulario: {
|
||||
titulo: '2025 Evaluación del Universitario(a)',
|
||||
descripcion:
|
||||
'Te invitamos a compartir tu experiencia respecto al programa de servicio social en el que participaste. Tus respuestas son confidenciales.',
|
||||
preguntas: [
|
||||
{
|
||||
id: 'criterios',
|
||||
tipo: 'seleccionMultiple',
|
||||
numeroPregunta:1,
|
||||
texto:
|
||||
'Señala los tres principales criterios que utilizaste para seleccionar el programa de servicio social',
|
||||
opciones: [
|
||||
|
||||
|
||||
'Actividades adscritas al programa',
|
||||
'Apoyo económico',
|
||||
'Asesoría académica',
|
||||
'Dependencia de la UNAM',
|
||||
'Flexibilidad en horarios',
|
||||
'Institución del sector público',
|
||||
'Institución del sector social',
|
||||
'Invitación de profesores',
|
||||
'Modalidad de titulación por servicio social',
|
||||
'Objetivo del programa',
|
||||
'Oportunidad de desarrollo de tesis',
|
||||
'Prestigio de la institución',
|
||||
'Recomendación de compañeros',
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
numeroPregunta:2,
|
||||
id: 'inscripcion',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Cómo evalúas tu proceso de inscripción?',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
{
|
||||
numeroPregunta:4,
|
||||
id: 'actividades',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Las actividades que realizaste fueron acordes a lo descrito en el programa?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:5,
|
||||
id: 'actividadesComentarios2',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'En caso de que las actividades que realizaste hayan sido distintas a las descritas en el programa, enlistas ¿Cuáles fueron?',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
{
|
||||
numeroPregunta:6,
|
||||
id: 'espacioFisico',
|
||||
tipo: 'seleccionUnica',
|
||||
texto:
|
||||
'¿Contaste con un espacio físico adecuado para realizar tus actividades?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:7,
|
||||
id: 'instalaciones',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: 'Las instalaciones en las que te desempeñaste, contaban con condiciones adecuadas para la realización de las actividades que te encomendaron',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:8,
|
||||
id: 'instalacionesComentarios',
|
||||
tipo: 'texto',
|
||||
texto: 'Si respondiste NO, ¿Por qué?',
|
||||
condicional: {
|
||||
preguntaId: 'instalaciones',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
{
|
||||
numeroPregunta:9,
|
||||
id: 'materialProporcionado',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿La institución te proporciono material/equipo necesario para el desempeño de tus actividades?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
|
||||
{
|
||||
numeroPregunta:13,
|
||||
id: 'supervisor',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Quién asesoró y supervisó las actividades que realizaste?',
|
||||
opciones: [
|
||||
|
||||
|
||||
'Coordinador administrativo del programa',
|
||||
'Responsable directo del programa',
|
||||
'Alguien diferente a los dos anteriores',
|
||||
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
numeroPregunta:14,
|
||||
id: 'apoyoEconomico',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: 'El apoyo económico señalado en el programa...',
|
||||
opciones: [
|
||||
'Se te otorgó de acuerdo a lo establecido',
|
||||
'Fue condicionado',
|
||||
'Se te proporcionó solo una parte',
|
||||
],
|
||||
},
|
||||
{
|
||||
numeroPregunta:15,
|
||||
id: 'recomendacion',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Recomendarías el programa en que participaste?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
numeroPregunta:16,
|
||||
id: 'actividadesComentarios3',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'¿Por qué?',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
numeroPregunta:18,
|
||||
id: 'actividadesComentarios1',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'Enlista los conocimiento o habilidades que te ayudarían a un mejor desempeño para tu actividad profesional a futuro',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
|
||||
tablas: [
|
||||
|
||||
|
||||
{
|
||||
idTabla: 130,
|
||||
preguntaTabla: '¿En la entidad o programa donde realizaste tu servicio social recibiste…?',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 3,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Asesoría',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Acompañamiento',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Supervisión',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Seguimiento',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 104,
|
||||
preguntaTabla: 'El trato que recibiste fue:',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 10,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Profesional',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Amable',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Respetuoso',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 105,
|
||||
preguntaTabla: 'En tu servicio social…',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 11,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Aplicaste conocimientos',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Desarrollaste habilidades',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Enriqueciste conocimientos',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Fortaleciste tus habilidades',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
idTabla: 106,
|
||||
preguntaTabla: 'Con respecto a la plataforma SIASSyPP web.',
|
||||
subPreguntaTabla: 'La información que te proporcionaron sobre los programas fue:',
|
||||
numeroPregunta: 17,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Adecuada',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Suficiente',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Actualizada',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 101,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'A. Habilidades personales',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Puntualidad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Eficiencia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Organización',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Eficacia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
idTabla: 102,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'B. Habilidades profesionales ',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Disposición',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Proactivo/anticipación',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Propositivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Resolutivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 103,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'C. Habilidades sociales',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Empatía',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Trabajo en equipo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Comunicación asertiva',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Receptividad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Tolerancia a la frustación',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
idTabla: 1042,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'D. Conocimientos',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Conocimientos teóricos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Conocimientos metodológicos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Pensamiento critico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Formación académica general',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Uso tecnológico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.respuestas = this.respuestas || {};
|
||||
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (!(pregunta.id in this.respuestas)) { // Solo inicializa si no existe
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
this.$set(this.respuestas, pregunta.id, []);
|
||||
} else {
|
||||
this.$set(this.respuestas, pregunta.id, null); // Usa null en lugar de ''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
if (!(tabla.idTabla in this.respuestas)) {
|
||||
this.$set(this.respuestas, tabla.idTabla, {});
|
||||
}
|
||||
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
if (!(renglon.idRenglon in this.respuestas[tabla.idTabla])) {
|
||||
this.$set(this.respuestas[tabla.idTabla], renglon.idRenglon, null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
watch: {
|
||||
respuestas: {
|
||||
handler(newVal) {
|
||||
console.log("Estado actualizado de respuestas:", newVal);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
computed: {
|
||||
sortedItems() {
|
||||
const items = [...this.formulario.preguntas, ...this.formulario.tablas]
|
||||
return items.sort((a, b) => {
|
||||
if (a.numeroPregunta === b.numeroPregunta) {
|
||||
return (a.idTabla || 0) - (b.idTabla || 0)
|
||||
}
|
||||
return a.numeroPregunta - b.numeroPregunta
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
isFormComplete() {
|
||||
// Verifica todas las preguntas individuales
|
||||
const allQuestionsAnswered = this.formulario.preguntas.every((pregunta) => {
|
||||
const respuesta = this.respuestas[pregunta.id];
|
||||
if (pregunta.tipo === "seleccionMultiple") {
|
||||
return respuesta && respuesta.length > 0; // Debe tener al menos una opción seleccionada
|
||||
}
|
||||
return respuesta !== null && respuesta !== ""; // No debe ser null ni vacío
|
||||
});
|
||||
|
||||
// Verifica todas las respuestas de la tabla
|
||||
const allTablesAnswered = this.formulario.tablas.every((tabla) => {
|
||||
return tabla.renglones.every((renglon) => {
|
||||
return this.respuestas[tabla.idTabla] && this.respuestas[tabla.idTabla][renglon.idRenglon] !== null;
|
||||
});
|
||||
});
|
||||
|
||||
return allQuestionsAnswered && allTablesAnswered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
toggleSelection(id, opcion, event) {
|
||||
let selectedOptions = this.respuestas[id];
|
||||
|
||||
if (selectedOptions.includes(opcion)) {
|
||||
// Si ya está seleccionada, se deselecciona
|
||||
this.respuestas[id] = selectedOptions.filter(opt => opt !== opcion);
|
||||
} else {
|
||||
if (selectedOptions.length < 3) {
|
||||
// Si hay espacio, se agrega la opción
|
||||
this.respuestas[id].push(opcion);
|
||||
} else {
|
||||
// Evita la selección de más de 3 opciones
|
||||
event.preventDefault();
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Límite alcanzado",
|
||||
message: "Solo puedes seleccionar hasta 3 opciones.",
|
||||
type: "is-warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
limitSelection(id, opcion, event) {
|
||||
if (this.respuestas[id].length >= 3 && !this.respuestas[id].includes(opcion)) {
|
||||
// Evita que se seleccione la opción adicional
|
||||
event.preventDefault();
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Límite alcanzado",
|
||||
message: "Solo puedes seleccionar hasta 3 opciones.",
|
||||
type: "is-warning",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
updateRespuestas(id, valor) {
|
||||
this.$set(this.respuestas, id, valor);
|
||||
console.log("Radio seleccionado:", id, valor);
|
||||
},
|
||||
|
||||
validateResponses() {
|
||||
for (const pregunta of this.formulario.preguntas) {
|
||||
const respuesta = this.respuestas[pregunta.id];
|
||||
|
||||
// Verifica que no haya respuestas vacías
|
||||
if (respuesta === null || respuesta === "") {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, responde la pregunta: "${pregunta.texto}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Para selección múltiple, al menos un elemento debe estar seleccionado
|
||||
if (pregunta.tipo === "seleccionMultiple" && (!respuesta || respuesta.length === 0)) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, selecciona al menos una opción en: "${pregunta.texto}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validación adicional si la pregunta es de texto (evitar respuestas peligrosas)
|
||||
if (pregunta.tipo === "texto" && respuesta.length > 500) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `La respuesta de la pregunta "${pregunta.texto}" es demasiado larga.`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica que todas las respuestas en las tablas estén completas
|
||||
for (const tabla of this.formulario.tablas) {
|
||||
for (const renglon of tabla.renglones) {
|
||||
const respuesta = this.respuestas[tabla.idTabla]?.[renglon.idRenglon];
|
||||
|
||||
if (respuesta === null) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, responde la pregunta en la tabla: "${tabla.preguntaTabla}" en la fila "${renglon.textoRenglon}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
|
||||
|
||||
if (!this.validateResponses()) return; // Detiene el envío si la validación falla
|
||||
console.log('Respuestas a enviar:', this.respuestas)
|
||||
//alert('Formulario enviado. Gracias por tu participación.')
|
||||
|
||||
|
||||
// Aquí formateamos las respuestas
|
||||
const respuestaFormateada = this.formatearRespuestas(this.respuestas)
|
||||
console.log('Respuestas formateadas:', respuestaFormateada)
|
||||
// this.sendAnswers(respuestaFormateada)
|
||||
|
||||
|
||||
|
||||
let data = { ...respuestaFormateada,
|
||||
idServicio: localStorage.getItem('idServicio'), // 4,
|
||||
p1: 'respuesta1 - trabajando para que sea una string',
|
||||
}
|
||||
|
||||
axios
|
||||
.post(`${process.env.api}/cuestionario_alumno`, data, //this.token
|
||||
)
|
||||
.then((res) => {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Success',
|
||||
message: 'Se enviaron los datos correctamente',
|
||||
type: 'is-success',
|
||||
hasIcon: true,
|
||||
icon: 'checkbox-marked-circle',
|
||||
ariaRole: 'alertdialog',
|
||||
ariaModal: true,
|
||||
})
|
||||
|
||||
//this.reset()
|
||||
localStorage.removeItem('idCuestionarioAlumno')
|
||||
this.$router.push('/alumno')
|
||||
})
|
||||
.catch((error) => {
|
||||
// this.error(error.response.data.message)
|
||||
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: error.response?.data?.message || "Error al enviar el formulario",
|
||||
type: "is-danger",
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
formatearRespuestas(respuestas) {
|
||||
// Objeto final a devolver
|
||||
const resultado = {}
|
||||
|
||||
// Recorremos todas las claves de "respuestas"
|
||||
for (const key in respuestas) {
|
||||
// Verificamos si es un ID de tabla (numérico) o un ID de pregunta (string)
|
||||
const esTabla = !isNaN(Number(key)) // true si la clave se puede convertir a número
|
||||
|
||||
if (esTabla) {
|
||||
// 1) BUSCAMOS LA DEFINICIÓN DE LA TABLA
|
||||
const idTabla = parseInt(key, 10)
|
||||
const tablaDef = this.formulario.tablas.find(t => t.idTabla === idTabla)
|
||||
if (!tablaDef) {
|
||||
// Si no se encontró la tabla, continuamos
|
||||
continue
|
||||
}
|
||||
|
||||
// 2) OBTENEMOS EL NÚMERO DE PREGUNTA Y, OPCIONALMENTE, LA LETRA (A, B, C...)
|
||||
const numPregunta = tablaDef.numeroPregunta
|
||||
|
||||
// Si quieres “sacar” la letra (A, B, C…) de algo como "A. Habilidades sociales"
|
||||
// Se puede hacer un match sencillo al principio
|
||||
let subLetra = ''
|
||||
if (tablaDef.subPreguntaTabla) {
|
||||
// Ejemplo: "A. Habilidades personales"
|
||||
const coincidencia = tablaDef.subPreguntaTabla.match(/^([A-E])\./)
|
||||
if (coincidencia) {
|
||||
subLetra = coincidencia[1] // 'A', 'B', 'C', etc.
|
||||
}
|
||||
}
|
||||
|
||||
// 3) LUEGO RECORREMOS LAS RESPUESTAS DE LA TABLA (por cada idRenglon)
|
||||
const respuestasTabla = respuestas[key] // p.ej: { "1": "Deficiente", "2": "Básico", ... }
|
||||
for (const idRenglon in respuestasTabla) {
|
||||
const valor = respuestasTabla[idRenglon]
|
||||
|
||||
// Formamos la clave final.
|
||||
// Si hay subLetra, hacemos `p3_A_1`. Sino, solo `p3_1`.
|
||||
let clave = `p${numPregunta}_${idRenglon}`
|
||||
if (subLetra) {
|
||||
clave = `p${numPregunta}_${subLetra}_${idRenglon}`
|
||||
}
|
||||
|
||||
resultado[clave] = valor
|
||||
}
|
||||
} else {
|
||||
// NO ES UNA TABLA => ES UNA PREGUNTA NORMAL
|
||||
// Buscamos su definición para obtener el numeroPregunta
|
||||
const preguntaDef = this.formulario.preguntas.find(p => p.id === key)
|
||||
if (!preguntaDef) {
|
||||
// No se encontró la definición (caso raro)
|
||||
continue
|
||||
}
|
||||
|
||||
const numPregunta = preguntaDef.numeroPregunta
|
||||
|
||||
// Creamos algo como `p2`, `p5`, etc.
|
||||
const clave = `p${numPregunta}`
|
||||
resultado[clave] = respuestas[key]
|
||||
}
|
||||
}
|
||||
|
||||
return resultado
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
|
||||
<!-- respuestas de cuestionario formulario2
|
||||
todas las preguntas se guardan correctamente
|
||||
{
|
||||
"p3_A_1": "Deficiente",
|
||||
"p3_A_2": "Deficiente",
|
||||
"p3_A_3": "Deficiente",
|
||||
"p3_A_4": "Deficiente",
|
||||
"p3_B_1": "Básico",
|
||||
"p3_B_2": "Básico",
|
||||
"p3_B_3": "Básico",
|
||||
"p3_B_4": "Básico",
|
||||
"p3_C_1": "Intermedio",
|
||||
"p3_C_2": "Intermedio",
|
||||
"p3_C_3": "Intermedio",
|
||||
"p3_C_4": "Intermedio",
|
||||
"p3_C_5": "Intermedio",
|
||||
"p3_D_1": "Destacado",
|
||||
"p3_D_2": "Destacado",
|
||||
"p3_D_3": "Destacado",
|
||||
"p3_D_4": "Destacado",
|
||||
"p3_D_5": "Destacado",
|
||||
"p3_E_1": "Deficiente",
|
||||
"p1": "respuesta1",
|
||||
"p2": "Excelente",
|
||||
"p4": "respuesta4",
|
||||
"p5": "Sí",
|
||||
"p6": "respuesta 6"
|
||||
} -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- respuestas de cuestionario formulario alumno
|
||||
|
||||
|
||||
{
|
||||
"p12_A_1": "Deficiente",
|
||||
"p12_A_2": "Deficiente",
|
||||
"p12_A_3": "Deficiente",
|
||||
"p12_A_4": "Deficiente",
|
||||
"p12_B_1": "Básico",
|
||||
"p12_B_2": "Básico",
|
||||
"p12_B_3": "Básico",
|
||||
"p12_B_4": "Básico",
|
||||
"p12_C_1": "Intermedio",
|
||||
"p12_C_2": "Intermedio",
|
||||
"p12_C_3": "Intermedio",
|
||||
"p12_C_4": "Intermedio",
|
||||
"p10_1": "si",
|
||||
"p10_2": "si",
|
||||
"p10_3": "si",
|
||||
"p11_1": "Nunca",
|
||||
"p11_2": "Rara vez",
|
||||
"p11_3": "Algunas veces",
|
||||
"p11_4": "Siempre",
|
||||
"p17_1": "si",
|
||||
"p17_2": "no",
|
||||
"p17_3": "si",
|
||||
"p3_1": "si",
|
||||
"p3_2": "si",
|
||||
"p3_3": "si",
|
||||
"p3_4": "si",
|
||||
"p12_D_1": "Destacado",
|
||||
"p12_D_2": "Destacado",
|
||||
"p12_D_3": "Destacado",
|
||||
"p12_D_4": "Destacado",
|
||||
"p12_D_5": "Destacado",
|
||||
"p1": [
|
||||
"Dependencia de la UNAM",
|
||||
"Asesoría académica",
|
||||
"Oportunidad de desarrollo de tesis"
|
||||
],
|
||||
"p2": "Deficiente",
|
||||
"p4": "No",
|
||||
"p5": "respuesta5",
|
||||
"p6": "Sí",
|
||||
"p7": "Sí",
|
||||
"p8": "respuesta8",
|
||||
"p9": "Sí",
|
||||
"p13": "Responsable directo del programa",
|
||||
"p14": "Se te otorgó de acuerdo a lo establecido",
|
||||
"p15": "Sí",
|
||||
"p16": "respuesta 16",
|
||||
"p18": "respuesta18"
|
||||
}
|
||||
|
||||
|
||||
-->
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,951 @@
|
||||
<template>
|
||||
<div class="container mt-5">
|
||||
<!-- <h1 class="text-center mb-4">{{ formulario.titulo }}</h1>
|
||||
<p class="text-center">{{ formulario.descripcion }}</p> -->
|
||||
|
||||
|
||||
<div >
|
||||
<div v-for="(item, index) in sortedItems" :key="item.id || item.idTabla" class="mb-4 mt-6">
|
||||
<div v-if="item.tipo" class="mt-6">
|
||||
|
||||
<label :for="item.id" class="form-label">{{ item.numeroPregunta }}. {{ item.texto }}</label>
|
||||
|
||||
<div v-if="item.tipo === 'seleccionUnica'" :key="item.id">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<!-- :id="item.id" -->
|
||||
<b-radio
|
||||
v-model="respuestas[item.id]"
|
||||
:key="item.id + '-' + opcion"
|
||||
:native-value="opcion"
|
||||
type="is-info"
|
||||
@change="updateRespuestas(item.id, opcion)"
|
||||
>
|
||||
{{ opcion }}
|
||||
</b-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="item.tipo === 'seleccionMultiple'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<input
|
||||
class="checkb"
|
||||
type="checkbox"
|
||||
:value="opcion"
|
||||
|
||||
|
||||
:checked="respuestas[item.id].includes(opcion)"
|
||||
@change="toggleSelection(item.id, opcion, $event)"
|
||||
|
||||
/>
|
||||
{{ opcion }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- v-model="respuestas[item.id]" -->
|
||||
<div v-if="item.tipo === 'texto'">
|
||||
<b-input
|
||||
:id="item.id"
|
||||
v-model="respuestas[item.id]"
|
||||
placeholder="Escribe tu respuesta aquí"
|
||||
></b-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- <h3 class="mb-3">{{ item.numeroPregunta }}. {{ item.preguntaTabla }}</h3>
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">{{ item.subPreguntaTabla }}</h5>
|
||||
-->
|
||||
|
||||
<template v-if="index === 0 || item.numeroPregunta !== sortedItems[index - 1].numeroPregunta">
|
||||
<h3 class="mb-3">
|
||||
{{ item.numeroPregunta }}. {{ item.preguntaTabla }}
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<!-- Subtítulo (h5) siempre que exista -->
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">
|
||||
{{ item.subPreguntaTabla }}
|
||||
</h5>
|
||||
|
||||
<table class="table table-bordered text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th v-for="opcion in item.renglones[0].opciones" :key="opcion">{{ opcion }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="renglon in item.renglones" :key="renglon.idRenglon">
|
||||
<td>{{ renglon.textoRenglon }}</td>
|
||||
<td v-for="opcion in renglon.opciones" :key="opcion">
|
||||
<input
|
||||
type="radio"
|
||||
:name="`tabla-${item.idTabla}-renglon-${renglon.idRenglon}`"
|
||||
:value="opcion"
|
||||
v-model="respuestas[item.idTabla][renglon.idRenglon]"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="my-6 mb-6" >
|
||||
<b-field class="centro">
|
||||
<button
|
||||
class="button is-success is-medium"
|
||||
@click="() => { submitForm() }"
|
||||
:disabled="!isFormComplete"
|
||||
>
|
||||
Enviar
|
||||
</button>
|
||||
</b-field>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import Buefy from 'buefy'
|
||||
import 'buefy/dist/buefy.css'
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
respuestas: {}, // Inicialización para almacenar las respuestas
|
||||
|
||||
formulario: {
|
||||
titulo: '2025 Evaluación del Universitario(a)',
|
||||
descripcion:
|
||||
'Te invitamos a compartir tu experiencia respecto al programa de servicio social en el que participaste. Tus respuestas son confidenciales.',
|
||||
preguntas: [
|
||||
{
|
||||
id: 'criterios',
|
||||
tipo: 'seleccionMultiple',
|
||||
numeroPregunta:1,
|
||||
texto:
|
||||
'Señala los tres principales criterios que utilizaste para seleccionar el programa de servicio social',
|
||||
opciones: [
|
||||
|
||||
|
||||
'Actividades adscritas al programa',
|
||||
'Apoyo económico',
|
||||
'Asesoría académica',
|
||||
'Dependencia de la UNAM',
|
||||
'Flexibilidad en horarios',
|
||||
'Institución del sector público',
|
||||
'Institución del sector social',
|
||||
'Invitación de profesores',
|
||||
'Modalidad de titulación por servicio social',
|
||||
'Objetivo del programa',
|
||||
'Oportunidad de desarrollo de tesis',
|
||||
'Prestigio de la institución',
|
||||
'Recomendación de compañeros',
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
numeroPregunta:2,
|
||||
id: 'inscripcion',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Cómo evalúas tu proceso de inscripción?',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
{
|
||||
numeroPregunta:4,
|
||||
id: 'actividades',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Las actividades que realizaste fueron acordes a lo descrito en el programa?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:5,
|
||||
id: 'actividadesComentarios2',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'En caso de que las actividades que realizaste hayan sido distintas a las descritas en el programa, enlistas ¿Cuáles fueron?',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
{
|
||||
numeroPregunta:6,
|
||||
id: 'espacioFisico',
|
||||
tipo: 'seleccionUnica',
|
||||
texto:
|
||||
'¿Contaste con un espacio físico adecuado para realizar tus actividades?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:7,
|
||||
id: 'instalaciones',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: 'Las instalaciones en las que te desempeñaste, contaban con condiciones adecuadas para la realización de las actividades que te encomendaron',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta:8,
|
||||
id: 'instalacionesComentarios',
|
||||
tipo: 'texto',
|
||||
texto: 'Si respondiste NO, ¿Por qué?',
|
||||
condicional: {
|
||||
preguntaId: 'instalaciones',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
{
|
||||
numeroPregunta:9,
|
||||
id: 'materialProporcionado',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿La institución te proporciono material/equipo necesario para el desempeño de tus actividades?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
|
||||
{
|
||||
numeroPregunta:13,
|
||||
id: 'supervisor',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Quién asesoró y supervisó las actividades que realizaste?',
|
||||
opciones: [
|
||||
|
||||
|
||||
'Coordinador administrativo del programa',
|
||||
'Responsable directo del programa',
|
||||
'Alguien diferente a los dos anteriores',
|
||||
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
numeroPregunta:14,
|
||||
id: 'apoyoEconomico',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: 'El apoyo económico señalado en el programa...',
|
||||
opciones: [
|
||||
'Se te otorgó de acuerdo a lo establecido',
|
||||
'Fue condicionado',
|
||||
'Se te proporcionó solo una parte',
|
||||
],
|
||||
},
|
||||
{
|
||||
numeroPregunta:15,
|
||||
id: 'recomendacion',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Recomendarías el programa en que participaste?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
numeroPregunta:16,
|
||||
id: 'actividadesComentarios3',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'¿Por qué?',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
numeroPregunta:18,
|
||||
id: 'actividadesComentarios1',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'Enlista los conocimiento o habilidades que te ayudarían a un mejor desempeño para tu actividad profesional a futuro',
|
||||
condicional: {
|
||||
preguntaId: 'actividades',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
|
||||
tablas: [
|
||||
|
||||
|
||||
{
|
||||
idTabla: 130,
|
||||
preguntaTabla: '¿En la entidad o programa donde realizaste tu servicio social recibiste…?',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 3,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Asesoría',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Acompañamiento',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Supervisión',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Seguimiento',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 104,
|
||||
preguntaTabla: 'El trato que recibiste fue:',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 10,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Profesional',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Amable',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Respetuoso',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 105,
|
||||
preguntaTabla: 'En tu servicio social…',
|
||||
subPreguntaTabla: '',
|
||||
numeroPregunta: 11,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Aplicaste conocimientos',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Desarrollaste habilidades',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Enriqueciste conocimientos',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Fortaleciste tus habilidades',
|
||||
opciones: ['Nunca', 'Rara vez', 'Algunas veces','Regularmente', 'Siempre'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
idTabla: 106,
|
||||
preguntaTabla: 'Con respecto a la plataforma SIASSyPP web.',
|
||||
subPreguntaTabla: 'La información que te proporcionaron sobre los programas fue:',
|
||||
numeroPregunta: 17,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Adecuada',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Suficiente',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Actualizada',
|
||||
opciones: ['si', 'no'],
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 101,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'A. Habilidades personales',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Puntualidad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Eficiencia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Organización',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Eficacia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
idTabla: 102,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'B. Habilidades profesionales ',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Disposición',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Proactivo/anticipación',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Propositivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Resolutivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
idTabla: 103,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'C. Habilidades sociales',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Empatía',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Trabajo en equipo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Comunicación asertiva',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Receptividad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Tolerancia a la frustación',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
idTabla: 1042,
|
||||
preguntaTabla: 'Evalúa tu propio desempeño en el servicio social en relación con',
|
||||
subPreguntaTabla: 'D. Conocimientos',
|
||||
numeroPregunta: 12,
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Conocimientos teóricos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Conocimientos metodológicos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Pensamiento critico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Formación académica general',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Uso tecnológico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.respuestas = this.respuestas || {};
|
||||
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (!(pregunta.id in this.respuestas)) { // Solo inicializa si no existe
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
this.$set(this.respuestas, pregunta.id, []);
|
||||
} else {
|
||||
this.$set(this.respuestas, pregunta.id, null); // Usa null en lugar de ''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
if (!(tabla.idTabla in this.respuestas)) {
|
||||
this.$set(this.respuestas, tabla.idTabla, {});
|
||||
}
|
||||
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
if (!(renglon.idRenglon in this.respuestas[tabla.idTabla])) {
|
||||
this.$set(this.respuestas[tabla.idTabla], renglon.idRenglon, null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
watch: {
|
||||
respuestas: {
|
||||
handler(newVal) {
|
||||
console.log("Estado actualizado de respuestas:", newVal);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
computed: {
|
||||
sortedItems() {
|
||||
const items = [...this.formulario.preguntas, ...this.formulario.tablas]
|
||||
return items.sort((a, b) => {
|
||||
if (a.numeroPregunta === b.numeroPregunta) {
|
||||
return (a.idTabla || 0) - (b.idTabla || 0)
|
||||
}
|
||||
return a.numeroPregunta - b.numeroPregunta
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
isFormComplete() {
|
||||
// Verifica todas las preguntas individuales
|
||||
const allQuestionsAnswered = this.formulario.preguntas.every((pregunta) => {
|
||||
const respuesta = this.respuestas[pregunta.id];
|
||||
if (pregunta.tipo === "seleccionMultiple") {
|
||||
return respuesta && respuesta.length > 0; // Debe tener al menos una opción seleccionada
|
||||
}
|
||||
return respuesta !== null && respuesta !== ""; // No debe ser null ni vacío
|
||||
});
|
||||
|
||||
// Verifica todas las respuestas de la tabla
|
||||
const allTablesAnswered = this.formulario.tablas.every((tabla) => {
|
||||
return tabla.renglones.every((renglon) => {
|
||||
return this.respuestas[tabla.idTabla] && this.respuestas[tabla.idTabla][renglon.idRenglon] !== null;
|
||||
});
|
||||
});
|
||||
|
||||
return allQuestionsAnswered && allTablesAnswered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
toggleSelection(id, opcion, event) {
|
||||
let selectedOptions = this.respuestas[id];
|
||||
|
||||
if (selectedOptions.includes(opcion)) {
|
||||
// Si ya está seleccionada, se deselecciona
|
||||
this.respuestas[id] = selectedOptions.filter(opt => opt !== opcion);
|
||||
} else {
|
||||
if (selectedOptions.length < 3) {
|
||||
// Si hay espacio, se agrega la opción
|
||||
this.respuestas[id].push(opcion);
|
||||
} else {
|
||||
// Evita la selección de más de 3 opciones
|
||||
event.preventDefault();
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Límite alcanzado",
|
||||
message: "Solo puedes seleccionar hasta 3 opciones.",
|
||||
type: "is-warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
limitSelection(id, opcion, event) {
|
||||
if (this.respuestas[id].length >= 3 && !this.respuestas[id].includes(opcion)) {
|
||||
// Evita que se seleccione la opción adicional
|
||||
event.preventDefault();
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Límite alcanzado",
|
||||
message: "Solo puedes seleccionar hasta 3 opciones.",
|
||||
type: "is-warning",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
updateRespuestas(id, valor) {
|
||||
this.$set(this.respuestas, id, valor);
|
||||
console.log("Radio seleccionado:", id, valor);
|
||||
},
|
||||
|
||||
validateResponses() {
|
||||
for (const pregunta of this.formulario.preguntas) {
|
||||
const respuesta = this.respuestas[pregunta.id];
|
||||
|
||||
// Verifica que no haya respuestas vacías
|
||||
if (respuesta === null || respuesta === "") {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, responde la pregunta: "${pregunta.texto}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Para selección múltiple, al menos un elemento debe estar seleccionado
|
||||
if (pregunta.tipo === "seleccionMultiple" && (!respuesta || respuesta.length === 0)) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, selecciona al menos una opción en: "${pregunta.texto}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validación adicional si la pregunta es de texto (evitar respuestas peligrosas)
|
||||
if (pregunta.tipo === "texto" && respuesta.length > 500) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `La respuesta de la pregunta "${pregunta.texto}" es demasiado larga.`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica que todas las respuestas en las tablas estén completas
|
||||
for (const tabla of this.formulario.tablas) {
|
||||
for (const renglon of tabla.renglones) {
|
||||
const respuesta = this.respuestas[tabla.idTabla]?.[renglon.idRenglon];
|
||||
|
||||
if (respuesta === null) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: `Por favor, responde la pregunta en la tabla: "${tabla.preguntaTabla}" en la fila "${renglon.textoRenglon}"`,
|
||||
type: "is-danger",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
|
||||
|
||||
if (!this.validateResponses()) return; // Detiene el envío si la validación falla
|
||||
console.log('Respuestas a enviar:', this.respuestas)
|
||||
//alert('Formulario enviado. Gracias por tu participación.')
|
||||
|
||||
|
||||
// Aquí formateamos las respuestas
|
||||
const respuestaFormateada = this.formatearRespuestas(this.respuestas)
|
||||
console.log('Respuestas formateadas:', respuestaFormateada)
|
||||
// this.sendAnswers(respuestaFormateada)
|
||||
|
||||
|
||||
|
||||
let data = { ...respuestaFormateada,
|
||||
idServicio: localStorage.getItem('idServicio'), // 4,
|
||||
p1: 'respuesta1 - trabajando para que sea una string',
|
||||
}
|
||||
|
||||
axios
|
||||
.post(`${process.env.api}/cuestionario_alumno`, data, //this.token
|
||||
)
|
||||
.then((res) => {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Success',
|
||||
message: 'Se enviaron los datos correctamente',
|
||||
type: 'is-success',
|
||||
hasIcon: true,
|
||||
icon: 'checkbox-marked-circle',
|
||||
ariaRole: 'alertdialog',
|
||||
ariaModal: true,
|
||||
})
|
||||
|
||||
//this.reset()
|
||||
localStorage.removeItem('idCuestionarioAlumno')
|
||||
this.$router.push('/alumno')
|
||||
})
|
||||
.catch((error) => {
|
||||
// this.error(error.response.data.message)
|
||||
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: "Error",
|
||||
message: error.response?.data?.message || "Error al enviar el formulario",
|
||||
type: "is-danger",
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
formatearRespuestas(respuestas) {
|
||||
// Objeto final a devolver
|
||||
const resultado = {}
|
||||
|
||||
// Recorremos todas las claves de "respuestas"
|
||||
for (const key in respuestas) {
|
||||
// Verificamos si es un ID de tabla (numérico) o un ID de pregunta (string)
|
||||
const esTabla = !isNaN(Number(key)) // true si la clave se puede convertir a número
|
||||
|
||||
if (esTabla) {
|
||||
// 1) BUSCAMOS LA DEFINICIÓN DE LA TABLA
|
||||
const idTabla = parseInt(key, 10)
|
||||
const tablaDef = this.formulario.tablas.find(t => t.idTabla === idTabla)
|
||||
if (!tablaDef) {
|
||||
// Si no se encontró la tabla, continuamos
|
||||
continue
|
||||
}
|
||||
|
||||
// 2) OBTENEMOS EL NÚMERO DE PREGUNTA Y, OPCIONALMENTE, LA LETRA (A, B, C...)
|
||||
const numPregunta = tablaDef.numeroPregunta
|
||||
|
||||
// Si quieres “sacar” la letra (A, B, C…) de algo como "A. Habilidades sociales"
|
||||
// Se puede hacer un match sencillo al principio
|
||||
let subLetra = ''
|
||||
if (tablaDef.subPreguntaTabla) {
|
||||
// Ejemplo: "A. Habilidades personales"
|
||||
const coincidencia = tablaDef.subPreguntaTabla.match(/^([A-E])\./)
|
||||
if (coincidencia) {
|
||||
subLetra = coincidencia[1] // 'A', 'B', 'C', etc.
|
||||
}
|
||||
}
|
||||
|
||||
// 3) LUEGO RECORREMOS LAS RESPUESTAS DE LA TABLA (por cada idRenglon)
|
||||
const respuestasTabla = respuestas[key] // p.ej: { "1": "Deficiente", "2": "Básico", ... }
|
||||
for (const idRenglon in respuestasTabla) {
|
||||
const valor = respuestasTabla[idRenglon]
|
||||
|
||||
// Formamos la clave final.
|
||||
// Si hay subLetra, hacemos `p3_A_1`. Sino, solo `p3_1`.
|
||||
let clave = `p${numPregunta}_${idRenglon}`
|
||||
if (subLetra) {
|
||||
clave = `p${numPregunta}_${subLetra}_${idRenglon}`
|
||||
}
|
||||
|
||||
resultado[clave] = valor
|
||||
}
|
||||
} else {
|
||||
// NO ES UNA TABLA => ES UNA PREGUNTA NORMAL
|
||||
// Buscamos su definición para obtener el numeroPregunta
|
||||
const preguntaDef = this.formulario.preguntas.find(p => p.id === key)
|
||||
if (!preguntaDef) {
|
||||
// No se encontró la definición (caso raro)
|
||||
continue
|
||||
}
|
||||
|
||||
const numPregunta = preguntaDef.numeroPregunta
|
||||
|
||||
// Creamos algo como `p2`, `p5`, etc.
|
||||
const clave = `p${numPregunta}`
|
||||
resultado[clave] = respuestas[key]
|
||||
}
|
||||
}
|
||||
|
||||
return resultado
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- respuestas de cuestionario formulario2
|
||||
todas las preguntas se guardan correctamente
|
||||
{
|
||||
"p3_A_1": "Deficiente",
|
||||
"p3_A_2": "Deficiente",
|
||||
"p3_A_3": "Deficiente",
|
||||
"p3_A_4": "Deficiente",
|
||||
"p3_B_1": "Básico",
|
||||
"p3_B_2": "Básico",
|
||||
"p3_B_3": "Básico",
|
||||
"p3_B_4": "Básico",
|
||||
"p3_C_1": "Intermedio",
|
||||
"p3_C_2": "Intermedio",
|
||||
"p3_C_3": "Intermedio",
|
||||
"p3_C_4": "Intermedio",
|
||||
"p3_C_5": "Intermedio",
|
||||
"p3_D_1": "Destacado",
|
||||
"p3_D_2": "Destacado",
|
||||
"p3_D_3": "Destacado",
|
||||
"p3_D_4": "Destacado",
|
||||
"p3_D_5": "Destacado",
|
||||
"p3_E_1": "Deficiente",
|
||||
"p1": "respuesta1",
|
||||
"p2": "Excelente",
|
||||
"p4": "respuesta4",
|
||||
"p5": "Sí",
|
||||
"p6": "respuesta 6"
|
||||
} -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- respuestas de cuestionario formulario alumno
|
||||
|
||||
|
||||
{
|
||||
"p12_A_1": "Deficiente",
|
||||
"p12_A_2": "Deficiente",
|
||||
"p12_A_3": "Deficiente",
|
||||
"p12_A_4": "Deficiente",
|
||||
"p12_B_1": "Básico",
|
||||
"p12_B_2": "Básico",
|
||||
"p12_B_3": "Básico",
|
||||
"p12_B_4": "Básico",
|
||||
"p12_C_1": "Intermedio",
|
||||
"p12_C_2": "Intermedio",
|
||||
"p12_C_3": "Intermedio",
|
||||
"p12_C_4": "Intermedio",
|
||||
"p10_1": "si",
|
||||
"p10_2": "si",
|
||||
"p10_3": "si",
|
||||
"p11_1": "Nunca",
|
||||
"p11_2": "Rara vez",
|
||||
"p11_3": "Algunas veces",
|
||||
"p11_4": "Siempre",
|
||||
"p17_1": "si",
|
||||
"p17_2": "no",
|
||||
"p17_3": "si",
|
||||
"p3_1": "si",
|
||||
"p3_2": "si",
|
||||
"p3_3": "si",
|
||||
"p3_4": "si",
|
||||
"p12_D_1": "Destacado",
|
||||
"p12_D_2": "Destacado",
|
||||
"p12_D_3": "Destacado",
|
||||
"p12_D_4": "Destacado",
|
||||
"p12_D_5": "Destacado",
|
||||
"p1": [
|
||||
"Dependencia de la UNAM",
|
||||
"Asesoría académica",
|
||||
"Oportunidad de desarrollo de tesis"
|
||||
],
|
||||
"p2": "Deficiente",
|
||||
"p4": "No",
|
||||
"p5": "respuesta5",
|
||||
"p6": "Sí",
|
||||
"p7": "Sí",
|
||||
"p8": "respuesta8",
|
||||
"p9": "Sí",
|
||||
"p13": "Responsable directo del programa",
|
||||
"p14": "Se te otorgó de acuerdo a lo establecido",
|
||||
"p15": "Sí",
|
||||
"p16": "respuesta 16",
|
||||
"p18": "respuesta18"
|
||||
}
|
||||
|
||||
|
||||
-->
|
||||
@@ -1,19 +1,35 @@
|
||||
<template>
|
||||
<div class="container mt-5">
|
||||
<!--
|
||||
<h1 class="text-center mb-4">{{ formulario.titulo }}</h1>
|
||||
<p class="text-center">{{ formulario.descripcion }}</p> -->
|
||||
<!-- Notificación flotante sin botón de cierre -->
|
||||
<b-notification
|
||||
v-if="pendingItems.length && !isMobile"
|
||||
type="is-warning"
|
||||
class="notification-floating"
|
||||
aria-close-label="Not applicable"
|
||||
:closable="false"
|
||||
>
|
||||
<p><strong>Te faltan contestar:</strong></p>
|
||||
<ul>
|
||||
<li v-for="(item, idx) in pendingItems" :key="idx">
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</b-notification>
|
||||
|
||||
<div>
|
||||
<div
|
||||
v-for="(item, index) in sortedItems"
|
||||
:key="item.id || item.idTabla"
|
||||
class="mb-6"
|
||||
v-if="isItemVisible(item)"
|
||||
>
|
||||
<!-- PREGUNTAS (texto, selección única, selección múltiple) -->
|
||||
<div v-if="item.tipo" class="mt-6">
|
||||
<label :for="item.id" class="form-label"
|
||||
>{{ item.numeroPregunta }}. {{ item.texto }}</label
|
||||
>
|
||||
<label :for="item.id" class="form-label">
|
||||
{{ item.numeroPregunta }}. {{ item.texto }}
|
||||
</label>
|
||||
|
||||
<!-- Selección Única -->
|
||||
<div v-if="item.tipo === 'seleccionUnica'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<b-radio
|
||||
@@ -26,6 +42,8 @@
|
||||
</b-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Selección Múltiple -->
|
||||
<div v-if="item.tipo === 'seleccionMultiple'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<input
|
||||
@@ -34,23 +52,25 @@
|
||||
:value="opcion"
|
||||
v-model="respuestas[item.id]"
|
||||
/>
|
||||
|
||||
{{ opcion }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Texto -->
|
||||
<div v-if="item.tipo === 'texto'">
|
||||
<b-input
|
||||
:id="item.id"
|
||||
v-model="respuestas[item.id]"
|
||||
|
||||
:maxlength="item.limite"
|
||||
show-counter
|
||||
placeholder="Escribe tu respuesta aquí"
|
||||
></b-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- <h3 class="mb-3">{{ item.numeroPregunta }}. {{ item.preguntaTabla }}</h3>
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">{{ item.subPreguntaTabla }}</h5>
|
||||
-->
|
||||
|
||||
<!-- TABLAS -->
|
||||
<div class="table-responsive" v-else>
|
||||
<template
|
||||
v-if="
|
||||
index === 0 ||
|
||||
@@ -62,7 +82,6 @@
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<!-- Subtítulo (h5) siempre que exista -->
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">
|
||||
{{ item.subPreguntaTabla }}
|
||||
</h5>
|
||||
@@ -94,11 +113,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BOTÓN ENVIAR -->
|
||||
<div class="my-6 mb-6">
|
||||
<b-field class="centro">
|
||||
<button
|
||||
class="button is-success is-medium"
|
||||
@click="() => {submitForm()}"
|
||||
@click="submitForm"
|
||||
:disabled="!isFormComplete"
|
||||
>
|
||||
Enviar
|
||||
@@ -116,7 +136,8 @@ import axios from 'axios'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
respuestas: {}, // Inicialización para almacenar las respuestas
|
||||
isLoading: false,
|
||||
respuestas: {},
|
||||
|
||||
formulario: {
|
||||
titulo:
|
||||
@@ -125,7 +146,6 @@ export default {
|
||||
Te solicitamos llenar cuidadosamente los campos solicitados a continuación para poder
|
||||
validar el término del servicio social de nuestro alumno(a).
|
||||
|
||||
|
||||
Los datos están sujetos al aviso de privacidad integral que se puede consultar en el sitio web: www.acatlan.unam.mx/normatividad`,
|
||||
|
||||
preguntas: [
|
||||
@@ -133,23 +153,25 @@ export default {
|
||||
numeroPregunta: 1,
|
||||
id: 'actividadesUniversitario',
|
||||
tipo: 'texto',
|
||||
limite: 100,
|
||||
texto:
|
||||
'Mencione las principales actividades que realizó el/la universitario(a) en su programa de servicio social',
|
||||
'Mencione las principales actividades que realizó el/la universitario(a) en su programa de servicio social',
|
||||
},
|
||||
{
|
||||
numeroPregunta: 2,
|
||||
id: 'calificacionGeneral',
|
||||
tipo: 'seleccionUnica',
|
||||
texto:
|
||||
'Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
'Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
opciones: ['Excelente', 'Bueno', 'Regular', 'Deficiente'],
|
||||
},
|
||||
{
|
||||
numeroPregunta: 4,
|
||||
id: 'cursosComplementarios',
|
||||
tipo: 'texto',
|
||||
limite: 100,
|
||||
texto:
|
||||
'¿Qué cursos considera que complementarían la formación de nuestros egresados?',
|
||||
'¿Qué cursos considera que complementarían la formación de nuestros egresados?',
|
||||
},
|
||||
{
|
||||
numeroPregunta: 5,
|
||||
@@ -162,6 +184,7 @@ export default {
|
||||
numeroPregunta: 6,
|
||||
id: 'porqueNoContrataria',
|
||||
tipo: 'texto',
|
||||
limite: 100,
|
||||
texto:
|
||||
'Si su respuesta a la pregunta anterior fue NO, comente ¿por qué?',
|
||||
condicional: {
|
||||
@@ -172,7 +195,7 @@ export default {
|
||||
],
|
||||
|
||||
tablas: [
|
||||
// ----- PREGUNTA 3, dividida en sub-secciones A, B, C, D, E ------
|
||||
// ----- PREGUNTA 3, dividida en sub-secciones A, B, C, D ------
|
||||
{
|
||||
idTabla: 301,
|
||||
numeroPregunta: 3,
|
||||
@@ -299,64 +322,22 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
/* {
|
||||
idTabla: 305,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'3. Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'E. Otro',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Otro',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
}, */
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
/* created() {
|
||||
// Inicializa las respuestas vacías para cada pregunta
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (pregunta.tipo === 'evaluacion') {
|
||||
this.respuestas[pregunta.id] = {}
|
||||
pregunta.categorias.forEach((categoria) => {
|
||||
categoria.items.forEach((item) => {
|
||||
this.respuestas[pregunta.id][item] = ''
|
||||
})
|
||||
})
|
||||
} else if (
|
||||
pregunta.tipo === 'checkbox' ||
|
||||
pregunta.tipo === 'seleccionMultiple'
|
||||
) {
|
||||
this.respuestas[pregunta.id] = []
|
||||
} else {
|
||||
this.respuestas[pregunta.id] = ''
|
||||
}
|
||||
})
|
||||
|
||||
// Inicializa respuestas para cada tabla
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
this.$set(this.respuestas, tabla.idTabla, {}); // Asegura que exista respuestas[tabla.idTabla]
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
this.$set(this.respuestas[tabla.idTabla], renglon.idRenglon, null); // Asegura que exista respuestas[tabla.idTabla][renglon.idRenglon]
|
||||
});
|
||||
});
|
||||
}, */
|
||||
|
||||
created() {
|
||||
// Inicializa las respuestas de cada pregunta
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
this.$set(this.respuestas, pregunta.id, []) // Inicializar correctamente selección múltiple
|
||||
this.$set(this.respuestas, pregunta.id, [])
|
||||
} else {
|
||||
this.$set(this.respuestas, pregunta.id, '') // Otras preguntas como texto o selección única
|
||||
this.$set(this.respuestas, pregunta.id, '')
|
||||
}
|
||||
})
|
||||
|
||||
// Inicializa respuestas para cada tabla
|
||||
// Inicializa las respuestas para cada tabla
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
this.$set(this.respuestas, tabla.idTabla, {})
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
@@ -366,6 +347,14 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
|
||||
isMobile() {
|
||||
return window.innerWidth < 576
|
||||
},
|
||||
|
||||
|
||||
// Combina preguntas y tablas en un array ordenado
|
||||
sortedItems() {
|
||||
const items = [...this.formulario.preguntas, ...this.formulario.tablas]
|
||||
return items.sort((a, b) => {
|
||||
@@ -376,58 +365,78 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
isFormComplete() {
|
||||
// Verifica todas las preguntas individuales
|
||||
const allQuestionsAnswered = this.formulario.preguntas.every(
|
||||
(pregunta) => {
|
||||
const respuesta = this.respuestas[pregunta.id]
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
return respuesta && respuesta.length > 0 // Debe tener al menos una opción seleccionada
|
||||
}
|
||||
return respuesta !== null && respuesta !== '' // No debe ser null ni vacío
|
||||
}
|
||||
)
|
||||
// Determina los ítems (preguntas/tablas) que siguen pendientes
|
||||
pendingItems() {
|
||||
let missing = []
|
||||
|
||||
// Verifica todas las respuestas de la tabla
|
||||
const allTablesAnswered = this.formulario.tablas.every((tabla) => {
|
||||
return tabla.renglones.every((renglon) => {
|
||||
return (
|
||||
this.respuestas[tabla.idTabla] &&
|
||||
this.respuestas[tabla.idTabla][renglon.idRenglon] !== null
|
||||
)
|
||||
})
|
||||
// Revisar preguntas (solo las que estén visibles)
|
||||
this.formulario.preguntas.forEach((p) => {
|
||||
if (!this.isItemVisible(p)) return
|
||||
const answer = this.respuestas[p.id]
|
||||
let answered = false
|
||||
|
||||
if (p.tipo === 'seleccionMultiple') {
|
||||
answered = answer && answer.length > 0
|
||||
} else {
|
||||
answered = answer !== null && answer !== ''
|
||||
}
|
||||
|
||||
if (!answered) {
|
||||
missing.push(`Pregunta ${p.numeroPregunta}`)
|
||||
}
|
||||
})
|
||||
|
||||
return allQuestionsAnswered && allTablesAnswered
|
||||
// Revisar tablas
|
||||
this.formulario.tablas.forEach((t) => {
|
||||
let allAnswered = t.renglones.every(
|
||||
(r) =>
|
||||
this.respuestas[t.idTabla] &&
|
||||
this.respuestas[t.idTabla][r.idRenglon] !== null
|
||||
)
|
||||
if (!allAnswered) {
|
||||
missing.push(`Tabla ${t.numeroPregunta}`)
|
||||
}
|
||||
})
|
||||
|
||||
return missing
|
||||
},
|
||||
|
||||
// El formulario se considera completo si no hay ítems pendientes
|
||||
isFormComplete() {
|
||||
return this.pendingItems.length === 0
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
// Determina si un item (pregunta/tabla) debe mostrarse (condicional)
|
||||
isItemVisible(item) {
|
||||
if (item.condicional) {
|
||||
// Checa la respuesta de la pregunta 'preguntaId'
|
||||
const respuestaCond = this.respuestas[item.condicional.preguntaId]
|
||||
return respuestaCond === item.condicional.valor
|
||||
}
|
||||
return true
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
if (!this.validateResponses()) {
|
||||
return // Detiene el envío si la validación falla
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Respuestas enviadas:', this.respuestas)
|
||||
//alert('Formulario enviado. Gracias por tu participación.')
|
||||
|
||||
// Aquí formateamos las respuestas
|
||||
// Convertir a formato p1, p2, p3_A_1, etc.
|
||||
const respuestaFormateada = this.formatearRespuestas(this.respuestas)
|
||||
console.log('Respuestas formateadas:', respuestaFormateada)
|
||||
|
||||
// this.sendAnswers(respuestaFormateada)
|
||||
|
||||
let data = {
|
||||
...respuestaFormateada,
|
||||
idServicio: localStorage.getItem('idServicio'),
|
||||
p1: 'respuesta1 - trabajando para que sea una string',
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
axios
|
||||
.post(
|
||||
`${process.env.api}/cuestionario_programa`,
|
||||
data //this.token
|
||||
)
|
||||
.then((res) => {
|
||||
.post(`${process.env.api}/cuestionario_programa`, data)
|
||||
.then(() => {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Success',
|
||||
message: 'Se enviaron los datos correctamente',
|
||||
@@ -437,14 +446,10 @@ export default {
|
||||
ariaRole: 'alertdialog',
|
||||
ariaModal: true,
|
||||
})
|
||||
|
||||
//this.reset()
|
||||
localStorage.removeItem('idCuestionarioAlumno')
|
||||
this.$router.push('/alumno')
|
||||
})
|
||||
.catch((error) => {
|
||||
// this.error(error.response.data.message)
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message:
|
||||
@@ -457,123 +462,54 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
formatearRespuestas(respuestas) {
|
||||
// Objeto final a devolver
|
||||
const resultado = {}
|
||||
|
||||
// Recorremos todas las claves de "respuestas"
|
||||
for (const key in respuestas) {
|
||||
// Verificamos si es un ID de tabla (numérico) o un ID de pregunta (string)
|
||||
const esTabla = !isNaN(Number(key)) // true si la clave se puede convertir a número
|
||||
|
||||
if (esTabla) {
|
||||
// 1) BUSCAMOS LA DEFINICIÓN DE LA TABLA
|
||||
const idTabla = parseInt(key, 10)
|
||||
const tablaDef = this.formulario.tablas.find(
|
||||
(t) => t.idTabla === idTabla
|
||||
)
|
||||
if (!tablaDef) {
|
||||
// Si no se encontró la tabla, continuamos
|
||||
continue
|
||||
}
|
||||
|
||||
// 2) OBTENEMOS EL NÚMERO DE PREGUNTA Y, OPCIONALMENTE, LA LETRA (A, B, C...)
|
||||
const numPregunta = tablaDef.numeroPregunta
|
||||
|
||||
// Si quieres “sacar” la letra (A, B, C…) de algo como "A. Habilidades sociales"
|
||||
// Se puede hacer un match sencillo al principio
|
||||
let subLetra = ''
|
||||
if (tablaDef.subPreguntaTabla) {
|
||||
// Ejemplo: "A. Habilidades personales"
|
||||
const coincidencia = tablaDef.subPreguntaTabla.match(/^([A-E])\./)
|
||||
if (coincidencia) {
|
||||
subLetra = coincidencia[1] // 'A', 'B', 'C', etc.
|
||||
}
|
||||
}
|
||||
|
||||
// 3) LUEGO RECORREMOS LAS RESPUESTAS DE LA TABLA (por cada idRenglon)
|
||||
const respuestasTabla = respuestas[key] // p.ej: { "1": "Deficiente", "2": "Básico", ... }
|
||||
for (const idRenglon in respuestasTabla) {
|
||||
const valor = respuestasTabla[idRenglon]
|
||||
|
||||
// Formamos la clave final.
|
||||
// Si hay subLetra, hacemos `p3_A_1`. Sino, solo `p3_1`.
|
||||
let clave = `p${numPregunta}_${idRenglon}`
|
||||
if (subLetra) {
|
||||
clave = `p${numPregunta}_${subLetra}_${idRenglon}`
|
||||
}
|
||||
|
||||
resultado[clave] = valor
|
||||
}
|
||||
} else {
|
||||
// NO ES UNA TABLA => ES UNA PREGUNTA NORMAL
|
||||
// Buscamos su definición para obtener el numeroPregunta
|
||||
const preguntaDef = this.formulario.preguntas.find(
|
||||
(p) => p.id === key
|
||||
)
|
||||
if (!preguntaDef) {
|
||||
// No se encontró la definición (caso raro)
|
||||
continue
|
||||
}
|
||||
|
||||
const numPregunta = preguntaDef.numeroPregunta
|
||||
|
||||
// Creamos algo como `p2`, `p5`, etc.
|
||||
const clave = `p${numPregunta}`
|
||||
resultado[clave] = respuestas[key]
|
||||
}
|
||||
}
|
||||
|
||||
return resultado
|
||||
},
|
||||
|
||||
// Valida que las preguntas y tablas visibles estén contestadas
|
||||
validateResponses() {
|
||||
// Validar preguntas
|
||||
for (const pregunta of this.formulario.preguntas) {
|
||||
if (!this.isItemVisible(pregunta)) continue
|
||||
|
||||
const respuesta = this.respuestas[pregunta.id]
|
||||
|
||||
// Verifica que no haya respuestas vacías
|
||||
if (respuesta === null || respuesta === '') {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, responde la pregunta: "${pregunta.texto}"`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
// Verifica que no esté vacía
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
if (!respuesta || respuesta.length === 0) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, selecciona al menos una opción en la pregunta ${pregunta.numeroPregunta}.`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if (respuesta === null || respuesta === '') {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, responde la pregunta ${pregunta.numeroPregunta}.`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Para selección múltiple, al menos un elemento debe estar seleccionado
|
||||
if (
|
||||
pregunta.tipo === 'seleccionMultiple' &&
|
||||
(!respuesta || respuesta.length === 0)
|
||||
) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, selecciona al menos una opción en: "${pregunta.texto}"`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// Validación adicional si la pregunta es de texto (evitar respuestas peligrosas)
|
||||
// Si es texto y excede 500 caracteres
|
||||
if (pregunta.tipo === 'texto' && respuesta.length > 500) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `La respuesta de la pregunta "${pregunta.texto}" es demasiado larga.`,
|
||||
message: `La respuesta de la pregunta ${pregunta.numeroPregunta} es demasiado larga (máx. 500 caracteres).`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica que todas las respuestas en las tablas estén completas
|
||||
// Validar tablas
|
||||
for (const tabla of this.formulario.tablas) {
|
||||
for (const renglon of tabla.renglones) {
|
||||
const respuesta = this.respuestas[tabla.idTabla]?.[renglon.idRenglon]
|
||||
|
||||
if (respuesta === null) {
|
||||
const respRenglon = this.respuestas[tabla.idTabla]?.[renglon.idRenglon]
|
||||
if (respRenglon === null) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, responde la pregunta en la tabla: "${tabla.preguntaTabla}" en la fila "${renglon.textoRenglon}"`,
|
||||
message: `Por favor, responde la tabla ${tabla.numeroPregunta}, fila "${renglon.textoRenglon}".`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
@@ -584,96 +520,82 @@ export default {
|
||||
return true
|
||||
},
|
||||
|
||||
updateRespuestas(id, valor) {
|
||||
this.$set(this.respuestas, id, valor)
|
||||
console.log('Radio seleccionado:', id, valor)
|
||||
// Convierte las respuestas en formato { p1: ..., p3_A_1: ..., etc. }
|
||||
formatearRespuestas(respuestas) {
|
||||
const resultado = {}
|
||||
|
||||
for (const key in respuestas) {
|
||||
const esTabla = !isNaN(Number(key))
|
||||
if (esTabla) {
|
||||
// Es una tabla
|
||||
const idTabla = parseInt(key, 10)
|
||||
const tablaDef = this.formulario.tablas.find(
|
||||
(t) => t.idTabla === idTabla
|
||||
)
|
||||
if (!tablaDef) continue
|
||||
|
||||
const numPregunta = tablaDef.numeroPregunta
|
||||
let subLetra = ''
|
||||
if (tablaDef.subPreguntaTabla) {
|
||||
const match = tablaDef.subPreguntaTabla.match(/^([A-E])\./)
|
||||
if (match) subLetra = match[1]
|
||||
}
|
||||
|
||||
const respuestasTabla = respuestas[key]
|
||||
for (const idRenglon in respuestasTabla) {
|
||||
const valor = respuestasTabla[idRenglon]
|
||||
let clave = `p${numPregunta}_${idRenglon}`
|
||||
if (subLetra) {
|
||||
clave = `p${numPregunta}_${subLetra}_${idRenglon}`
|
||||
}
|
||||
resultado[clave] = valor
|
||||
}
|
||||
} else {
|
||||
// Es una pregunta normal
|
||||
const preguntaDef = this.formulario.preguntas.find(
|
||||
(p) => p.id === key
|
||||
)
|
||||
if (!preguntaDef) continue
|
||||
|
||||
const numPregunta = preguntaDef.numeroPregunta
|
||||
const clave = `p${numPregunta}`
|
||||
resultado[clave] = respuestas[key]
|
||||
}
|
||||
}
|
||||
|
||||
return resultado
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- respuestas de cuestionario formulario2
|
||||
todas las preguntas se guardan correctamente
|
||||
{
|
||||
"p3_A_1": "Deficiente",
|
||||
"p3_A_2": "Deficiente",
|
||||
"p3_A_3": "Deficiente",
|
||||
"p3_A_4": "Deficiente",
|
||||
"p3_B_1": "Básico",
|
||||
"p3_B_2": "Básico",
|
||||
"p3_B_3": "Básico",
|
||||
"p3_B_4": "Básico",
|
||||
"p3_C_1": "Intermedio",
|
||||
"p3_C_2": "Intermedio",
|
||||
"p3_C_3": "Intermedio",
|
||||
"p3_C_4": "Intermedio",
|
||||
"p3_C_5": "Intermedio",
|
||||
"p3_D_1": "Destacado",
|
||||
"p3_D_2": "Destacado",
|
||||
"p3_D_3": "Destacado",
|
||||
"p3_D_4": "Destacado",
|
||||
"p3_D_5": "Destacado",
|
||||
"p3_E_1": "Deficiente",
|
||||
"p1": "respuesta1",
|
||||
"p2": "Excelente",
|
||||
"p4": "respuesta4",
|
||||
"p5": "Sí",
|
||||
"p6": "respuesta 6"
|
||||
} -->
|
||||
<style scoped>
|
||||
/* Notificación flotante en parte inferior derecha, sin botón de cerrar */
|
||||
.notification-floating {
|
||||
position: fixed !important;
|
||||
bottom: 2rem;
|
||||
right: 2rem;
|
||||
z-index: 9999;
|
||||
max-width: 350px;
|
||||
width: auto; /* o 90% si prefieres */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
<!-- respuestas de cuestionario formulario alumno
|
||||
|
||||
|
||||
{
|
||||
"p12_A_1": "Deficiente",
|
||||
"p12_A_2": "Deficiente",
|
||||
"p12_A_3": "Deficiente",
|
||||
"p12_A_4": "Deficiente",
|
||||
"p12_B_1": "Básico",
|
||||
"p12_B_2": "Básico",
|
||||
"p12_B_3": "Básico",
|
||||
"p12_B_4": "Básico",
|
||||
"p12_C_1": "Intermedio",
|
||||
"p12_C_2": "Intermedio",
|
||||
"p12_C_3": "Intermedio",
|
||||
"p12_C_4": "Intermedio",
|
||||
"p10_1": "si",
|
||||
"p10_2": "si",
|
||||
"p10_3": "si",
|
||||
"p11_1": "Nunca",
|
||||
"p11_2": "Rara vez",
|
||||
"p11_3": "Algunas veces",
|
||||
"p11_4": "Siempre",
|
||||
"p17_1": "si",
|
||||
"p17_2": "no",
|
||||
"p17_3": "si",
|
||||
"p3_1": "si",
|
||||
"p3_2": "si",
|
||||
"p3_3": "si",
|
||||
"p3_4": "si",
|
||||
"p12_D_1": "Destacado",
|
||||
"p12_D_2": "Destacado",
|
||||
"p12_D_3": "Destacado",
|
||||
"p12_D_4": "Destacado",
|
||||
"p12_D_5": "Destacado",
|
||||
"p1": [
|
||||
"Dependencia de la UNAM",
|
||||
"Asesoría académica",
|
||||
"Oportunidad de desarrollo de tesis"
|
||||
],
|
||||
"p2": "Deficiente",
|
||||
"p4": "No",
|
||||
"p5": "respuesta5",
|
||||
"p6": "Sí",
|
||||
"p7": "Sí",
|
||||
"p8": "respuesta8",
|
||||
"p9": "Sí",
|
||||
"p13": "Responsable directo del programa",
|
||||
"p14": "Se te otorgó de acuerdo a lo establecido",
|
||||
"p15": "Sí",
|
||||
"p16": "respuesta 16",
|
||||
"p18": "respuesta18"
|
||||
/* Ajustes en pantallas pequeñas (ej. < 480px) */
|
||||
@media (max-width: 480px) {
|
||||
.notification-floating {
|
||||
right: 1rem;
|
||||
left: 1rem; /* Opcional: para centrar la notificación */
|
||||
bottom: 1rem;
|
||||
max-width: none; /* Para que no se limite a 350px */
|
||||
width: auto; /* O 90%, como prefieras */
|
||||
}
|
||||
|
||||
|
||||
-->
|
||||
}
|
||||
|
||||
|
||||
.table-responsive {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,679 @@
|
||||
<template>
|
||||
<div class="container mt-5">
|
||||
<!--
|
||||
<h1 class="text-center mb-4">{{ formulario.titulo }}</h1>
|
||||
<p class="text-center">{{ formulario.descripcion }}</p> -->
|
||||
|
||||
<div>
|
||||
<div
|
||||
v-for="(item, index) in sortedItems"
|
||||
:key="item.id || item.idTabla"
|
||||
class="mb-6"
|
||||
>
|
||||
<div v-if="item.tipo" class="mt-6">
|
||||
<label :for="item.id" class="form-label"
|
||||
>{{ item.numeroPregunta }}. {{ item.texto }}</label
|
||||
>
|
||||
<div v-if="item.tipo === 'seleccionUnica'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<b-radio
|
||||
v-model="respuestas[item.id]"
|
||||
:id="item.id"
|
||||
:native-value="opcion"
|
||||
type="is-info"
|
||||
>
|
||||
{{ opcion }}
|
||||
</b-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.tipo === 'seleccionMultiple'">
|
||||
<div v-for="opcion in item.opciones" :key="opcion" class="SINO">
|
||||
<input
|
||||
class="checkb"
|
||||
type="checkbox"
|
||||
:value="opcion"
|
||||
v-model="respuestas[item.id]"
|
||||
/>
|
||||
|
||||
{{ opcion }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.tipo === 'texto'">
|
||||
<b-input
|
||||
:id="item.id"
|
||||
v-model="respuestas[item.id]"
|
||||
placeholder="Escribe tu respuesta aquí"
|
||||
></b-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- <h3 class="mb-3">{{ item.numeroPregunta }}. {{ item.preguntaTabla }}</h3>
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">{{ item.subPreguntaTabla }}</h5>
|
||||
-->
|
||||
|
||||
<template
|
||||
v-if="
|
||||
index === 0 ||
|
||||
item.numeroPregunta !== sortedItems[index - 1].numeroPregunta
|
||||
"
|
||||
>
|
||||
<h3 class="mb-3">
|
||||
{{ item.numeroPregunta }}. {{ item.preguntaTabla }}
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<!-- Subtítulo (h5) siempre que exista -->
|
||||
<h5 v-if="item.subPreguntaTabla" class="mb-3">
|
||||
{{ item.subPreguntaTabla }}
|
||||
</h5>
|
||||
|
||||
<table class="table table-bordered text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th v-for="opcion in item.renglones[0].opciones" :key="opcion">
|
||||
{{ opcion }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="renglon in item.renglones" :key="renglon.idRenglon">
|
||||
<td>{{ renglon.textoRenglon }}</td>
|
||||
<td v-for="opcion in renglon.opciones" :key="opcion">
|
||||
<input
|
||||
type="radio"
|
||||
:name="`tabla-${item.idTabla}-renglon-${renglon.idRenglon}`"
|
||||
:value="opcion"
|
||||
v-model="respuestas[item.idTabla][renglon.idRenglon]"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-6 mb-6">
|
||||
<b-field class="centro">
|
||||
<button
|
||||
class="button is-success is-medium"
|
||||
@click="() => {submitForm()}"
|
||||
:disabled="!isFormComplete"
|
||||
>
|
||||
Enviar
|
||||
</button>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Buefy from 'buefy'
|
||||
import 'buefy/dist/buefy.css'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
respuestas: {}, // Inicialización para almacenar las respuestas
|
||||
|
||||
formulario: {
|
||||
titulo:
|
||||
'2025 Evaluación de la institución receptora de servicio social',
|
||||
descripcion: `Estimado(a) responsable de programa de servicio social:
|
||||
Te solicitamos llenar cuidadosamente los campos solicitados a continuación para poder
|
||||
validar el término del servicio social de nuestro alumno(a).
|
||||
|
||||
|
||||
Los datos están sujetos al aviso de privacidad integral que se puede consultar en el sitio web: www.acatlan.unam.mx/normatividad`,
|
||||
|
||||
preguntas: [
|
||||
{
|
||||
numeroPregunta: 1,
|
||||
id: 'actividadesUniversitario',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'Mencione las principales actividades que realizó el/la universitario(a) en su programa de servicio social',
|
||||
},
|
||||
{
|
||||
numeroPregunta: 2,
|
||||
id: 'calificacionGeneral',
|
||||
tipo: 'seleccionUnica',
|
||||
texto:
|
||||
'Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
opciones: ['Excelente', 'Bueno', 'Regular', 'Deficiente'],
|
||||
},
|
||||
{
|
||||
numeroPregunta: 4,
|
||||
id: 'cursosComplementarios',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'¿Qué cursos considera que complementarían la formación de nuestros egresados?',
|
||||
},
|
||||
{
|
||||
numeroPregunta: 5,
|
||||
id: 'contratariaFuturo',
|
||||
tipo: 'seleccionUnica',
|
||||
texto: '¿Considera contratar en un futuro al universitario(a)?',
|
||||
opciones: ['Sí', 'No'],
|
||||
},
|
||||
{
|
||||
numeroPregunta: 6,
|
||||
id: 'porqueNoContrataria',
|
||||
tipo: 'texto',
|
||||
texto:
|
||||
'Si su respuesta a la pregunta anterior fue NO, comente ¿por qué?',
|
||||
condicional: {
|
||||
preguntaId: 'contratariaFuturo',
|
||||
valor: 'No',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
tablas: [
|
||||
// ----- PREGUNTA 3, dividida en sub-secciones A, B, C, D, E ------
|
||||
{
|
||||
idTabla: 301,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'Haciendo una evaluación general, ¿Cómo Califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'A. Habilidades personales',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Puntualidad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Eficiencia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Organizado',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Eficacia',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
idTabla: 302,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'3. Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'B. Habilidades profesionales',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Disposición',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Proactivo/anticipación',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Propositivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Resolutivo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
idTabla: 303,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'3. Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'C. Habilidades sociales',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Empatía',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Trabajo en equipo',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Comunicación asertiva',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Receptividad',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Tolerancia a la frustración',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
idTabla: 304,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'3. Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'D. Conocimientos',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Conocimientos teóricos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 2,
|
||||
textoRenglon: 'Conocimientos metodológicos',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 3,
|
||||
textoRenglon: 'Pensamiento crítico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 4,
|
||||
textoRenglon: 'Formación académica general',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
{
|
||||
idRenglon: 5,
|
||||
textoRenglon: 'Uso tecnológico',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
},
|
||||
/* {
|
||||
idTabla: 305,
|
||||
numeroPregunta: 3,
|
||||
preguntaTabla:
|
||||
'3. Haciendo una evaluación general, ¿Cómo califica el desempeño del universitario(a)?',
|
||||
subPreguntaTabla: 'E. Otro',
|
||||
renglones: [
|
||||
{
|
||||
idRenglon: 1,
|
||||
textoRenglon: 'Otro',
|
||||
opciones: ['Deficiente', 'Básico', 'Intermedio', 'Destacado'],
|
||||
},
|
||||
],
|
||||
}, */
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
/* created() {
|
||||
// Inicializa las respuestas vacías para cada pregunta
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (pregunta.tipo === 'evaluacion') {
|
||||
this.respuestas[pregunta.id] = {}
|
||||
pregunta.categorias.forEach((categoria) => {
|
||||
categoria.items.forEach((item) => {
|
||||
this.respuestas[pregunta.id][item] = ''
|
||||
})
|
||||
})
|
||||
} else if (
|
||||
pregunta.tipo === 'checkbox' ||
|
||||
pregunta.tipo === 'seleccionMultiple'
|
||||
) {
|
||||
this.respuestas[pregunta.id] = []
|
||||
} else {
|
||||
this.respuestas[pregunta.id] = ''
|
||||
}
|
||||
})
|
||||
|
||||
// Inicializa respuestas para cada tabla
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
this.$set(this.respuestas, tabla.idTabla, {}); // Asegura que exista respuestas[tabla.idTabla]
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
this.$set(this.respuestas[tabla.idTabla], renglon.idRenglon, null); // Asegura que exista respuestas[tabla.idTabla][renglon.idRenglon]
|
||||
});
|
||||
});
|
||||
}, */
|
||||
|
||||
created() {
|
||||
this.formulario.preguntas.forEach((pregunta) => {
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
this.$set(this.respuestas, pregunta.id, []) // Inicializar correctamente selección múltiple
|
||||
} else {
|
||||
this.$set(this.respuestas, pregunta.id, '') // Otras preguntas como texto o selección única
|
||||
}
|
||||
})
|
||||
|
||||
// Inicializa respuestas para cada tabla
|
||||
this.formulario.tablas.forEach((tabla) => {
|
||||
this.$set(this.respuestas, tabla.idTabla, {})
|
||||
tabla.renglones.forEach((renglon) => {
|
||||
this.$set(this.respuestas[tabla.idTabla], renglon.idRenglon, null)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
computed: {
|
||||
sortedItems() {
|
||||
const items = [...this.formulario.preguntas, ...this.formulario.tablas]
|
||||
return items.sort((a, b) => {
|
||||
if (a.numeroPregunta === b.numeroPregunta) {
|
||||
return (a.idTabla || 0) - (b.idTabla || 0)
|
||||
}
|
||||
return a.numeroPregunta - b.numeroPregunta
|
||||
})
|
||||
},
|
||||
|
||||
isFormComplete() {
|
||||
// Verifica todas las preguntas individuales
|
||||
const allQuestionsAnswered = this.formulario.preguntas.every(
|
||||
(pregunta) => {
|
||||
const respuesta = this.respuestas[pregunta.id]
|
||||
if (pregunta.tipo === 'seleccionMultiple') {
|
||||
return respuesta && respuesta.length > 0 // Debe tener al menos una opción seleccionada
|
||||
}
|
||||
return respuesta !== null && respuesta !== '' // No debe ser null ni vacío
|
||||
}
|
||||
)
|
||||
|
||||
// Verifica todas las respuestas de la tabla
|
||||
const allTablesAnswered = this.formulario.tablas.every((tabla) => {
|
||||
return tabla.renglones.every((renglon) => {
|
||||
return (
|
||||
this.respuestas[tabla.idTabla] &&
|
||||
this.respuestas[tabla.idTabla][renglon.idRenglon] !== null
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
return allQuestionsAnswered && allTablesAnswered
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
if (!this.validateResponses()) {
|
||||
return // Detiene el envío si la validación falla
|
||||
}
|
||||
|
||||
console.log('Respuestas enviadas:', this.respuestas)
|
||||
//alert('Formulario enviado. Gracias por tu participación.')
|
||||
|
||||
// Aquí formateamos las respuestas
|
||||
const respuestaFormateada = this.formatearRespuestas(this.respuestas)
|
||||
console.log('Respuestas formateadas:', respuestaFormateada)
|
||||
|
||||
// this.sendAnswers(respuestaFormateada)
|
||||
|
||||
let data = {
|
||||
...respuestaFormateada,
|
||||
idServicio: localStorage.getItem('idServicio'),
|
||||
p1: 'respuesta1 - trabajando para que sea una string',
|
||||
}
|
||||
|
||||
axios
|
||||
.post(
|
||||
`${process.env.api}/cuestionario_programa`,
|
||||
data //this.token
|
||||
)
|
||||
.then((res) => {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Success',
|
||||
message: 'Se enviaron los datos correctamente',
|
||||
type: 'is-success',
|
||||
hasIcon: true,
|
||||
icon: 'checkbox-marked-circle',
|
||||
ariaRole: 'alertdialog',
|
||||
ariaModal: true,
|
||||
})
|
||||
|
||||
//this.reset()
|
||||
localStorage.removeItem('idCuestionarioAlumno')
|
||||
this.$router.push('/alumno')
|
||||
})
|
||||
.catch((error) => {
|
||||
// this.error(error.response.data.message)
|
||||
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message:
|
||||
error.response?.data?.message || 'Error al enviar el formulario',
|
||||
type: 'is-danger',
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
formatearRespuestas(respuestas) {
|
||||
// Objeto final a devolver
|
||||
const resultado = {}
|
||||
|
||||
// Recorremos todas las claves de "respuestas"
|
||||
for (const key in respuestas) {
|
||||
// Verificamos si es un ID de tabla (numérico) o un ID de pregunta (string)
|
||||
const esTabla = !isNaN(Number(key)) // true si la clave se puede convertir a número
|
||||
|
||||
if (esTabla) {
|
||||
// 1) BUSCAMOS LA DEFINICIÓN DE LA TABLA
|
||||
const idTabla = parseInt(key, 10)
|
||||
const tablaDef = this.formulario.tablas.find(
|
||||
(t) => t.idTabla === idTabla
|
||||
)
|
||||
if (!tablaDef) {
|
||||
// Si no se encontró la tabla, continuamos
|
||||
continue
|
||||
}
|
||||
|
||||
// 2) OBTENEMOS EL NÚMERO DE PREGUNTA Y, OPCIONALMENTE, LA LETRA (A, B, C...)
|
||||
const numPregunta = tablaDef.numeroPregunta
|
||||
|
||||
// Si quieres “sacar” la letra (A, B, C…) de algo como "A. Habilidades sociales"
|
||||
// Se puede hacer un match sencillo al principio
|
||||
let subLetra = ''
|
||||
if (tablaDef.subPreguntaTabla) {
|
||||
// Ejemplo: "A. Habilidades personales"
|
||||
const coincidencia = tablaDef.subPreguntaTabla.match(/^([A-E])\./)
|
||||
if (coincidencia) {
|
||||
subLetra = coincidencia[1] // 'A', 'B', 'C', etc.
|
||||
}
|
||||
}
|
||||
|
||||
// 3) LUEGO RECORREMOS LAS RESPUESTAS DE LA TABLA (por cada idRenglon)
|
||||
const respuestasTabla = respuestas[key] // p.ej: { "1": "Deficiente", "2": "Básico", ... }
|
||||
for (const idRenglon in respuestasTabla) {
|
||||
const valor = respuestasTabla[idRenglon]
|
||||
|
||||
// Formamos la clave final.
|
||||
// Si hay subLetra, hacemos `p3_A_1`. Sino, solo `p3_1`.
|
||||
let clave = `p${numPregunta}_${idRenglon}`
|
||||
if (subLetra) {
|
||||
clave = `p${numPregunta}_${subLetra}_${idRenglon}`
|
||||
}
|
||||
|
||||
resultado[clave] = valor
|
||||
}
|
||||
} else {
|
||||
// NO ES UNA TABLA => ES UNA PREGUNTA NORMAL
|
||||
// Buscamos su definición para obtener el numeroPregunta
|
||||
const preguntaDef = this.formulario.preguntas.find(
|
||||
(p) => p.id === key
|
||||
)
|
||||
if (!preguntaDef) {
|
||||
// No se encontró la definición (caso raro)
|
||||
continue
|
||||
}
|
||||
|
||||
const numPregunta = preguntaDef.numeroPregunta
|
||||
|
||||
// Creamos algo como `p2`, `p5`, etc.
|
||||
const clave = `p${numPregunta}`
|
||||
resultado[clave] = respuestas[key]
|
||||
}
|
||||
}
|
||||
|
||||
return resultado
|
||||
},
|
||||
|
||||
validateResponses() {
|
||||
for (const pregunta of this.formulario.preguntas) {
|
||||
const respuesta = this.respuestas[pregunta.id]
|
||||
|
||||
// Verifica que no haya respuestas vacías
|
||||
if (respuesta === null || respuesta === '') {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, responde la pregunta: "${pregunta.texto}"`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// Para selección múltiple, al menos un elemento debe estar seleccionado
|
||||
if (
|
||||
pregunta.tipo === 'seleccionMultiple' &&
|
||||
(!respuesta || respuesta.length === 0)
|
||||
) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, selecciona al menos una opción en: "${pregunta.texto}"`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// Validación adicional si la pregunta es de texto (evitar respuestas peligrosas)
|
||||
if (pregunta.tipo === 'texto' && respuesta.length > 500) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `La respuesta de la pregunta "${pregunta.texto}" es demasiado larga.`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica que todas las respuestas en las tablas estén completas
|
||||
for (const tabla of this.formulario.tablas) {
|
||||
for (const renglon of tabla.renglones) {
|
||||
const respuesta = this.respuestas[tabla.idTabla]?.[renglon.idRenglon]
|
||||
|
||||
if (respuesta === null) {
|
||||
this.$buefy.dialog.alert({
|
||||
title: 'Error',
|
||||
message: `Por favor, responde la pregunta en la tabla: "${tabla.preguntaTabla}" en la fila "${renglon.textoRenglon}"`,
|
||||
type: 'is-danger',
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
updateRespuestas(id, valor) {
|
||||
this.$set(this.respuestas, id, valor)
|
||||
console.log('Radio seleccionado:', id, valor)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- respuestas de cuestionario formulario2
|
||||
todas las preguntas se guardan correctamente
|
||||
{
|
||||
"p3_A_1": "Deficiente",
|
||||
"p3_A_2": "Deficiente",
|
||||
"p3_A_3": "Deficiente",
|
||||
"p3_A_4": "Deficiente",
|
||||
"p3_B_1": "Básico",
|
||||
"p3_B_2": "Básico",
|
||||
"p3_B_3": "Básico",
|
||||
"p3_B_4": "Básico",
|
||||
"p3_C_1": "Intermedio",
|
||||
"p3_C_2": "Intermedio",
|
||||
"p3_C_3": "Intermedio",
|
||||
"p3_C_4": "Intermedio",
|
||||
"p3_C_5": "Intermedio",
|
||||
"p3_D_1": "Destacado",
|
||||
"p3_D_2": "Destacado",
|
||||
"p3_D_3": "Destacado",
|
||||
"p3_D_4": "Destacado",
|
||||
"p3_D_5": "Destacado",
|
||||
"p3_E_1": "Deficiente",
|
||||
"p1": "respuesta1",
|
||||
"p2": "Excelente",
|
||||
"p4": "respuesta4",
|
||||
"p5": "Sí",
|
||||
"p6": "respuesta 6"
|
||||
} -->
|
||||
|
||||
<!-- respuestas de cuestionario formulario alumno
|
||||
|
||||
|
||||
{
|
||||
"p12_A_1": "Deficiente",
|
||||
"p12_A_2": "Deficiente",
|
||||
"p12_A_3": "Deficiente",
|
||||
"p12_A_4": "Deficiente",
|
||||
"p12_B_1": "Básico",
|
||||
"p12_B_2": "Básico",
|
||||
"p12_B_3": "Básico",
|
||||
"p12_B_4": "Básico",
|
||||
"p12_C_1": "Intermedio",
|
||||
"p12_C_2": "Intermedio",
|
||||
"p12_C_3": "Intermedio",
|
||||
"p12_C_4": "Intermedio",
|
||||
"p10_1": "si",
|
||||
"p10_2": "si",
|
||||
"p10_3": "si",
|
||||
"p11_1": "Nunca",
|
||||
"p11_2": "Rara vez",
|
||||
"p11_3": "Algunas veces",
|
||||
"p11_4": "Siempre",
|
||||
"p17_1": "si",
|
||||
"p17_2": "no",
|
||||
"p17_3": "si",
|
||||
"p3_1": "si",
|
||||
"p3_2": "si",
|
||||
"p3_3": "si",
|
||||
"p3_4": "si",
|
||||
"p12_D_1": "Destacado",
|
||||
"p12_D_2": "Destacado",
|
||||
"p12_D_3": "Destacado",
|
||||
"p12_D_4": "Destacado",
|
||||
"p12_D_5": "Destacado",
|
||||
"p1": [
|
||||
"Dependencia de la UNAM",
|
||||
"Asesoría académica",
|
||||
"Oportunidad de desarrollo de tesis"
|
||||
],
|
||||
"p2": "Deficiente",
|
||||
"p4": "No",
|
||||
"p5": "respuesta5",
|
||||
"p6": "Sí",
|
||||
"p7": "Sí",
|
||||
"p8": "respuesta8",
|
||||
"p9": "Sí",
|
||||
"p13": "Responsable directo del programa",
|
||||
"p14": "Se te otorgó de acuerdo a lo establecido",
|
||||
"p15": "Sí",
|
||||
"p16": "respuesta 16",
|
||||
"p18": "respuesta18"
|
||||
}
|
||||
|
||||
|
||||
-->
|
||||
Reference in New Issue
Block a user