From 4b17816cde390b4f80ca9eb4d0ea688e0d1682e8 Mon Sep 17 00:00:00 2001 From: RoderickGrc <121266955+RoderickGrc@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:03:15 -0600 Subject: [PATCH] Improve sidebar design with icons --- 404.html | 72 ++++++++++++++++++++++++++++++++++++++++++++++-------- README.md | 9 ++++--- index.html | 72 ++++++++++++++++++++++++++++++++++++++++++++++-------- script.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++--- styles.css | 64 +++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 256 insertions(+), 29 deletions(-) diff --git a/404.html b/404.html index 83a5138..d7b68bf 100644 --- a/404.html +++ b/404.html @@ -12,31 +12,83 @@
- + Colección
+
diff --git a/README.md b/README.md index 6a66758..0c59fc0 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,15 @@ 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. +- **La materia se muestra junto al nombre de la colección** en el encabezado y al seleccionar una colección. +- **Menú lateral rediseñado con iconos** para facilitar la navegació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. @@ -32,7 +35,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. diff --git a/index.html b/index.html index 83a5138..d7b68bf 100644 --- a/index.html +++ b/index.html @@ -12,31 +12,83 @@
- + Colección
+
diff --git a/script.js b/script.js index ebf004b..0a82aaf 100644 --- a/script.js +++ b/script.js @@ -38,6 +38,8 @@ 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; @@ -73,6 +75,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 = ` + ${col.materia || ''} +

${col.nombre}

+

${col.descripcion || ''}

+ `; + 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() { @@ -85,6 +127,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'); @@ -112,7 +156,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 || !homeContainer || !homeCarousel) { console.error("Error: No se encontraron elementos esenciales del DOM (quiz, status, inputs, o elementos del modal)."); if(quizDiv) quizDiv.innerHTML = "

Error crítico: Faltan elementos HTML esenciales para el quiz o la configuración.

"; return; @@ -128,6 +172,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() { @@ -207,7 +258,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'); @@ -216,6 +267,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(); @@ -339,7 +397,11 @@ function updateCollectionTitleById(id) { collectionTitleSpan.textContent = 'Personalizado'; } else { const col = availableCollections.find(c => c.id === id); - collectionTitleSpan.textContent = col ? col.nombre : 'Colección'; + if (col) { + collectionTitleSpan.innerHTML = `${col.materia} ${col.nombre}`; + } else { + collectionTitleSpan.textContent = 'Colección'; + } } } diff --git a/styles.css b/styles.css index 6db5ddd..8f6e0f6 100644 --- a/styles.css +++ b/styles.css @@ -38,6 +38,7 @@ --status-error-bg: #f8d7da; --status-error-color: #721c24; --status-error-border: #f5c6cb; + --subject-color: #d63384; --modal-bg: #fff; } @@ -81,6 +82,7 @@ body.dark-mode { --partial-selection-color: #fff2b3; --partial-selection-border: #b1922c; --modal-bg: #2a2a2a; + --subject-color: #e670a5; } html { @@ -127,6 +129,7 @@ body { color: var(--text-color); font-size: 1.5rem; cursor: pointer; + padding: 0.5rem 1rem; } #collection-title { @@ -141,11 +144,13 @@ body { height: 100%; background-color: #222; color: #fff; - padding-top: 1rem; + padding-top: 0; transform: translateX(-100%); transition: transform 0.3s ease; z-index: 100; overflow-y: auto; + display: flex; + flex-direction: column; } .sidebar.open { @@ -165,7 +170,7 @@ body.sidebar-open { .sidebar .menu-section { border-bottom: 1px solid #444; - padding: 0.5rem 0; + padding: 0.75rem 0; } .sidebar .menu-section:last-child { @@ -174,7 +179,9 @@ body.sidebar-open { .sidebar button, .sidebar a { - display: block; + display: flex; + align-items: center; + gap: 0.5rem; width: 100%; background: none; border: none; @@ -185,6 +192,12 @@ body.sidebar-open { cursor: pointer; text-decoration: none; } +.sidebar button svg, +.sidebar a svg { + width: 20px; + height: 20px; + flex-shrink: 0; +} .sidebar button:hover, .sidebar a:hover { @@ -195,6 +208,7 @@ body.sidebar-open { display: none; text-align: left; color: #fff; + align-self: flex-end; } body.sidebar-open .close-sidebar { @@ -765,3 +779,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-inline { + font-weight: bold; + color: var(--subject-color); + margin-right: 0.5rem; +}