Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
<body>
<header class="main-header">
<button id="open-sidebar" class="sidebar-toggle" aria-label="Abrir menú">&#9776;</button>
<span id="collection-title">Colección</span>
<span id="collection-title"><span id="collection-subject" class="collection-subject-header"></span><span id="collection-name">Colección</span></span>
</header>

<aside id="sidebar" class="sidebar">
<button id="close-sidebar" class="sidebar-toggle close-sidebar" aria-label="Cerrar menú">&#9776;</button>
<div class="menu-section">
<a href="/" id="home-link">Inicio</a>
<a href="/home" id="home-link">Inicio</a>
<button id="change-collection-button">Cambiar colección</button>
</div>
<div class="menu-section">
Expand All @@ -37,6 +37,10 @@
<button id="login-button">Iniciar sesión</button>
</div>
</aside>
<div id="home-container" class="home-container hidden">
<h1>¿Qué estudiaremos hoy?</h1>
<div id="home-carousel" class="home-carousel"></div>
</div>
<div class="quiz-container">
<div id="quiz"></div>
<!-- Elemento para mostrar mensajes de estado (opcional) -->
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ Este proyecto es un quiz interactivo implementado con HTML, CSS y JavaScript pur
- **Modo claro u oscuro** seleccionable desde la configuración.
- **Texto de botones negro** para asegurar contraste en ambos temas.
- **Banner de error en preguntas múltiples** que resalta aciertos parciales en amarillo.
- **Las colecciones muestran también su materia** tanto en el encabezado como en la lista de selección.

## Uso rápido

1. Clona el repositorio y abre `index.html` en un navegador web moderno.
2. El quiz cargará por defecto el archivo `questions.csv` incluido en el repositorio.
3. Utiliza los botones de la parte superior para:
2. Al iniciar se muestra una pantalla de inicio accesible también en `/home` con las colecciones disponibles.
3. El quiz cargará por defecto el archivo `questions.csv` incluido en el repositorio.
4. Utiliza los botones de la parte superior para:
- Guardar o cargar el progreso (archivo JSON).
- Cargar un CSV diferente con tus propias preguntas.
- Reiniciar el avance actual.
Expand All @@ -32,7 +34,7 @@ Si se desea utilizar un CSV propio, consulta `doc/prompt.md` para conocer el for

## Estructura del repositorio

- `index.html` – vista principal del quiz.
- `index.html` – página principal que muestra el home y el quiz.
- `script.js` – lógica de funcionamiento y manejo de estado.
- `styles.css` – estilos de la interfaz.
- `questions.csv` – ejemplo de preguntas en formato CSV.
Expand Down
8 changes: 6 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
<body>
<header class="main-header">
<button id="open-sidebar" class="sidebar-toggle" aria-label="Abrir menú">&#9776;</button>
<span id="collection-title">Colección</span>
<span id="collection-title"><span id="collection-subject" class="collection-subject-header"></span><span id="collection-name">Colección</span></span>
</header>

<aside id="sidebar" class="sidebar">
<button id="close-sidebar" class="sidebar-toggle close-sidebar" aria-label="Cerrar menú">&#9776;</button>
<div class="menu-section">
<a href="/" id="home-link">Inicio</a>
<a href="/home" id="home-link">Inicio</a>
<button id="change-collection-button">Cambiar colección</button>
</div>
<div class="menu-section">
Expand All @@ -37,6 +37,10 @@
<button id="login-button">Iniciar sesión</button>
</div>
</aside>
<div id="home-container" class="home-container hidden">
<h1>¿Qué estudiaremos hoy?</h1>
<div id="home-carousel" class="home-carousel"></div>
</div>
<div class="quiz-container">
<div id="quiz"></div>
<!-- Elemento para mostrar mensajes de estado (opcional) -->
Expand Down
79 changes: 74 additions & 5 deletions script.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ let quizContainerDiv = null; // <-- NUEVO: Referencia al contenedor principal
let timeProgressDiv = null;
let timeBarDiv = null;
let timeRemainingSpan = null;
let homeContainer = null;
let homeCarousel = null;
let sidebar = null;
let openSidebarButton = null;
let closeSidebarButton = null;
let collectionTitleSpan = null;
let collectionSubjectSpan = null;
let collectionNameSpan = null;

let initialTotalRepetitions = 0;
let questionStartTime = null;
Expand Down Expand Up @@ -73,6 +77,46 @@ function updateUrlForCollection(id, replace = false) {
}
}

function isHomePath() {
const path = window.location.pathname.replace(/\/+$/, '');
return path === '' || path === '/home';
}

function showHome() {
homeContainer?.classList.remove('hidden');
quizContainerDiv?.classList.add('hidden');
timeProgressDiv?.classList.add('hidden');
}

function showQuiz() {
homeContainer?.classList.add('hidden');
quizContainerDiv?.classList.remove('hidden');
timeProgressDiv?.classList.remove('hidden');
}

function populateHomeCarousel() {
if (!homeCarousel) return;
homeCarousel.innerHTML = '';
availableCollections.forEach(col => {
const card = document.createElement('div');
card.className = 'collection-card';
card.innerHTML = `
<span class="collection-subject">${col.materia || ''}</span>
<h3>${col.nombre}</h3>
<p>${col.descripcion || ''}</p>
`;
card.addEventListener('click', () => {
showQuiz();
updateUrlForCollection(col.id);
collectionSelect.value = col.id;
localStorage.setItem(COLLECTION_STORAGE_KEY, col.id);
loadQuestionsFromCollection(col.id);
updateCollectionTitleById(col.id);
});
homeCarousel.appendChild(card);
});
}

// --- Inicialización ---

document.addEventListener('DOMContentLoaded', function() {
Expand All @@ -85,6 +129,8 @@ document.addEventListener('DOMContentLoaded', function() {
timeProgressDiv = document.getElementById('time-progress');
timeBarDiv = document.getElementById('time-bar');
timeRemainingSpan = document.getElementById('time-remaining');
homeContainer = document.getElementById('home-container');
homeCarousel = document.getElementById('home-carousel');
collectionSelect = document.getElementById('collection-select');
changeCollectionButton = document.getElementById('change-collection-button');
collectionModalOverlay = document.getElementById('collection-modal-overlay');
Expand All @@ -95,6 +141,8 @@ document.addEventListener('DOMContentLoaded', function() {
openSidebarButton = document.getElementById('open-sidebar');
closeSidebarButton = document.getElementById('close-sidebar');
collectionTitleSpan = document.getElementById('collection-title');
collectionSubjectSpan = document.getElementById('collection-subject');
collectionNameSpan = document.getElementById('collection-name');

// Referencias para el modal de configuración
configButton = document.getElementById('config-button');
Expand All @@ -112,7 +160,7 @@ document.addEventListener('DOMContentLoaded', function() {
!changeCollectionButton || !collectionModalOverlay || !collectionModal || !confirmCollectionButton ||
!configButton || !configModalOverlay || !configModal || !configRepsOnErrorInput ||
!configInitialRepsInput || !configThemeSelect || !saveConfigButton || !closeModalButton || !closeModalXButton ||
!sidebar || !openSidebarButton || !closeSidebarButton || !collectionTitleSpan) {
!sidebar || !openSidebarButton || !closeSidebarButton || !collectionTitleSpan || !collectionSubjectSpan || !collectionNameSpan || !homeContainer || !homeCarousel) {
console.error("Error: No se encontraron elementos esenciales del DOM (quiz, status, inputs, o elementos del modal).");
if(quizDiv) quizDiv.innerHTML = "<p class='error-message'>Error crítico: Faltan elementos HTML esenciales para el quiz o la configuración.</p>";
return;
Expand All @@ -128,6 +176,13 @@ document.addEventListener('DOMContentLoaded', function() {
window.addEventListener('beforeunload', saveState);
document.addEventListener('visibilitychange', handleVisibilityChange);
autosaveIntervalId = setInterval(saveState, 10000);
window.addEventListener('popstate', () => {
if (isHomePath()) {
showHome();
} else {
showQuiz();
}
});
});

function setupEventListeners() {
Expand Down Expand Up @@ -207,7 +262,7 @@ async function loadCollections() {
availableCollections.forEach(c => {
const opt = document.createElement('option');
opt.value = c.id;
opt.textContent = c.nombre;
opt.textContent = c.materia ? `${c.materia} | ${c.nombre}` : c.nombre;
collectionSelect.appendChild(opt);
});
customOption = document.createElement('option');
Expand All @@ -216,6 +271,13 @@ async function loadCollections() {
customOption.disabled = true;
collectionSelect.appendChild(customOption);

populateHomeCarousel();

if (isHomePath()) {
showHome();
return;
}

const saved = localStorage.getItem(COLLECTION_STORAGE_KEY);
const pathId = getCollectionIdFromPath();

Expand Down Expand Up @@ -334,12 +396,19 @@ function handleDocumentClick(event) {
}

function updateCollectionTitleById(id) {
if (!collectionTitleSpan) return;
if (!collectionSubjectSpan || !collectionNameSpan) return;
if (id === 'custom') {
collectionTitleSpan.textContent = 'Personalizado';
collectionSubjectSpan.textContent = '';
collectionNameSpan.textContent = 'Personalizado';
} else {
const col = availableCollections.find(c => c.id === id);
collectionTitleSpan.textContent = col ? col.nombre : 'Colección';
if (col) {
collectionSubjectSpan.textContent = col.materia ? col.materia : '';
collectionNameSpan.textContent = col.nombre;
} else {
collectionSubjectSpan.textContent = '';
collectionNameSpan.textContent = 'Colección';
}
}
}

Expand Down
46 changes: 46 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
--status-error-bg: #f8d7da;
--status-error-color: #721c24;
--status-error-border: #f5c6cb;
--subject-color: #d63384;
--modal-bg: #fff;
}

Expand Down Expand Up @@ -81,6 +82,7 @@ body.dark-mode {
--partial-selection-color: #fff2b3;
--partial-selection-border: #b1922c;
--modal-bg: #2a2a2a;
--subject-color: #e670a5;
}

html {
Expand Down Expand Up @@ -765,3 +767,47 @@ body.sidebar-open #open-sidebar {
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

/* --- Estilos para la pantalla de inicio --- */
.home-container {
width: 90%;
max-width: 1000px;
margin: 2rem auto;
text-align: center;
}

.home-carousel {
display: flex;
overflow-x: auto;
gap: 1rem;
padding: 1rem 0;
}

.collection-card {
flex: 0 0 auto;
background-color: var(--container-bg);
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
padding: 1rem;
width: 220px;
cursor: pointer;
border: 2px solid transparent;
transition: border-color 0.3s ease;
}

.collection-card:hover {
border-color: var(--option-selected-border);
}

.collection-subject {
font-weight: bold;
color: var(--subject-color);
display: block;
margin-bottom: 0.5rem;
}

.collection-subject-header {
font-weight: bold;
color: var(--subject-color);
margin-right: 0.25rem;
}