646 lines
22 KiB
HTML

<script src="js/QuizManager.min.js"></script>
<style>
.fake {
background-image: url("img/actividad/fondo-inicio.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
}
.fakedesarrollo {
background-image: url("img/actividad/fondo-desarrollo.jpg");
}
.fakecierre {
background-image: url("img/actividad/fondo-cierre.jpg");
}
.page-activity {
display: none;
}
#inicio {
display: flex;
}
#quiz-container {
margin-top: 20px;
}
.results {
text-align: center;
}
.results h2 {
margin-bottom: 20px;
}
.swal2-popup.swal2-show.pop-retro {
background-color: transparent !important;
background: transparent !important;
border-radius: 0;
border: 0;
}
.custom-card {
background: transparent;
border-top: solid 3px #ffff;
border-radius: 0px;
border-bottom: solid 3px #ffff;
border-left: 0px;
border-right: 0px;
}
#desarrollo {
min-height: 100%;
display: flex;
flex-direction: column;
display: none;
}
.trophy img {
max-width: 85%;
height: auto;
}
.asesor {
margin-top: 0;
max-width: 70px;
}
.pregunta {
color: var(--bs-primary);
text-align: center;
}
/* ============================================================================================================================
== PINCHED SPEECH BUBBLE (more CSS3)
** ============================================================================================================================ */
.pinched {
position: relative;
padding: 15px;
margin: 50px 0 3em;
text-align: center;
color: #fff;
background: #333;
/* css3 */
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
/* creates a rectangle of the colour wanted for the pointy bit */
.pinched:before {
content: "";
position: absolute;
top: -20px;
left: 50%;
width: 100px;
height: 20px;
margin: 0 0 0 -50px;
background: #333;
}
.bubble {
position: relative;
background: var(--bs-coral);
color: #FFFFFF;
box-shadow: 5px 7px 7px -1px rgb(239 186 146 / 44%);
text-align: center;
border-radius: 15px;
padding: 1em;
}
.bubble:after {
content: '';
position: absolute;
display: block;
width: 0;
z-index: 1;
border-style: solid;
border-color: var(--bs-coral) transparent;
border-width: 0 20px 20px;
top: -20px;
left: 50%;
margin-left: -20px;
}
.bg-responsive {
background: #e3e6e7;
padding: 15px;
border-radius: 10px;
}
/* En pantallas md (>=768px) mostrar el triángulo apuntando hacia la izquierda */
@media (min-width: 768px) {
.bubble:after {
/* Hacer el triángulo hacia la izquierda: color en el borde derecho */
border-color: transparent var(--bs-coral) transparent transparent;
/* top right bottom left */
border-width: 20px 20px 20px 0;
/* Colocar el triángulo centrado verticalmente y fuera a la izquierda */
top: 50%;
left: -18px;
margin-left: 0;
margin-top: -20px;
}
}
.glass {
/* From https://css.glass */
background: rgba(255, 255, 255, 0.8);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(24, 53, 104, 0.3);
}
.option-btn {
transition: all .3s ease-in-out;
color: var(--blue-2);
}
.option-btn:hover {
transform: scale(.9);
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset !important;
border: 5px solid #945b9d !important;
}
.bannerend {
width: 100%;
height: auto;
object-fit: cover;
aspect-ratio: 16/5;
max-height: 45dvh;
}
.grid-cierre {
position: relative;
width: 100%;
flex: 1;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 60% auto;
justify-content: center;
align-items: center;
}
.bg-pass {
background-image: url(img/actividad/bannerbien.jpg);
background-repeat: no-repeat;
background-position: 50% 100%;
background-size: cover;
}
.bg-fail {
background-image: url(img/actividad/bannermal.jpg);
background-repeat: no-repeat;
background-position: 50% 100%;
background-size: cover;
}
@media(min-width: 768px) {
.trophy {
max-width: 45px;
}
}
@media(min-width: 991px) {
.bg-pass {
background-position: 100% 100%;
}
.bg-fail {
background-position: 100% 100%;
}
}
@media (min-width: 1200px) {
.asesor {
margin-top: -90px;
max-width: 200px;
}
.bannerend {
object-position: bottom center;
max-height: 65dvh;
}
.img-w-perso {
max-width: 65%;
}
.grid-cierre {
grid-template-rows: 458px auto;
}
.bg-pass {
background-image: none;
}
.bg-fail {
background-image: none;
}
}
@media(min-width: 1400px) {
.m-h {
height: 100%;
}
}
</style>
<div class="page-sco full-height page-activity" id="inicio">
<div class="container-xxl">
<div class="row justify-content-center align-items-center">
<div class="col-12">
<div class="row justify-content-center align-items-center">
<div class="col-6 col-sm-6 col-md-6 col-xl-4 text-center mt-md-0 mt-4">
<img src="img/actividad/avatar-inicio.png" class="img-fluid floating">
</div>
<div class="col-12 col-sm-12 col-md-6 col-xl-6">
<div class="card custom-card animate__animated animate__fadeInRightBig p-md-4 p-2">
<div class="card-body text-center text-white">
<h1 class="text-coral fw-bold">
¿Quién está diciendo la verdad?
</h1>
En esta actividad podrás practicar cómo responder <span class="fw-bold text-gray-1">objeciones</span> y
elegir quién da la respuesta correcta.<br><br>Prepárate para afinar tu criterio y tomar la mejor
decisión.
</div>
</div>
<div class="w-100 text-center animate__animated animate__slideInDown mt-3">
<div
class="btn btn-begin text-white fw-bold py-1 animate__animated animate__pulse animate__infinite disabled"
id="btn-comenzar">
Comenzar
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="page-sco page-activity full-height py-2 pt-md-3" id="desarrollo" style="display: none;">
<div class="container-xl">
<div class="row align-items-center">
<div class="col-12">
<div class="row align-items-center justify-content-center">
<div class="col-12 text-center">
<h2 class="fw-medium text-secondary">¿Quién está diciendo la verdad?</h2>
</div>
<div class="col-12 col-md-8 ins_act">
<div class="text-center w-100 d-inline-block p-md-3 p-1 bg-coral rounded-3 shadow" style="color: #0e1c62;">
<strong style="color: #0e1c62;">Instrucciones: </strong>Lee la respuesta de los dos representantes sobre
una objeción. Analiza
cuidadosamente sus argumentos y elige quién tiene la razón.
</div>
</div>
<div class="col-12 col-md-8 col-lg-6">
<div class="d-flex gap-3 justify-content-center mt-3">
<div class="trophy text-center"> <img src="img/actividad/tocheck.png" alt=""> </div>
<div class="trophy text-center"> <img src="img/actividad/tocheck.png" alt=""> </div>
<div class="trophy text-center"> <img src="img/actividad/tocheck.png" alt=""> </div>
<div class="trophy text-center"> <img src="img/actividad/tocheck.png" alt=""> </div>
<div class="trophy text-center"> <img src="img/actividad/tocheck.png" alt=""> </div>
</div>
</div>
<div class="col-12 col-md-9 col-lg-8 col-xl-10 actividad_show" style="display: none;">
<div id="quiz-container" class="mt-3 w-100">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="page-sco page-activity full-height" id="cierre" style="display: none;">
<div class="container">
<div class="row justify-content-center align-items-center">
<div class="col-7 col-md-5 col-xl-5 text-center">
<div class="passed w-100 text-center" style="display: none;">
<img src="img/actividad/bannerbien.png" class="img-fluid ">
</div>
<div class="failed w-100 text-center" style="display: none;">
<img src="img/actividad/bannermal.png" class="img-fluid ">
</div>
</div>
<div class="col-7 col-md-7 col-xl-7">
<div class="container">
<div class="row align-items-center justify-content-center pt-2">
<div class="col-12 col-md-8">
<div class="row">
<div class="col-12 text-center animate__animated animate__fadeInLeft passed" style="display: none;">
<h1 class="fw-bold text-secondary">¡Excelente trabajo!</h1>
<p>Dominas las principales objeciones y sabes cómo responderlas con claridad y seguridad.</p>
</div>
<div class="col-12 text-center animate__animated animate__fadeInLeft failed" style="display: none;">
<h1 class="fw-bold text-secondary">¡Tú puedes lograrlo!</h1>
<p>Repasa el curso para dominar las objeciones más frecuentes y vuelve a intentarlo.</p>
<div class="w-100 text-center">
<div
class="btn btn-begin text-white fw-bold py-1 animate__animated animate__pulse animate__infinite"
onclick="CourseNav.reload()">
Volver a intentar
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(async function () {
// Configuración inicial
$(".page-sco").addClass("fake");
$("#loader-course360").show();
// Configuración de las páginas
const pageActivity = ".page-activity";
const pageStart = "#inicio";
const pageDevelopment = "#desarrollo";
const pageSummary = "#cierre";
const audios = {
"inicio": CourseNav.createSound('audio/audiom20.mp3'),
"instrucciones": CourseNav.createSound('audio/audiom21.mp3'),
"correcto": CourseNav.createSound('audio/audiom22.mp3'),
"incorrecto": CourseNav.createSound('audio/audiom23.mp3'),
"fc": CourseNav.createSound('audio/feedback-correct.mp3'),
"fi": CourseNav.createSound('audio/feedback-incorrect.mp3')
}
audios.inicio.on("end", function () {
$("#btn-comenzar").removeClass("disabled");
});
audios.instrucciones.on("end", function () {
$(".btn-open-question").removeClass("disabled grayscale");
$('.ins_act').hide();
$('.actividad_show').show();
});
// Crear instancia de QuizManager
const quizManager = new QuizManager({
excelFileUrl: "manejoDeObjeciones.xlsx",
mandatoryFields: {
question: "pregunta",
correctOption: "opcion_c",
correctFeedback: "retroalimentacion_correcta",
incorrectFeedback: "retroalimentacion_incorrecta",
},
optionPrefix: "opcion", // Prefijo para las opciones
randomizeQuestions: true, // Habilitar preguntas aleatorias
randomizeOptions: true, // Habilitar opciones aleatorias
passingScore: 80, // Puntaje mínimo aprobatorio
defaultWeight: 1, // Ponderación por defecto
maxAttempts: Infinity, // Intentos máximos por defecto
maxQuestions: 5, // Obtener solo 5 preguntas
specialOptions: ["Ninguna de las anteriores", "Todas las anteriores"], // Textos especiales
});
// Configurar intentos iniciales con validación desde el LMS
const attempt = !isNaN(CourseNav.getLessonLocation()) ? Number(CourseNav.getLessonLocation()) : 0;
console.log("Intento actual obtenido del LMS:", attempt);
quizManager.setAttempts(attempt);
if (attempt < 1) {
CourseNav.audioController.stopAllSoundsAndPlay(audios.inicio);
} else {
$("#btn-comenzar").removeClass("disabled");
}
// Cargar las preguntas al inicio
await loadAndStartQuiz();
// Manejar clic en el botón "Comenzar"
$("#btn-comenzar").click(function () {
const maxAttempts = quizManager.config.maxAttempts || Infinity; // Obtener intentos máximos
const attemptsMade = quizManager.getAttempts(); // Intentos realizados
if (!quizManager.hasReachedMaxAttempts()) {
$(pageActivity).hide();
$(pageDevelopment).addClass('d-flex');
// Incrementar los intentos y guardar en el LMS
quizManager.incrementAttempts();
CourseNav.setLessonLocation(quizManager.getAttempts());
$(".page-sco").addClass('fakedesarrollo');
CourseNav.audioController.stopAllSoundsAndPlay(audios.instrucciones);
// Renderizar la primera pregunta
renderQuestion("#quiz-container", false);
} else {
// Mostrar mensaje si se alcanzó el límite de intentos
const maxAttemptsTxt = maxAttempts === Infinity ? "&infin;" : maxAttempts;
Swal.fire({
icon: "error",
title: "¡Límite de intentos alcanzado!",
html: `
<p>Has alcanzado el límite de intentos.</p>
<p><strong>Intentos realizados:</strong> ${attemptsMade}</p>
<p><strong>Intentos permitidos:</strong> ${maxAttemptsTxt}</p>
`,
confirmButtonText: "Aceptar",
}).then(() => {
CourseNav.resetCourse();
});
}
});
/**
* Carga las preguntas desde el archivo Excel y muestra el inicio.
*/
async function loadAndStartQuiz() {
try {
await quizManager.loadQuestionsFromExcel();
console.log("Preguntas cargadas exitosamente.");
console.table(quizManager.getAllRenderData());
$("#loader-course360").hide();
} catch (error) {
console.error("Error al cargar las preguntas:", error);
$("#loader-course360").hide(); // Asegurarse de ocultar el loader en caso de error
}
}
/**
* Renderiza la pregunta actual en un contenedor específico o en un Swal.
* @param {string} containerSelector - Selector del contenedor donde se renderizará la pregunta.
* @param {boolean} [useSwal=false] - Si es `true`, muestra la pregunta en un Swal en lugar del contenedor.
*/
function renderQuestion(containerSelector, useSwal = false) {
const questionData = quizManager.getRenderData();
if (questionData) {
const questionHtml = `<div class="row justify-content-center align-items-center">
<div class="col-12 text-center mb-3">
<div class="row align-items-center justify-content-center">
<div class="col-4 col-md-3 text-center mb-3 mb-md-0"><img src="img/actividad/medico.png" class="img-fluid animate__animated animate__flipInY" alt=""></div>
<div class="col-12 col-md-9 text-center"><div class="w-100 pregunta bubble">${questionData.text}</div></div>
</div>
</div>
<div class="col-12 col-xl-5 animate__animated animate__fadeInLeft">
<div class="card glass border-0 rounded-15 shadow option-btn cursor p-1 p-md-3" data-correct="${questionData.options[0].isCorrect}">
<div class="card-body text-center d-inline-flex flex-xl-column flex-row justify-content-center align-items-center p-1 p-md-3">
<img src="img/actividad/atenciona.png" class="img-fluid asesor" alt="">
<div class="w-100 opcion text-md-center text-start">${questionData.options[0].text}</div>
</div>
</div>
</div>
<div class="col-12 col-xl-2 my-md-3 my-xl-0 text-center animate__animated animate__bounceIn animate__delay-1s my-2 my-md-0">
<img src="img/actividad/vs.png" class="img-fluid d-xl-inline-block d-none img-w-perso" alt="">
<img src="img/actividad/vsmd.png" class="img-fluid d-xl-none d-inline-block" alt="">
</div>
<div class="col-12 col-xl-5 animate__animated animate__fadeInRight">
<div class="card glass border-0 rounded-15 shadow option-btn cursor p-1 p-md-3" data-correct="${questionData.options[1].isCorrect}">
<div class="card-body text-center d-inline-flex flex-xl-column flex-row justify-content-center align-items-center p-1 p-md-3">
<img src="img/actividad/atencionb.png" class="img-fluid asesor" alt="">
<div class="w-100 opcion text-md-center text-start">${questionData.options[1].text}</div>
</div>
</div>
</div>
</div>`;
if (useSwal) {
// Mostrar la pregunta en un Swal
Swal.fire({
html: questionHtml,
showConfirmButton: false,
customClass: { popup: "swal-question-popup" },
backdrop: "rgba(171, 180, 183, .8)",
showDenyButton: false,
showCancelButton: false,
allowOutsideClick: false,
allowEscapeKey: false,
focusConfirm: false,
target: "body",
didOpen: () => {
//document.body.style.paddingRight = '';
//document.body.classList.remove('swal2-height-auto');
const swalContent = Swal.getHtmlContainer(); // Obtiene el contenedor HTML actual de Swal
// Eliminar cualquier controlador anterior para evitar duplicados
$(swalContent)
.find(".option-btn")
.off("click")
.on("click", function () {
const isCorrect = $(this).data("correct") === "true";
const feedback = isCorrect
? questionData.correctFeedback || "¡Correcto!"
: questionData.incorrectFeedback || "Incorrecto";
handleFeedback(isCorrect, feedback, containerSelector, true); // Usar función para manejar retroalimentación
});
},
});
} else {
// Renderizar pregunta en el contenedor HTML
$(containerSelector).html(questionHtml);
// Eliminar cualquier controlador anterior en el contenedor antes de agregar nuevos
$(containerSelector).off("click", ".option-btn");
// Manejar clic en las opciones
$(containerSelector).on("click", ".option-btn", function () {
const isCorrect = $(this).data("correct") === true;
const feedback = isCorrect
? questionData.correctFeedback || "¡Correcto!"
: questionData.incorrectFeedback || "Incorrecto";
handleFeedback(isCorrect, feedback, containerSelector, false); // Usar función para manejar retroalimentación
});
}
}
}
/**
* Maneja la retroalimentación de la respuesta del usuario y realiza acciones posteriores.
* @param {boolean} isCorrect - Indica si la respuesta del usuario es correcta.
* @param {string} feedback - El texto de retroalimentación que se mostrará.
* @param {string} containerSelector - Selector del contenedor o Swal para renderizar la siguiente pregunta.
* @param {boolean} useSwal - Si es `true`, las preguntas se muestran en un Swal.
*/
function handleFeedback(isCorrect, feedback, containerSelector, useSwal) {
const imageName = isCorrect ? 'retrobien.png' : 'retromal.png';
const html = `<div class="text-center w-100 overflow-hidden">
<img src="img/actividad/${imageName}" class="img-fluid animate__animated animate__flipInY">
<p class="text-secondary bg-responsive">${feedback}</p>
</div>`;
if (isCorrect) {
CourseNav.audioController.stopAllSoundsAndPlay(audios.fc);
} else {
CourseNav.audioController.stopAllSoundsAndPlay(audios.fi);
}
Swal.fire({
html: html,
showConfirmButton: true,
confirmButtonText: "Cerrar",
backdrop: "rgba(171, 180, 183, .8)",
showCloseButton: false,
target: "body",
customClass: {
popup: 'w-32em pop-retro',
confirmButton: 'btn btn-begin text-white fw-bold py-1 animate__animated animate__pulse animate__infinite'
},
/* didOpen: () => {
document.body.style.paddingRight = '';
document.body.classList.remove('swal2-height-auto');
}, */
}).then(() => {
updateVisualFeedback(isCorrect); // Actualiza visualización
quizManager.answerCurrentQuestion(isCorrect); // Registra respuesta
// Mostrar siguiente pregunta o resultados finales
if (quizManager.hasMoreQuestions()) {
quizManager.getNextQuestion();
renderQuestion(containerSelector, false); // Renderizar la siguiente pregunta
} else {
renderResults("#resume-container"); // Mostrar resultados finales
}
});
}
/**
* Renderiza los resultados finales en un contenedor específico.
* @param {string} containerSelector - Selector del contenedor donde se renderizarán los resultados.
*/
function renderResults(containerSelector) {
$(pageActivity).hide().removeClass("d-flex");
$(pageSummary).show().addClass("d-flex");
$(".page-sco").addClass("fakecierre");
const summary = quizManager.getSummary();
const maxAttempts = quizManager.config.maxAttempts || Infinity; // Intentos máximos desde la configuración
const maxAttemptsTxt = maxAttempts === Infinity ? "&infin;" : maxAttempts;
if (summary.passed) {
CourseNav.audioController.stopAllSoundsAndPlay(audios.correcto);
$(".passed").show();
CourseNav.setSlideVisited();
} else {
$(".failed").show();
CourseNav.audioController.stopAllSoundsAndPlay(audios.incorrecto);
}
}
function updateVisualFeedback(isCorrect) {
if (isCorrect) {
$(".trophy").eq(quizManager.currentQuestionIndex).addClass("win");
$(".trophy").eq(quizManager.currentQuestionIndex).find("img").attr('src', 'img/actividad/check.png').addClass("win");
} else {
$(".trophy").eq(quizManager.currentQuestionIndex).find("img").attr('src', 'img/actividad/uncheck.png');
}
}
});
</script>