Merge pull request 'Actividad 11' (#2) from Feuture-11 into main

Reviewed-on: #2
This commit is contained in:
Salvador Martínez Gaytán 2025-09-23 15:40:17 -06:00
commit 1bb1258c16
12 changed files with 388 additions and 66 deletions

View File

@ -11,38 +11,119 @@
width: 40%; width: 40%;
} }
.bg-custom {
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
}
.content-cards { .content-cards {
width: 100%; width: 100%;
} }
.content-cards .persoSwiper { .dislike-indicator {
top: 50%;
left: 20px;
transform: translateY(-50%);
z-index: 10;
opacity: 0;
}
.like-indicator {
top: 50%;
right: 20px;
transform: translateY(-50%);
z-index: 10;
opacity: 0;
}
.indicator-circle {
width: 60px;
height: 60px;
font-size: 24px;
}
.gradient-bg {
top: 0;
left: 0;
z-index: 1;
}
.gradient-left {
left: 0;
top: 10%;
width: 50%;
height: 80%;
background: #925c8d;
background: linear-gradient(270deg, rgba(146, 92, 141, 1) 0%, rgba(146, 92, 141, 0) 100%);
}
.gradient-right {
right: 0;
top: 10%;
width: 50%;
height: 80%;
background: #6c9d7a;
background: linear-gradient(90deg, rgba(108, 157, 122, 1) 0%, rgba(108, 157, 122, 0) 100%);
}
.bg-image {
z-index: 2;
opacity: 0.7;
}
.bg-image-left {
left: 20px;
bottom: 60px;
}
.bg-image-right {
right: 20px;
bottom: 60px;
}
.bg-image img {
width: 220px;
height: auto;
}
.card-stack {
position: relative;
width: 326px; width: 326px;
height: 326px; height: 326px;
margin: 0 auto;
z-index: 5;
}
.tinder-card {
position: absolute;
width: 100%;
height: 100%;
cursor: grab;
transition: transform 0.3s ease;
user-select: none;
}
.tinder-card img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 10px;
} }
</style> </style>
<div class='page-sco py-2 py-md-0 h-100'> <div class="page-sco py-2 py-md-0 h-100">
<div class='container h-100'> <div class="container h-100">
<div class='row justify-content-center align-items-center h-100'> <div class="row justify-content-center align-items-center h-100">
<div class='col-12'> <div class="col-12">
<div class='row justify-content-center'> <div class="row justify-content-center">
<div class="col-10 mb-2 animate__animated animate__bounceInDown"> <div class="col-10 mb-2 animate__animated animate__bounceInDown">
<h2 class="text-center fw-bold text-primary">Características del sitio de salida</h2> <h2 class="text-center fw-bold text-primary">Características del sitio de salida</h2>
<hr class="border border-3 border-verde-oscuro hr-style mx-auto my-0"> <hr class="border border-3 border-verde-oscuro hr-style mx-auto my-0" />
</div> </div>
<div class="col-12 px-0 mb-1 animate__animated animate__lightSpeedInLeft"> <div class="col-12 px-0 mb-1 animate__animated animate__lightSpeedInLeft" id="col-instrucciones">
<div class="card bg-white border-0 my-2 rounded-0 bg-custom px-3 py-2 text-center"> <div class="card bg-white border-0 my-2 rounded-0 bg-custom px-3 py-2 text-center">
<div class="d-flex justify-content-center align-items-center flex-row gap-2"> <div class="d-flex justify-content-center align-items-center flex-row gap-2">
<img src="img/3.1.png" class="img-fluid mx-3"> <img src="img/3.1.png" class="img-fluid mx-3" />
<div class="parrafos text-start"> <div class="parrafos text-start">
<p class="mb-2"><strong>Instrucciones:</strong> Observa las imágenes del sitio de salida que se presentan en las <p class="mb-2"><strong>Instrucciones:</strong> Observa las imágenes del sitio de salida que se presentan en las tarjetas.</p>
tarjetas.</p> <p class="mb-0">
<p class="mb-0">Si consideras que se encuentra sano, desliza la tarjeta a la <strong class="text-verde-pino">derecha</strong>. Si Si consideras que se encuentra sano, desliza la tarjeta a la <strong class="text-verde-pino">derecha</strong>. Si crees que no está sano,
crees que no está sano, desliza la tarjeta a la <strong class="text-verde-pino">izquierda</strong>.
desliza la tarjeta a la <strong class="text-verde-pino">izquierda</strong>.</p> </p>
</div> </div>
</div> </div>
</div> </div>
@ -54,26 +135,48 @@
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="position-relative content-cards text-center"> <div class="position-relative content-cards text-center">
<div class="swiper persoSwiper"> <!-- Like/Dislike indicators -->
<div class="swiper-wrapper"> <div class="position-absolute dislike-indicator" id="dislike-indicator">
<div class="swiper-slide"> <div class="bg-danger text-white rounded-circle d-flex align-items-center justify-content-center indicator-circle"></div>
<img src="img/11.0.png" class="img-fluid"> <div class="text-danger fw-bold mt-2">NO SANO</div>
</div> </div>
<div class="swiper-slide"> <div class="position-absolute like-indicator" id="like-indicator">
<img src="img/11.1.png" class="img-fluid"> <div class="bg-success text-white rounded-circle d-flex align-items-center justify-content-center indicator-circle"></div>
</div> <div class="text-success fw-bold mt-2">SANO</div>
<div class="swiper-slide"> </div>
<img src="img/11.2.png" class="img-fluid">
</div> <!-- Degradados de fondo -->
<div class="swiper-slide"> <div class="position-absolute w-100 h-100 gradient-bg">
<img src="img/11.3.png" class="img-fluid"> <div class="position-absolute gradient-left"></div>
</div> <div class="position-absolute gradient-right"></div>
<div class="swiper-slide"> </div>
<img src="img/11.4.png" class="img-fluid">
</div> <!-- Imágenes de fondo -->
<div class="swiper-slide"> <div class="position-absolute bg-image bg-image-left">
<img src="img/11.5.png" class="img-fluid"> <img src="img/11.nosano.png" alt="No Sano" />
</div> </div>
<div class="position-absolute bg-image bg-image-right">
<img src="img/11.sano.png" alt="Sano" />
</div>
<div id="card-stack" class="card-stack">
<div data-index="0" class="tinder-card">
<img src="img/11.0.png" alt="Imagen 1" />
</div>
<div data-index="1" class="tinder-card">
<img src="img/11.1.png" alt="Imagen 2" />
</div>
<div data-index="2" class="tinder-card">
<img src="img/11.2.png" alt="Imagen 3" />
</div>
<div data-index="3" class="tinder-card">
<img src="img/11.3.png" alt="Imagen 4" />
</div>
<div data-index="4" class="tinder-card">
<img src="img/11.4.png" alt="Imagen 5" />
</div>
<div data-index="5" class="tinder-card">
<img src="img/11.5.png" alt="Imagen 6" />
</div> </div>
</div> </div>
</div> </div>
@ -85,14 +188,31 @@
</div> </div>
</div> </div>
</div> </div>
<div class="d-none">
<div id="pop0">
<div class="container-fluid">
<div class=" w-100 text-center">
<img src="img/3.5.png" class="img-fluid">
</div>
<div class="row justify-content-center">
<div class="col-12 text-center mb-2">
<h3 class="text-secondary-dark fw-bold">Ten en cuenta que…</h3>
</div>
<div class="col-12 text-center">
<p class="mb-0">En caso de alguna complicación, se debe acudir a la unidad de diálisis.</p>
</div>
</div>
</div>
</div>
</div>
<script> <script>
$(function () { $(function () {
"use strict"; "use strict";
$('.wrap-course-content').addClass('fake'); $(".wrap-course-content").addClass("fake");
const feedbackcorrect = CourseNav.createSound('audio/feedback-correct.mpeg'); const feedbackcorrect = CourseNav.createSound("audio/feedback-correct.mpeg");
const feedbackincorrect = CourseNav.createSound('audio/feedback-incorrect.mpeg'); const feedbackincorrect = CourseNav.createSound("audio/feedback-incorrect.mpeg");
const respuestasCorrectas = ['true','true','false','false','false']; const respuestasCorrectas = ["true", "true", "false", "false", "false"];
function shuffleArray(array) { function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) { for (let i = array.length - 1; i > 0; i--) {
@ -102,38 +222,240 @@
return array; return array;
} }
// Shuffle slides and answers // Shuffle cards and answers
const slides = Array.from(document.querySelectorAll('.swiper-slide')); const cards = Array.from(document.querySelectorAll(".tinder-card"));
const slidesData = slides.map((slide, index) => ({ const cardsData = cards.map((card, index) => ({
element: slide, element: card,
answer: respuestasCorrectas[index] answer: respuestasCorrectas[index],
})); }));
const shuffledData = shuffleArray(slidesData); const shuffledData = shuffleArray(cardsData);
const wrapper = document.querySelector('.swiper-wrapper'); const stack = document.getElementById("card-stack");
wrapper.innerHTML = ''; stack.innerHTML = "";
const shuffledAnswers = []; const shuffledAnswers = [];
shuffledData.forEach((item, index) => { shuffledData.forEach((item, index) => {
wrapper.appendChild(item.element); item.element.style.zIndex = shuffledData.length - index;
stack.appendChild(item.element);
shuffledAnswers[index] = item.answer; shuffledAnswers[index] = item.answer;
}); });
const swiper = new Swiper('.persoSwiper', { let currentCardIndex = 0;
effect: 'cards', let userAnswers = [];
grabCursor: true, let isProcessing = false;
centeredSlides: true, let isDragging = false;
slidesPerView: 'auto', let startX = 0;
initialSlide: 0, let startY = 0;
cardsEffect: { let currentX = 0;
slideShadows: false, let currentY = 0;
perSlideOffset: 10,
perSlideRotate: 2, function initTinderCards() {
}, const currentCard = shuffledData[currentCardIndex]?.element;
on: { if (!currentCard) return;
slideChange: function () {
} currentCard.addEventListener("mousedown", handleStart, { passive: false });
currentCard.addEventListener("touchstart", handleStart, { passive: false });
}
function handleStart(e) {
if (isProcessing) return;
e.preventDefault();
isDragging = true;
const touch = e.type === "touchstart" ? e.touches[0] : e;
startX = touch.clientX;
startY = touch.clientY;
const card = e.target.closest(".tinder-card");
card.style.transition = "none";
card.style.cursor = "grabbing";
document.addEventListener("mousemove", handleMove, { passive: false });
document.addEventListener("touchmove", handleMove, { passive: false });
document.addEventListener("mouseup", handleEnd);
document.addEventListener("touchend", handleEnd);
}
function handleMove(e) {
if (!isDragging || isProcessing) return;
e.preventDefault();
const touch = e.type === "touchmove" ? e.touches[0] : e;
currentX = touch.clientX - startX;
currentY = touch.clientY - startY;
const card = shuffledData[currentCardIndex]?.element;
if (!card) return;
const rotation = currentX * 0.1;
card.style.transform = `translate(${currentX}px, ${currentY}px) rotate(${rotation}deg)`;
const likeIndicator = document.getElementById("like-indicator");
const dislikeIndicator = document.getElementById("dislike-indicator");
if (currentX > 50) {
likeIndicator.style.opacity = Math.min(1, (currentX - 50) / 100);
dislikeIndicator.style.opacity = 0;
} else if (currentX < -50) {
dislikeIndicator.style.opacity = Math.min(1, (Math.abs(currentX) - 50) / 100);
likeIndicator.style.opacity = 0;
} else {
likeIndicator.style.opacity = 0;
dislikeIndicator.style.opacity = 0;
} }
}); }
function handleEnd(e) {
if (!isDragging || isProcessing) return;
isDragging = false;
document.removeEventListener("mousemove", handleMove);
document.removeEventListener("touchmove", handleMove);
document.removeEventListener("mouseup", handleEnd);
document.removeEventListener("touchend", handleEnd);
const card = shuffledData[currentCardIndex]?.element;
if (!card) return;
card.style.transition = "transform 0.3s ease";
card.style.cursor = "grab";
const likeIndicator = document.getElementById("like-indicator");
const dislikeIndicator = document.getElementById("dislike-indicator");
likeIndicator.style.opacity = 0;
dislikeIndicator.style.opacity = 0;
if (Math.abs(currentX) > 100) {
isProcessing = true;
const isLike = currentX > 0;
const correctAnswer = shuffledAnswers[currentCardIndex] === "true";
const isCorrect = (isLike && correctAnswer) || (!isLike && !correctAnswer);
animateCardOut(card, isLike, isCorrect);
processSwipe(isLike, isCorrect);
} else {
card.style.transform = "";
}
currentX = 0;
currentY = 0;
}
function animateCardOut(card, isLike, isCorrect) {
if (isCorrect) {
const direction = isLike ? 1 : -1;
card.style.transform = `translateX(${direction * 400}px) rotate(${direction * 30}deg)`;
card.style.opacity = "0";
setTimeout(() => {
card.style.display = "none";
nextCard();
}, 300);
} else {
// Animación de rebote para respuesta incorrecta
card.style.transform = "scale(0.95)";
setTimeout(() => {
card.style.transform = "";
isProcessing = false;
}, 200);
}
}
function nextCard() {
currentCardIndex++;
updateProgress();
if (currentCardIndex < shuffledData.length) {
initTinderCards();
isProcessing = false;
}
}
initTinderCards();
function processSwipe(isLike, isCorrect) {
if (isCorrect) {
feedbackcorrect.play();
userAnswers.push({
cardIndex: currentCardIndex,
userAnswer: isLike,
isCorrect: true,
});
if (currentCardIndex + 1 >= shuffledAnswers.length) {
setTimeout(() => {
updateProgress();
showResults();
}, 500);
}
} else {
feedbackincorrect.play();
// No avanzar, permitir reintentar
}
}
function updateProgress() {
const indicators = document.querySelector(".indicadores-avance");
indicators.innerHTML = "";
for (let i = 0; i < shuffledAnswers.length; i++) {
const indicator = document.createElement("div");
indicator.style.cssText = "width: 40px; height: 40px; margin: 0 8px; display: flex; align-items: center; justify-content: center;";
if (i < userAnswers.length) {
const img = document.createElement("img");
img.style.cssText = "width: 100%; height: 100%;";
img.src = "img/11.good.png";
indicator.appendChild(img);
} else if (i === currentCardIndex) {
indicator.style.cssText += "background-color: #2196F3; border-radius: 50%; color: white; font-size: 18px; font-weight: bold;";
indicator.innerHTML = (i + 1).toString();
} else {
indicator.style.cssText += "background-color: #E0E0E0; border-radius: 50%; color: #999; font-size: 18px; font-weight: bold;";
indicator.innerHTML = (i + 1).toString();
}
indicators.appendChild(indicator);
}
}
function showResults() {
// Ocultar instrucciones
document.getElementById("col-instrucciones").style.display = "none";
const resultHTML = `
<div class="text-center">
<h3>¡Actividad completada!</h3>
<p>¡Todas las respuestas fueron correctas!</p>
</div>
`;
checkAllCompleted();
document.querySelector(".content-cards").innerHTML = resultHTML;
CourseNav.setSlideVisited(true);
}
function checkAllCompleted() {
const html = $("#pop0").html();
Swal.fire({
html: html,
target: document.getElementById('wrap-course-content'),
customClass: {
popup: "pop_html_style border border-3 border-primary rounded-4",
confirmButton: "btn text-white bg-primary amor fw-semibold animate__animated animate__pulse animate__infinite",
},
confirmButtonText: "Cerrar",
showConfirmButton: true,
allowOutsideClick: false,
allowEscapeKey: false,
backdrop: "rgba(65, 60, 60, .95)",
width: "35em",
didClose: () => {
CourseNav.setSlideVisited();
},
});
}
// Initialize progress indicators
updateProgress();
}); });
</script> </script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 54 KiB

BIN
img/11.bad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
img/11.check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
img/11.good.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
img/11.nosano.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
img/11.sano.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB