VanguardAI/app/Views/modules/fitness/rutinas.php
2024-10-27 12:50:51 -06:00

484 lines
17 KiB
PHP

<?php include __DIR__ . "/../../layouts/header.php"; ?>
<style>
/* --- Diseño adaptable (Responsive) y estilos de juego --- */
body {
background-color: #f0f2f5;
}
.game-container {
background-color: #f5f5f5;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 20px;
margin-top: 30px;
}
.card {
border: none;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease-in-out;
}
.card:hover {
transform: translateY(-2px);
}
.achievement {
transition: transform 0.3s ease-in-out;
}
.achievement:hover {
transform: scale(1.05);
}
.progress {
height: 25px;
font-size: 0.8rem;
background-color: #e9ecef;
border-radius: 1rem;
overflow: hidden;
}
.progress-bar {
display: flex;
align-items: center;
justify-content: center;
background-color: #007bff;
color: white;
transition: width 0.6s ease;
}
.btn-primary {
background-color: #4e73df;
border-color: #4e73df;
}
.btn-primary:hover {
background-color: #2e59d9;
border-color: #2653d4;
}
.list-group-item {
border-left: 5px solid #4e73df;
margin-bottom: 10px;
border-radius: 5px;
}
.badge {
font-size: 0.8rem;
padding: 0.4em 0.6em;
}
.text-primary {
color: #4e73df !important;
}
/* Animaciones */
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.075);
}
100% {
transform: scale(1);
}
}
.pulse {
animation: pulse 2s infinite;
}
/* Breakpoint para tablets y pantallas medianas (≥ 768px) */
@media (max-width: 767.98px) {
.achievement-card {
margin-bottom: 1rem;
}
}
/* Breakpoint para teléfonos y pantallas pequeñas (≤ 576px) */
@media (max-width: 576px) {
.card-title {
font-size: 1.25rem;
}
}
/* Block: profile-card */
.profile-card {
background: linear-gradient(145deg, #ffffff, #f5f5f5);
border-radius: 16px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
font-family: 'Segoe UI', system-ui, sans-serif;
}
/* Elements */
.profile-card__header {
display: flex;
align-items: center;
margin-bottom: 1.5rem;
}
.profile-card__icon {
background: linear-gradient(45deg, #4e73df, #2e59d9);
color: white;
width: 48px;
height: 48px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
font-size: 1.5rem;
}
.profile-card__title {
color: #1a1a1a;
font-size: 1.5rem;
font-weight: 600;
margin: 0;
}
.profile-card__stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
margin-bottom: 1.5rem;
}
.profile-card__stat-item {
background: rgba(78, 115, 223, 0.1);
padding: 1rem;
border-radius: 12px;
text-align: center;
}
.profile-card__stat-label {
color: #666;
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
.profile-card__stat-value {
color: #1a1a1a;
font-size: 1.25rem;
font-weight: 600;
}
.profile-card__progress {
background: #e0e0e0;
border-radius: 8px;
height: 12px;
overflow: hidden;
position: relative;
}
.profile-card__progress-bar {
background: linear-gradient(90deg, #4e73df, #2e59d9); /* Colores ajustados */
height: 100%;
transition: width 0.3s ease;
}
/* Modifiers */
.profile-card__progress-bar--low {
background: linear-gradient(90deg, #FFA726, #F57C00);
}
.profile-card__progress-bar--high {
background: linear-gradient(90deg, #66BB6A, #388E3C);
}
</style>
<div class="container-fluid px-3 px-md-4 mt-4">
<div class="game-container">
<div class="row mt-3">
<div class="col-12">
<h1 class="text-center fw-bold h2 text-dark">
<i class="fas fa-dumbbell mr-2"></i> Rutinas Personalizadas
</h1>
</div>
</div>
<div class="row mt-4">
<div class="col-12 col-md-4">
<div class="profile-card">
<div class="profile-card__header">
<div class="profile-card__icon">
<i class="fas fa-user-circle"></i>
</div>
<h2 class="profile-card__title">Perfil de Gymbro</h2>
</div>
<div class="profile-card__stats">
<div class="profile-card__stat-item">
<div class="profile-card__stat-label">Nivel</div>
<div class="profile-card__stat-value" id="userLevel">1</div>
</div>
<div class="profile-card__stat-item">
<div class="profile-card__stat-label">Puntos XP</div>
<div class="profile-card__stat-value" id="userPoints">0</div>
</div>
</div>
<div class="profile-card__progress">
<div class="profile-card__progress-bar" id="expProgress" role="progressbar" aria-valuenow="0"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<div class="col-12 col-md-8">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title"><i class="fas fa-tasks mr-2"></i> Misión Diaria</h5>
<select id="routineType" class="form-select mb-3">
<option value="fullBody">Full Body</option>
<option value="upperLower">Torso/Pierna</option>
</select>
<ul id="exerciseList" class="list-group mb-3">
<!-- Los ejercicios se agregarán dinámicamente aquí -->
</ul>
<button id="completeRoutine" class="btn btn-primary btn-lg btn-block">
<i class="fas fa-check-circle mr-2"></i> Completar Misión
</button>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<h3 class="text-center mb-3 text-primary"><i class="fas fa-trophy mr-2"></i> Logros Desbloqueados</h3>
<div id="achievements" class="row">
<!-- Los logros se agregarán dinámicamente aquí -->
</div>
</div>
</div>
</div>
</div>
<!-- SweetAlert2 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const exercisesByType = {
fullBody: [
{ name: 'Sentadillas', points: 15, icon: 'fa-dumbbell' },
{ name: 'Flexiones', points: 10, icon: 'fa-child' },
{ name: 'Peso muerto', points: 20, icon: 'fa-dumbbell' },
{ name: 'Dominadas', points: 15, icon: 'fa-child' },
{ name: 'Burpees', points: 20, icon: 'fa-running' }
],
upperLower: {
upper: [
{ name: 'Press de banca', points: 15, icon: 'fa-dumbbell' },
{ name: 'Remo con barra', points: 15, icon: 'fa-dumbbell' },
{ name: 'Press militar', points: 12, icon: 'fa-dumbbell' },
{ name: 'Curl de bíceps', points: 10, icon: 'fa-dumbbell' },
{ name: 'Tríceps en polea', points: 10, icon: 'fa-dumbbell' }
],
lower: [
{ name: 'Sentadillas', points: 15, icon: 'fa-dumbbell' },
{ name: 'Peso muerto', points: 20, icon: 'fa-dumbbell' },
{ name: 'Prensa de piernas', points: 15, icon: 'fa-dumbbell' },
{ name: 'Elevaciones de pantorrilla', points: 10, icon: 'fa-dumbbell' },
{ name: 'Hip thrust', points: 12, icon: 'fa-dumbbell' }
]
},
pushPullLegs: {
push: [
{ name: 'Press de banca', points: 15, icon: 'fa-dumbbell' },
{ name: 'Press militar', points: 12, icon: 'fa-dumbbell' },
{ name: 'Fondos en paralelas', points: 15, icon: 'fa-child' },
{ name: 'Elevaciones laterales', points: 10, icon: 'fa-dumbbell' },
{ name: 'Extensiones de tríceps', points: 10, icon: 'fa-dumbbell' }
],
pull: [
{ name: 'Dominadas', points: 15, icon: 'fa-child' },
{ name: 'Remo con barra', points: 15, icon: 'fa-dumbbell' },
{ name: 'Curl de bíceps', points: 10, icon: 'fa-dumbbell' },
{ name: 'Face pull', points: 12, icon: 'fa-dumbbell' },
{ name: 'Remo en T', points: 12, icon: 'fa-dumbbell' }
],
legs: [
{ name: 'Sentadillas', points: 15, icon: 'fa-dumbbell' },
{ name: 'Peso muerto', points: 20, icon: 'fa-dumbbell' },
{ name: 'Prensa de piernas', points: 15, icon: 'fa-dumbbell' },
{ name: 'Extensiones de cuádriceps', points: 10, icon: 'fa-dumbbell' },
{ name: 'Curl de isquiotibiales', points: 10, icon: 'fa-dumbbell' }
]
}
};
const achievements = [
{ name: 'Principiante', description: 'Completa tu primera misión', icon: 'fa-star', unlocked: false },
{ name: 'Constante', description: 'Completa 5 misiones', icon: 'fa-fire', unlocked: false },
{ name: 'Maestro del Fitness', description: 'Alcanza el nivel 5', icon: 'fa-fist-raised', unlocked: false },
{ name: 'Imparable', description: 'Acumula 1000 puntos', icon: 'fa-trophy', unlocked: false }
];
let userPoints = 0;
let userLevel = 1;
let routinesCompleted = 0;
function updateUserInterface() {
document.getElementById('userPoints').textContent = userPoints;
document.getElementById('userLevel').textContent = userLevel;
const expProgress = (userPoints % 100) / 100 * 100;
const progressBar = document.getElementById('expProgress');
progressBar.style.width = `${expProgress}%`;
progressBar.setAttribute('aria-valuenow', expProgress);
// Eliminado: progressBar.textContent
}
function populateExerciseList() {
const exerciseList = document.getElementById('exerciseList');
exerciseList.innerHTML = '';
const routineType = document.getElementById('routineType').value;
let exercises;
if (routineType === 'fullBody') {
exercises = exercisesByType.fullBody;
} else if (routineType === 'upperLower') {
exercises = Math.random() < 0.5 ? exercisesByType.upperLower.upper : exercisesByType.upperLower.lower;
} else {
const pplTypes = ['push', 'pull', 'legs'];
const randomType = pplTypes[Math.floor(Math.random() * pplTypes.length)];
exercises = exercisesByType.pushPullLegs[randomType];
}
exercises.forEach((exercise, index) => {
const li = document.createElement('li');
li.className = 'list-group-item d-flex justify-content-between align-items-center';
li.innerHTML = `
<span><i class="fas ${exercise.icon} mr-2"></i> ${exercise.name}</span>
<span class="badge bg-primary rounded-pill">${exercise.points} XP</span>
`;
exerciseList.appendChild(li);
});
}
function completeRoutine() {
const routineType = document.getElementById('routineType').value;
let exercises;
if (routineType === 'fullBody') {
exercises = exercisesByType.fullBody;
} else if (routineType === 'upperLower') {
exercises = Math.random() < 0.5 ? exercisesByType.upperLower.upper : exercisesByType.upperLower.lower;
} else {
const pplTypes = ['push', 'pull', 'legs'];
const randomType = pplTypes[Math.floor(Math.random() * pplTypes.length)];
exercises = exercisesByType.pushPullLegs[randomType];
}
const earnedPoints = exercises.reduce((sum, exercise) => sum + exercise.points, 0);
userPoints += earnedPoints;
routinesCompleted++;
while (userPoints >= userLevel * 100) {
userPoints -= userLevel * 100;
userLevel++;
showLevelUpMessage(userLevel);
}
updateUserInterface();
checkAchievements();
showMessageToast(`¡Misión cumplida! Has ganado ${earnedPoints} puntos de experiencia.`);
}
function showLevelUpMessage(newLevel) {
Swal.fire({
title: '¡Subiste de nivel!',
text: `Has alcanzado el nivel ${newLevel}. ¡Sigue así, campeón!`,
icon: 'success',
confirmButtonText: '¡Genial!'
});
}
function checkAchievements() {
achievements.forEach((achievement, index) => {
if (!achievement.unlocked) {
if (
(achievement.name === 'Principiante' && routinesCompleted >= 1) ||
(achievement.name === 'Constante' && routinesCompleted >= 5) ||
(achievement.name === 'Maestro del Fitness' && userLevel >= 5) ||
(achievement.name === 'Imparable' && userPoints + (userLevel - 1) * 100 >= 1000)
) {
achievement.unlocked = true;
updateAchievementDisplay(index);
showAchievementUnlockedMessage(achievement);
}
}
});
}
function updateAchievementDisplay(index) {
const achievementElement = document.getElementById(`achievement-${index}`);
if (achievementElement) {
achievementElement.classList.remove('bg-secondary');
achievementElement.classList.add('bg-success', 'pulse');
}
}
function showAchievementUnlockedMessage(achievement) {
Swal.fire({
title: '¡Logro Desbloqueado!',
text: `Has conseguido el logro "${achievement.name}": ${achievement.description}`,
icon: 'success',
confirmButtonText: '¡Increíble!'
});
}
function populateAchievements() {
const achievementsContainer = document.getElementById('achievements');
achievements.forEach((achievement, index) => {
const achievementElement = document.createElement('div');
achievementElement.className = 'col-md-3 mb-3';
achievementElement.innerHTML = `
<div id="achievement-${index}" class="card text-white ${achievement.unlocked ? 'bg-success' : 'bg-secondary'} achievement">
<div class="card-body text-center">
<h5 class="card-title"><i class="fas ${achievement.icon} mr-2"></i> ${achievement.name}</h5>
<p class="card-text">${achievement.description}</p>
</div>
</div>
`;
achievementsContainer.appendChild(achievementElement);
});
}
function showMessageToast(message, type = 'success') {
Swal.fire({
text: message,
icon: type,
showConfirmButton: false,
timer: 2000,
toast: true,
position: 'top-end',
background: '#f8f9fa',
color: '#000',
iconColor: type === 'error' ? '#dc3545' : type === 'warning' ? '#ffc107' : '#28a745',
customClass: {
popup: 'shadow-sm'
}
});
}
document.getElementById('routineType').addEventListener('change', populateExerciseList);
document.getElementById('completeRoutine').addEventListener('click', completeRoutine);
populateExerciseList();
populateAchievements();
updateUserInterface();
});
</script>
<?php include __DIR__ . "/../../layouts/footer.php"; ?>