diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml new file mode 100644 index 00000000..a7c495e9 --- /dev/null +++ b/.github/workflows/jekyll-gh-pages.yml @@ -0,0 +1,51 @@ +# Sample workflow for building and deploying a Jekyll site to GitHub Pages +name: Deploy Jekyll with GitHub Pages dependencies preinstalled + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./src + destination: ./_site + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..0a6a85b3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "livePreview.defaultPreviewPath": "/src/index.html" +} \ No newline at end of file diff --git a/README.md b/README.md index 0e78340d..1f1cb960 100644 --- a/README.md +++ b/README.md @@ -1,398 +1,135 @@ -# Data Lovers +# Data Lovers: Pokémon Lab Go ## Índice * [1. Preámbulo](#1-preámbulo) -* [2. Resumen del proyecto](#2-resumen-del-proyecto) -* [3. Objetivos de aprendizaje](#3-objetivos-de-aprendizaje) -* [4. Consideraciones generales](#4-consideraciones-generales) -* [5. Criterios de aceptación mínimos del proyecto](#5-criterios-de-aceptación-mínimos-del-proyecto) -* [6. Hacker edition](#6-hacker-edition) -* [7. Consideraciones técnicas](#7-consideraciones-técnicas) -* [8. Pistas, tips y lecturas complementarias](#8-pistas-tips-y-lecturas-complementarias) -* [9. Checklist para solicitar PF](#9-checklist-para-solicitar-pf) +* [2. Definición del proyecto](#2-definición-del-proyecto) +* [3. Consideraciones generales](#3-consideraciones-generales) +* [4. Tecnologías Utilizadas](#4-tecnologías-utilizadas) +* [5. Flujo de trabajo](#5-flujo-de-trabajo) +* [6. Estructura de archivos](#6-estructura-de-archivos) +* [7. Pruebas unitarias](#7-pruebas-unitarias) +* [8. Interfaz desplegada](#8-interfaz-desplegada) +* [9. Desarrolladoras ](#9-desarrolladoras) *** ## 1. Preámbulo -Según [Forbes](https://www.forbes.com/sites/bernardmarr/2018/05/21/how-much-data-do-we-create-every-day-the-mind-blowing-stats-everyone-should-read), -el 90% de la data que existe hoy ha sido creada durante los últimos dos años. -Cada día generamos 2.5 millones de terabytes de datos, una cifra sin -precedentes. +El objetivo de este proyecto es adquirir conocimientos en la manipulación de datos y ganar experiencia en el trabajo colaborativo a través de una situación y contexto ficticios. Nuestro objetivo es diseñar una interfaz interactiva que permita visualizar, filtrar y ordenar datos. -No obstante, los datos por sí mismos son de poca utilidad. Para que esas -grandes cantidades de datos se conviertan en **información** fácil de leer para -los usuarios, necesitamos entender y procesar estos datos. Una manera simple de -hacerlo es creando _interfaces_ y _visualizaciones_. +## 2. Definición del proyecto -En la siguiente imagen, podrás ver cómo con la data que que se ve en la parte -izquierda se puede construir una interfaz amigable y entendible por las -usuarias, al lado derecho. +Nuestro proyecto se llama **Pokémon Lab Go**, durante el proceso de diseño de la interfaz, deberemos tener en cuenta las necesidades y expectativas de nuestros usuarios. Comprender quiénes son nuestros usuarios y qué información desean visualizar y explorar. Con base en esta comprensión, crearemos una interfaz amigable y fácil de usar que satisfaga las necesidades de nuestros usuarios. -![pokemon-data-to-ui](https://user-images.githubusercontent.com/12631491/218505816-c6d11758-9de4-428f-affb-2a56ea4d68c4.png) +Al finalizar este proyecto, habremos adquirido habilidades en la manipulación de datos, el diseño de interfaces de usuario, el trabajo colaborativo en equipo y el desarrollo web utilizando _HTML, CSS_ y _JavaScript_. Estaremos preparados para enfrentar desafíos técnicos y brindar soluciones efectivas a problemas de visualización de datos con el uso de _Una single page application (SPA)_, es un tipo de aplicación web que carga una única página inicial desde el servidor y luego actualiza dinámicamente su contenido, mediante las interacciones del usuario, sin necesidad de cargar páginas adicionales del servidor. -## 2. Resumen del proyecto - -En este proyecto **construirás una _página web_ para visualizar un -_conjunto (set) de datos_** que se adecúe a lo que descubras que tu usuario -necesita. - -Como entregable final tendrás una página web que permita **visualizar la data, -filtrarla, ordenarla y hacer algún cálculo agregado**. Con cálculo agregado -nos referimos a distintos cálculos que puedes hacer con la data para mostrar -información aún más relevante para los usuarios (promedio, el valor máximo -o mínimo, etc). - -Esta vez te proponemos una serie de datos de diferentes _temáticas_ para que -explores y decidas con qué temática te interesa trabajar. Hemos elegido -específicamente estos sets de datos porque creemos que se adecúan bien a esta -etapa de tu aprendizaje. - -Una vez que definas tu área de interés, buscar entender quién es tu usuario -y qué necesita saber o ver exactamente; luego podrás construir la interfaz que -le ayude a interactuar y entender mejor esos datos. - -Estos son datos que te proponemos: +Para esto se nos proporciono los siguientes datos: * [Pokémon](src/data/pokemon/pokemon.json): - En este set encontrarás una lista con los 251 Pokémon de la región de Kanto - y Johto, junto con sus respectivas estadísticas usadas en el juego + En este set encontrarás una lista con los 251 Pokémon de la región de Kanto y Johto, junto con sus respectivas estadísticas usadas en el juego [Pokémon GO](http://pokemongolive.com). - [Investigación con jugadores de Pokémon Go](src/data/pokemon/README.md) -* [League of Legends - Challenger leaderboard](src/data/lol/lol.json): - Este set de datos muestra la lista de campeones en una liga del - juego League of Legends (LoL). - - [Investigación con jugadores de LoL](src/data/lol/README.md) - -* [Rick and Morty](src/data/rickandmorty/rickandmorty.json). - Este set nos proporciona la lista de los personajes de la serie Rick and - Morty. [API Rick and Morty](https://rickandmortyapi.com). - - [Investigación con seguidores de Rick and Morty](src/data/rickandmorty/README.md) - -* [Juegos Olímpicos de Río de Janeiro](src/data/athletes/athletes.json). - Este set nos proporciona la lista de los atletas que ganaron medallas en las - olímpiadas de Río de Janeiro. - - [Investigación con interesados en juegos olímpicos de Río de Janeiro](src/data/athletes/README.md) - -* [Studio Ghibli](src/data/ghibli/ghibli.json). - En este set encontrarás una lista de las animaciones y sus personajes del - [Studio Ghibli](https://ghiblicollection.com/). - - [Investigación con seguidores de las animaciones del Studio Ghibli](src/data/ghibli/README.md) - -El objetivo principal de este proyecto es que aprendas a diseñar y construir una -interfaz web donde se pueda visualizar y manipular data, entendiendo lo que el -usuario necesita. - -## 3. Objetivos de aprendizaje - -Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en tu proyecto. Piensa en eso al decidir tu estrategia de trabajo. - -### HTML - -- [ ] **Uso de HTML semántico** - -
Links

- - * [HTML semántico](https://curriculum.laboratoria.la/es/topics/html/02-html5/02-semantic-html) - * [Semantics - MDN Web Docs Glossary](https://developer.mozilla.org/en-US/docs/Glossary/Semantics#Semantics_in_HTML) -

- -### CSS - -- [ ] **Uso de selectores de CSS** - -
Links

- - * [Intro a CSS](https://curriculum.laboratoria.la/es/topics/css/01-css/01-intro-css) - * [CSS Selectors - MDN](https://developer.mozilla.org/es/docs/Web/CSS/CSS_Selectors) -

- -- [ ] **Modelo de caja (box model): borde, margen, padding** - -
Links

- - * [Box Model & Display](https://curriculum.laboratoria.la/es/topics/css/01-css/02-boxmodel-and-display) - * [The box model - MDN](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model) - * [Introduction to the CSS box model - MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model) - * [CSS display - MDN](https://developer.mozilla.org/pt-BR/docs/Web/CSS/display) - * [display - CSS Tricks](https://css-tricks.com/almanac/properties/d/display/) -

- -- [ ] **Uso de flexbox en CSS** - -
Links

- - * [A Complete Guide to Flexbox - CSS Tricks](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) - * [Flexbox Froggy](https://flexboxfroggy.com/#es) - * [Flexbox - MDN](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox) -

- -### Web APIs - -- [ ] **Uso de selectores del DOM** - -
Links

- - * [Manipulación del DOM](https://curriculum.laboratoria.la/es/topics/browser/02-dom/03-1-dom-methods-selection) - * [Introducción al DOM - MDN](https://developer.mozilla.org/es/docs/Web/API/Document_Object_Model/Introduction) - * [Localizando elementos DOM usando selectores - MDN](https://developer.mozilla.org/es/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors) -

- -- [ ] **Manejo de eventos del DOM (listeners, propagación, delegación)** - -
Links

- - * [Introducción a eventos - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/Events) - * [EventTarget.addEventListener() - MDN](https://developer.mozilla.org/es/docs/Web/API/EventTarget/addEventListener) - * [EventTarget.removeEventListener() - MDN](https://developer.mozilla.org/es/docs/Web/API/EventTarget/removeEventListener) - * [El objeto Event](https://developer.mozilla.org/es/docs/Web/API/Event) -

- -- [ ] **Manipulación dinámica del DOM** - -
Links

- - * [Introducción al DOM](https://developer.mozilla.org/es/docs/Web/API/Document_Object_Model/Introduction) - * [Node.appendChild() - MDN](https://developer.mozilla.org/es/docs/Web/API/Node/appendChild) - * [Document.createElement() - MDN](https://developer.mozilla.org/es/docs/Web/API/Document/createElement) - * [Document.createTextNode()](https://developer.mozilla.org/es/docs/Web/API/Document/createTextNode) - * [Element.innerHTML - MDN](https://developer.mozilla.org/es/docs/Web/API/Element/innerHTML) - * [Node.textContent - MDN](https://developer.mozilla.org/es/docs/Web/API/Node/textContent) -

- -### JavaScript - -- [ ] **Diferenciar entre tipos de datos primitivos y no primitivos** - -- [ ] **Arrays (arreglos)** - -
Links

- - * [Arreglos](https://curriculum.laboratoria.la/es/topics/javascript/04-arrays) - * [Array - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/) - * [Array.prototype.sort() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) - * [Array.prototype.forEach() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) - * [Array.prototype.map() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map) - * [Array.prototype.filter() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) - * [Array.prototype.reduce() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) -

- -- [ ] **Objetos (key, value)** - -
Links

- - * [Objetos en JavaScript](https://curriculum.laboratoria.la/es/topics/javascript/05-objects/01-objects) -

- -- [ ] **Variables (declaración, asignación, ámbito)** - -
Links

- - * [Valores, tipos de datos y operadores](https://curriculum.laboratoria.la/es/topics/javascript/01-basics/01-values-variables-and-types) - * [Variables](https://curriculum.laboratoria.la/es/topics/javascript/01-basics/02-variables) -

- -- [ ] **Uso de condicionales (if-else, switch, operador ternario, lógica booleana)** +## 3. Consideraciones Generales -
Links

+* Este proyecto se desarrollo en duplas +* El rango de tiempo estimado para completar el proyecto fue de 3 a 4 Sprints. +* El proyecto fue entregado subiendo nuestro código a **GitHub** _(commit/push)_ y la interfaz fue desplegada usando **GitHub Pages**. +* El proyecto debe estar implementada completamente en _JavaScript (ES6), HTML y CSS_. (Sin hacer uso de librerias). - * [Estructuras condicionales y repetitivas](https://curriculum.laboratoria.la/es/topics/javascript/02-flow-control/01-conditionals-and-loops) - * [Tomando decisiones en tu código — condicionales - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/conditionals) -

+## 4. Tecnologías utilizadas -- [ ] **Uso de bucles/ciclos (while, for, for..of)** +**Trello**: Es una plataforma de gestión de proyectos y organización colaborativa basada en tableros. Permitendo crear listas, tarjetas para visualizar y organizar tareas del proyecto. -
Links

+**Figma**: Es una herramienta de diseño de interfaces de usuario, que permite crear, colaborar y prototipar diseños de manera eficiente y efectiva. - * [Bucles (Loops)](https://curriculum.laboratoria.la/es/topics/javascript/02-flow-control/02-loops) - * [Bucles e iteración - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Loops_and_iteration) -

+**HTML**: Es un lenguaje utilizado para estructurar y presentar contenido en la web, proporcionando elementos y etiquetas para crear y dar la estructura de una página. -- [ ] **Funciones (params, args, return)** +**JavaScript**: Es un lenguaje de programación que se utiliza para agregar interactividad y funcionalidad a las páginas web, permitiendo crear efectos dinámicos, manipular datos y responder a las acciones del usuario. -
Links

+**CSS**: Es un lenguaje de estilo utilizado para definir la presentación y apariencia visual de una página web, permitiendo controlar el diseño, el formato y los estilos de los elementos en el _HTML_. Y con su caracteristica de _@media queries_ podemos adapatar el diseño y estilo en función del tipo de dispositivo que el usuario estime para visualizar la página. - * [Funciones (control de flujo)](https://curriculum.laboratoria.la/es/topics/javascript/02-flow-control/03-functions) - * [Funciones clásicas](https://curriculum.laboratoria.la/es/topics/javascript/03-functions/01-classic) - * [Arrow Functions](https://curriculum.laboratoria.la/es/topics/javascript/03-functions/02-arrow) - * [Funciones — bloques de código reutilizables - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/Functions) -

+**Git**: Es un sistema de control de versiones que facilita el seguimiento de los cambios en el código fuente, permitiendo gestionar y controlar las distintas versiones del proyecto, facilitando el trabajo colaborativo y la gestión de ramas y fusiones. -- [ ] **Pruebas unitarias (unit tests)** +**GitHub**: Es una plataforma online basada en _Git_ que ofrece alojamiento de repositorios remotos y herramientas colaborativas, permitiendo compartir, colaborar y gestionar proyectos de forma más sencilla -
Links

+**Github Pages**: Permite a los usuarios de _GitHub_ crear y compartir sitios web públicos para proyectos, documentación, portafolios, etc. - * [Empezando con Jest - Documentación oficial](https://jestjs.io/docs/es-ES/getting-started) -

+**Jest**: Es un framework de pruebas unitarias de _JavaScript_, permite realizar afirmaciones y crear casos de prueba para verificar si el código se comporta como se espera. -- [ ] **Módulos de ECMAScript (ES Modules)** +## 5. Flujo de trabajo -
Links

+Para establecer un flujo de trabajo eficiente, comenzamos organizando nuestro espacio en **Trello**. Segmentamos todas las tareas requeridas en el proyecto, los objetivos de aprendizaje, las historias de usuario y los prototipos de baja y alta fidelidad. Progresivamente, profundizamos en cada uno de ellos, dividiéndolos en categorías como _"Sprint Backlog"_ (por hacer en la semana), _"En proceso"_ y _"Hecho"_. También creamos una tarjeta para los bloqueos con el fin de mantener un desarrollo de proyecto ordenado y estructurado. Este enfoque nos permitió tener una visión clara de las tareas pendientes y su progreso, lo que contribuyó a un desarrollo efectivo del proyecto. - * [import - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/import) - * [export - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/export) -

+### Perfil del usuario -- [ ] **Uso de linter (ESLINT)** +Nuestro producto **"Pokémon Lab Go"** está dirigido a niños, jóvenes y adultos con intereses relacionados con [_"Pokémon"_](https://es.wikipedia.org/wiki/Pok%C3%A9mon) y sus derivados como [_"Pokémon Go"_](https://pokemongolive.com/?hl=es), [_"Pokémon Go Plus+"_](https://www.pokemongoplusplus.com/es-ES/), [_"Pokémon sleep"_](https://www.pokemonsleep.net/es-ES/). -- [ ] **Uso de identificadores descriptivos (Nomenclatura y Semántica)** +Para ello, tenemos a disposicion información relevante para formar nuestras historias de usuario. -- [ ] **Diferenciar entre expresiones (expressions) y sentencias (statements)** +### Historia de usuario 1 -### Control de Versiones (Git y GitHub) +objetivo Visualizar Data -- [ ] **Git: Instalación y configuración** +### Historia de usuario 2 +objetivo Mostrar Ranking de Aparición de Pokémon -- [ ] **Git: Control de versiones con git (init, clone, add, commit, status, push, pull, remote)** - -- [ ] **Git: Integración de cambios entre ramas (branch, checkout, fetch, merge, reset, rebase, tag)** - -- [ ] **GitHub: Creación de cuenta y repos, configuración de llaves SSH** - -- [ ] **GitHub: Despliegue con GitHub Pages** - -
Links

- - * [Sitio oficial de GitHub Pages](https://pages.github.com/) -

- -- [ ] **GitHub: Colaboración en Github (branches | forks | pull requests | code review | tags)** - -### Centrado en el usuario - -- [ ] **Diseñar y desarrollar un producto o servicio poniendo a las usuarias en el centro** - -### Diseño de producto - -- [ ] **Crear prototipos de alta fidelidad que incluyan interacciones** - -- [ ] **Seguir los principios básicos de diseño visual** - -### Investigación - -- [ ] **Planear y ejecutar testeos de usabilidad de prototipos en distintos niveles de fidelidad** - -
Links

- - * [Intro a testeos usabilidad](https://coda.io/@bootcamp-laboratoria/contenido-ux/test-de-usabilidad-15) - * [Pruebas con Usuarios 1 — ¿Qué, cuándo y para qué testeamos?](https://eugeniacasabona.medium.com/pruebas-con-usuarios-1-qu%C3%A9-cu%C3%A1ndo-y-para-qu%C3%A9-testeamos-7c3a89b4b5e7) -

- -## 4. Consideraciones generales - -* Este proyecto se debe resolver en duplas. -* El rango de tiempo estimado para completar el proyecto es de 3 a 4 Sprints. -* El proyecto será entregado subiendo tu código a GitHub (commit/push) y la - interfaz será desplegada usando [GitHub Pages](https://pages.github.com/). - -## 5. Criterios de aceptación mínimos del proyecto - -Los criterios para considerar que has completado este proyecto son: - -### Definición del producto - -Documenta brevemente tu trabajo en el archivo `README.md` de tu repositorio, -contándonos cómo fue tu proceso de diseño y cómo crees que el producto resuelve -el problema (o problemas) que tiene tu usuario. - -### Historias de usuario - -Una vez que entiendas las necesidades de tus usuarios, escribe las [Historias -de Usuario](https://es.wikipedia.org/wiki/Historias_de_usuario) que representen -todo lo que el usuario necesita hacer/ver. Las **Historias de Usuario** deben -ser el resultado de tu proceso de investigación o _research_ de tus usuarios. - -Asegúrate de incluir la definición de terminado (_definition of done_) y los -Criterios de Aceptación para cada una. - -En la medida de lo posible, termina una historia de usuario antes de pasar -a la siguiente (Cumple con Definición de Terminado + Criterios de Aceptación). +### Historia de usuario 3 +objetivo Filtrar Pokémon ### Diseño de la Interfaz de Usuario - #### Prototipo de baja fidelidad -Durante tu trabajo deberás haber hecho e iterado bocetos (_sketches_) de tu -solución usando papel y lápiz. Te recomendamos tomar fotos de todas las -iteraciones que hagas, que las subas a tu repositorio y las menciones en tu -`README.md`. - -#### Prototipo de alta fidelidad - -Lo siguiente es diseñar tu Interfaz de Usuario (UI por sus siglas en inglés - -_User Interface_). Para eso debes aprender a utilizar alguna herramienta de -diseño visual. Nosotros te recomendamos [Figma](https://www.figma.com/) que es -una herramienta que funciona en el navegador y, además, puedes crear una cuenta -gratis. Sin embargo, eres libre de utilizar otros editores gráficos como -Illustrator, Photoshop, PowerPoint, Keynote, etc. +En cuanto al diseño de la página, lo primero después de definir el tema a trabajar fue desarrollar un prototipo de baja fidelidad. Para ello realizamos inicialmente bocetos en papel que llevamos posteriormente a _Figma_. -El diseño debe representar el _ideal_ de tu solución. Digamos que es lo que -desearías implementar si tuvieras tiempo ilimitado para trabajar. Además, tu -diseño debe seguir los fundamentos de _visual design_. +##### _Boceto en papel_: +Boceto de la página -#### Testeos de usabilidad +##### _Prototipo en Figma_: +Prototipo de baja pag inicial +Prototipo de baja open menu +Prototipo de baja open modal -Durante el reto deberás hacer _tests_ de usabilidad con distintos usuarios, y -en base a los resultados, deberás iterar tus diseños. Cuéntanos -qué problemas de usabilidad detectaste a través de los _tests_ y cómo los -mejoraste en tu propuesta final. +#### Prototipo de alta fidelidad -### Implementación de la Interfaz de Usuario (HTML/CSS/JS) +Tras las primeras iteraciones realizamos el prototipo de alta fidelidad en la cual definimos una paleta de colores inicial, priorizado que fuesen iconicas de _"Pokémon"_. -Luego de diseñar tu interfaz de usuario deberás trabajar en su implementación. -**No** es necesario que construyas la interfaz exactamente como la diseñaste. -Tu tiempo de hacking es escaso, así que deberás priorizar +Paleta de colores -Como mínimo, tu implementación debe: +##### _Prototipo en Figma_: +Prototipo de alta pag inicial +Prototipo de alta menu type +Prototipo de alta sub menu +Prototipo de alta open type +Prototipo de alta open modal -1. Mostrar la data en una interfaz: puede ser un card, una tabla, una lista, - etc. -2. Permitir al usuario interactuar para obtener la infomación que necesita. -3. Ser _responsive_, es decir, debe visualizarse sin problemas desde distintos - tamaños de pantallas: móviles, tablets y desktops. -4. Que la interfaz siga los fundamentos de _visual design_. +#### Testeos de usabilidad -### Pruebas unitarias +Durante los testos de usabilidad se nos da el feedback de modificar las **_“CATEGORIAS”_** y los _sub-menus_ desglosarlos en el _nav_, y que solo **_tipos_** tenga la posibilidad de desplegar, ya que formaba mucho _ruido visual_. -El _boilerplate_ de este proyecto no incluye Pruebas Unitarias (_tests_), así es -que tendrás que escribirlas tú para las funciones encargadas de _procesar_, -_filtrar_ y _ordenar_ la data, así como _calcular_ estadísticas. +Y tras las modificaciones correspondientes quedo así: -Tus _pruebas unitarias_ deben dar una cobertura del 70% de _statements_ -(_sentencias_), _functions_ (_funciones_), _lines_ (_líneas_), y _branches_ -(_ramas_) del archivo `src/data.js` que contenga tus funciones y está detallado -en la sección de [Consideraciones técnicas](#srcdatajs). +Prototipo de alta post feedback +Prototipo de alta post feedback -## 6. Hacker edition +Para interactuar con los últimas cambios realizados en **Figma** de nuestro prototipo de alta fidelidad [haz click aqui](https://www.figma.com/proto/pidKRNIkKzxTi7C86XmXJc/Prototipo-alta-DL?type=design&node-id=1-5&t=hoRF5R4XbQ2Csy5X-0&scaling=scale-down&page-id=0%3A1&starting-point-node-id=1%3A5) -Las secciones llamadas _Hacker Edition_ son **opcionales**. Si **terminaste** -con todo lo anterior y te queda tiempo, intenta completarlas. Así podrás -profundizar y/o ejercitar más sobre los objetivos de aprendizaje del proyecto. +Prototipo de alta pag inicial +Prototipo de alta menu°/tipo +Prototipo de alta tipos +Prototipo de alta modal -Features/características extra sugeridas: +Para realizar la búsqueda por nombre de nuestro prototipo en **Figma** -* En lugar de consumir la data estática brindada en este repositorio, puedes - consumir la data de forma dinámica, cargando un archivo JSON por medio de - `fetch`. La carpeta `src/data` contiene una versión `.js` y una `.json` de - de cada set datos. -* Agregarle a tu interfaz de usuario implementada visualizaciones gráficas. Para - ello te recomendamos explorar librerías de gráficas como - [Chart.js](https://www.chartjs.org/) - o [Google Charts](https://developers.google.com/chart/). -* 100% Coverage +Prototipo de alta buscador +Prototipo de alta buscador por nombre Pikachu +Prototipo de alta modal pikachu -## 7. Consideraciones técnicas -La lógica del proyecto debe estar implementada completamente en JavaScript -(ES6), HTML y CSS. En este proyecto NO está permitido usar librerías o -frameworks, solo [vanilla JavaScript](https://medium.com/laboratoria-how-to/vanillajs-vs-jquery-31e623bbd46e), -con la excepción de librerías para hacer gráficas (charts); ver -[_Parte opcional_](#6-hacker-edition) más arriba. +## 6. Estructura de archivos -El _boilerplate_ contiene una estructura de archivos como punto de partida así -como toda la configuración de dependencias: +El proyecto está organizado de la siguiente manera: ```text . @@ -400,226 +137,71 @@ como toda la configuración de dependencias: ├── README.md ├── package.json ├── src -| ├── data (según con qué data trabajes) -| | ├── lol -| | | ├── lol.js -| | | ├── lol.json -| | | └── README.md +| ├── assets +| ├── data | | ├── pokemon | | | ├── pokemon.js | | | ├── pokemon.json | | | └── README.md -| | └── rickandmorty -| | | ├── rickandmorty.js -| | | ├── rickandmorty.json -| | | └── README.md -| | └── athletes -| | | ├── athletes.js -| | | ├── athletes.json -| | | └── README.md -| | └── ghibli -| | | ├── ghibli.js -| | | ├── ghibli.json -| | | └── README.md +| ├── img | ├── data.js | ├── index.html | ├── main.js +| └── query.css | └── style.css └── test └── data.spec.js - -directory: 7 file: 20 ``` -### `src/index.html` +### `src/assets`: Contiene las imágenes correspondientes a los icon de cada tipo de Pokémon. -Como en el proyecto anterior, existe un archivo `index.html`. Como ya sabes, -acá va la página que se mostrará al usuario. También nos sirve para indicar -qué scripts se usarán y unir todo lo que hemos hecho. +### `src/data/pokemon`: En este set se encuentra una lista con los 251 Pokémon de la región de Kanto y Johto, junto con sus respectivas estadísticas usadas en el juego. -### `src/main.js` +### `src/img`: Contiene las imágenes utilizadas tanto en la página, como las utilizadas en este Readme. -Recomendamos usar `src/main.js` para todo tu código que tenga que ver con -mostrar los datos en la pantalla. Con esto nos referimos básicamente a la -interacción con el DOM. Operaciones como creación de nodos, registro de -manejadores de eventos (_event listeners_ o _event handlers_), .... +### `src/data.js`: Contiene un objeto llamado _"funcionesPokemon"_ que contiene varias funciones relacionadas con la manipulación y filtrado de datos de Pokémon. La cual se exporta al final del código utilizando export default, lo que permite que estas funciones estén disponibles para su uso en otros archivos que importen este módulo. +### `src/index.html`: Proporciona la estructura, los estilos, los recursos y la funcionalidad necesarios para construir una página web completa y efectiva. -Esta no es la única forma de dividir tu código, puedes usar más archivos y -carpetas, siempre y cuando la estructura sea clara para tus compañeras. +### `src/main.js`: Se importa las funciones de _'data.js'_ y crea una página web interactiva que muestra información de los Pokémon, en _"cards"_ que permiten que se abra una modal y proporciona opciones de búsqueda y ordenamiento, y muestra un ranking basado en la probabilidad de aparición de los Pokémon. -En este archivo encontrarás una serie de _imports_ _comentados_. Para _cargar_ -las diferentes fuentes de datos tendrás que _descomentar_ la línea -correspondiente. +### `src/style.css`: Este archivo contiene los estilos CSS del sitio web, aplicados para darle una apariencia visual atractiva. -Por ejemplo, si "descomentamos" la siguiente línea: +### `src/query.css`: Aquí se aplican todos los _@media query_, para que el diseño de la página sea responsivo y amigable para los usuarios en una diversa gama de dispositivos. -```js -// import data from './data/lol/lol.js'; -``` +### `test/data.spect.js`: Este es un archivo de pruebas (test) escrito en _Jest_ para garantizar que las funciones del módulo _"funcionesPokemon"_ se comporten correctamente y produzcan los resultados deseados` -La línea quedaría así: +## 7. Pruebas unitarias -```js -import data from './data/lol/lol.js'; -``` +Estos test contribuyen al mantenimiento y la calidad del código, permiten detectar rápidamente problemas que puedan surgir tras cambios en el código. + +test aprobados + +## 8. Interfaz desplegada +### Versión escritorio +Esta es la interfaz final de la aplicación web en la vista de escritorio. + +pag inicial + ranki + filtro +all pokemon +search +orden z-a + + +### Versión tableta +Esta es la interfaz final de la aplicación web en la vista de tableta equivalente a _720 px_. +pag inicial + ranki + filtro +### Versión móvil +Esta es la interfaz final de la aplicación web en la vista de movil equivalente a _480 px_. +pag inicial + ranki + filtro + +## 9. Desarrolladoras + +* [Nancy A. Mendoza _(MX)_](https://github.com/nancyale24/) -Y ahora tendríamos la variable `data` disponible en el script `src/main.js`. +* [Paulina Torres A. _(CL)_](https://github.com/Paulytorres/) -### `src/data.js` - -El corazón de este proyecto es la manipulación de datos a través de arreglos -y objetos. - -Te recomendamos que este archivo contenga toda la funcionalidad que corresponda -a obtener, procesar y manipular datos (tus funciones). Por ejemplo: - -* `filterData(data, condition)`: esta función `filter` o filtrar recibiría la - data, y nos retornaría aquellos datos que sí cumplan con la condición. - -* `sortData(data, sortBy, sortOrder)`: esta función `sort` u ordenar - recibe tres parámetros. - El primer parámetro, `data`, nos entrega los datos. - El segundo parámetro, `sortBy`, nos dice con respecto a cuál de los campos de - la data se quiere ordenar. - El tercer parámetro, `sortOrder`, indica si se quiere ordenar de manera - ascendente o descendente. - -* `computeStats(data)`: la función `compute` o calcular, nos permitirá hacer - cálculos estadísticos básicos para ser mostrados de acuerdo a la data - proporcionada. - -Estos nombres de funciones y de parámetros son solamente referenciales, lo que -decidas depende de tu propia implementación. - -Estas funciones deben ser [_puras_](https://medium.com/laboratoria-developers/introducci%C3%B3n-a-la-programaci%C3%B3n-funcional-en-javascript-parte-2-funciones-puras-b99e08c2895d) -e independientes del DOM. Estas funciones serán después usadas desde el archivo -`src/main.js`, al cargar la página, y cada vez que el usuario interactúe (click, -filtrado, ordenado, ...). - -### `src/data` - -En esta carpeta están los datos de las diferentes fuentes. Encontrarás una -carpeta por cada fuente, y dentro de cada carpeta dos archivos: uno con la -extensión `.js` y otro `.json`. Ambos archivos contienen la misma data; la -diferencia es que el `.js` lo usaremos a través de una etiqueta ` - - + + + + + Data Lovers + + + + + + + + + +
+ + a - z + a - z +
+ + + +
+ + \ No newline at end of file diff --git a/src/main.js b/src/main.js index 71c59f2d..d692f46a 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,402 @@ -import { example } from './data.js'; -// import data from './data/lol/lol.js'; +import funcionesPokemon from './data.js'; + +//importa un objeto llamado data desde el archivo pokemon.js ubicado en el directorio ./data/pokemon/ +// El objeto data contendrá información sobre los Pokémon. import data from './data/pokemon/pokemon.js'; -// import data from './data/rickandmorty/rickandmorty.js'; -console.log(example, data); + + +const tiposUnicos = data.pokemon.filter(pokemon => pokemon.type).flatMap(pokemon => pokemon.type).filter((type, index, self) => self.indexOf(type) === index); + +const subMenu = tiposUnicos.map(tipo => ({ + type: tipo, + img: `./assets/${tipo.toLowerCase()}.svg`, + href: '#' +})); + +const menu = { + "menu": [ + { + "title": "HOME", + "class": "menu__link", + "href": "index.html" + }, + { + "title": "All Pokémon", + "class": "menu__link", + "href": "#" + + }, + { + "title": "TYPE", + "class": "menu__item menu__item--show", + "href": "#", + "subMenu": subMenu + }, + { + "title": "Top Spawn Chance", + "class": "menu__link", + "href": "#ranking-section" + } + ] +} + +const body = document.querySelector('body'); +const tagFirst = body.firstChild; + +const header = document.createElement('header'); +header.classList.add("header", "item"); +const nav = document.createElement('nav'); +nav.classList.add("menu"); +const section = document.createElement('section'); +section.classList.add("menu__container"); + +const logo = document.createElement('img'); +logo.src = "./img/logopokemon.png"; +logo.classList.add("logo"); +logo.width = 180; +logo.height = 80; +logo.alt = "Logo Pokémon Lab Go"; + + + +const ul = document.createElement('ul'); +ul.classList.add("menu__links"); + +menu.menu.forEach((opciones) => { + const liTitle = document.createElement('li'); + liTitle.classList.add(...opciones.class.split(' ')); + + const aTitle = document.createElement('a'); + aTitle.classList.add("menu__link"); + aTitle.href = opciones.href; + aTitle.innerHTML = opciones.title; + + + if (opciones.subMenu) { + const ulSubMenu = document.createElement('ul'); + ulSubMenu.classList.add("menu__nesting", 'menu__nesting--columns'); + + opciones.subMenu.forEach((submenu) => { + const liSubMenu = document.createElement('li'); + liSubMenu.classList.add("menu__inside"); + + const aTitleSub = document.createElement('a'); + aTitleSub.classList.add("menu__link", "menu__link--inside"); + aTitleSub.href = submenu.href; + + const spanSpace = document.createElement('span'); + spanSpace.innerHTML = ' '; + + const spanName = document.createElement('span'); + spanName.textContent = submenu.type; + aTitleSub.append(spanSpace, spanName); + + const img = document.createElement('img'); + img.src = submenu.img; + aTitleSub.insertBefore(img, aTitleSub.firstChild); + + //--------------- evento que al dar click en type pokemon llamara a la funcion displayPokemonByType + aTitleSub.addEventListener('click', () => { + const selectedType = submenu.type; + const filteredPokemon = funcionesPokemon.displayPokemonByType(data.pokemon, selectedType); + displayPokemon(filteredPokemon) + }); + + liSubMenu.appendChild(aTitleSub); + ulSubMenu.appendChild(liSubMenu) + }); + + liTitle.appendChild(ulSubMenu); + } + if (opciones.title === "All Pokémon") { + aTitle.addEventListener('click', () => displayPokemon(data.pokemon, null)); + } + + liTitle.appendChild(aTitle); + ul.appendChild(liTitle); + +}); + +const search = document.createElement('input') +search.setAttribute("type", "text"); +search.classList.add("buscarPokemon"); +search.placeholder = "Search Pokémon for name or num"; + + +const orderaz = document.querySelector(".az"); +const orderza = document.querySelector(".za"); + +section.append(logo, ul, search, orderaz, orderza); +nav.appendChild(section); +header.appendChild(nav) + +body.insertBefore(header, tagFirst); + +//// FIN MENU //// + +// Muestra data Random de Pokemon // +const randomPokemon = data.pokemon.slice().sort(() => 0.5 - Math.random()).slice(0, 5); + + +//busca y devuelve el primer elemento con el id root. +const root = document.getElementById("root"); + + + +const displayPokemon = (dataPokemon, filter) => { + root.innerHTML = ''; + if (filter) { + dataPokemon = dataPokemon.filter(pokemon => pokemon.type && pokemon.type.includes(filter)); + } + + + + dataPokemon.forEach((pokemon) => { + + const type = pokemon.type; + const card = document.createElement("div"); + card.classList.add("card"); + if (type.length > 1) { + const color1 = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[0]); + const color2 = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[1]); + card.style.background = "linear-gradient(to right, " + color1 + " 30%, " + color2 + ")"; + } + else { + const color = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[0]); + card.style.background = color; + } + + const imgContainer = document.createElement("div"); + imgContainer.classList.add("img-container"); + + + const imgPokemon = document.createElement("img"); + imgPokemon.src = pokemon.img; + imgContainer.appendChild(imgPokemon); + + const infoContainer = document.createElement("div"); + infoContainer.classList.add("info-container"); + + const numPokemon = document.createElement("p"); + + numPokemon.textContent = `N.º ${pokemon.num}`; + infoContainer.appendChild(numPokemon); + numPokemon.classList.add("numPokemon"); + + const namePokemon = document.createElement("h1"); + namePokemon.textContent = pokemon.name; + infoContainer.appendChild(namePokemon); + + const typePokemon = document.createElement("p"); + typePokemon.textContent = `Type: ${pokemon.type.join(", ")}`; + infoContainer.appendChild(typePokemon); + + + card.append(infoContainer, imgContainer); + root.appendChild(card); + + ////// M O D A L P O K E M O N ///////// + //abrir modal + card.addEventListener('click', () => { + + const modal = document.createElement("div"); + modal.classList.add("modalPokemon"); + modal.style.display = 'block'; + if (type.length > 1) { + const color1 = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[0]); + const color2 = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[1]); + modal.style.background = "linear-gradient(to right, " + color1 + " 30%, " + color2 + ")"; + } + else { + const color = getComputedStyle(document.documentElement).getPropertyValue('--pokemon-type-' + type[0]); + modal.style.background = color; + } + + const modalContent = document.createElement("div"); + modalContent.classList.add("modal-content"); + + const pokemonId = document.createElement("div"); + pokemonId.classList.add("IdPokemon"); + pokemonId.textContent = `N.º ${pokemon.num}`; + modalContent.appendChild(pokemonId); + + const pokemonName = document.createElement("div"); + pokemonName.classList.add("PokemonName"); + pokemonName.textContent = pokemon.name.toUpperCase(); + modalContent.appendChild(pokemonName); + + const imgPokemonModal = document.createElement("div"); + imgPokemonModal.classList.add("imgPokemonModal"); + const imgPokemonMod = document.createElement("img"); + imgPokemonMod.src = pokemon.img; + imgPokemonModal.appendChild(imgPokemonMod); + + const datosPoke = document.createElement("div"); + datosPoke.classList.add("datosPoke"); + + const typeModal = document.createElement("div"); + typeModal.classList.add("typeModal"); + typeModal.innerHTML = `Type: ${pokemon.type}
`; + datosPoke.appendChild(typeModal); + + const resistantModal = document.createElement("div"); + resistantModal.innerHTML = `Resistant: ${pokemon.resistant.join(", ")}`; + datosPoke.appendChild(resistantModal); + + const weaknessesModal = document.createElement("div"); + weaknessesModal.textContent = `Weaknesses: ${pokemon.weaknesses.join(", ")}`; + datosPoke.appendChild(weaknessesModal); + + const quickMoveModal = document.createElement("div"); + const quickMove = pokemon["quick-move"]; + const quickData = []; + for (let i = 0; i < quickMove.length; i++) { + quickData.push(quickMove[i].name); + } + quickMoveModal.textContent = `Quick Move: ${quickData.join(", ")}`; + datosPoke.appendChild(quickMoveModal); + + const attack = document.createElement("div"); + const specialAttackData = pokemon["special-attack"]; + const attackName = []; + for (let i = 0; i < specialAttackData.length; i++) { + attackName.push(specialAttackData[i].name) + } + attack.textContent = `Special Attack: ${attackName.join(", ")}`; + datosPoke.appendChild(attack) + + const imgEgg = document.createElement("img"); + imgEgg.src = "./assets/egg.svg"; + imgEgg.alt = "Eggs"; + + const eggs = document.createElement("p"); + eggs.innerHTML = pokemon.egg; + eggs.insertBefore(imgEgg, eggs.firstChild); + datosPoke.appendChild(eggs); + + + + //cerar modal + const close = document.createElement("span"); + close.classList.add("close"); + close.textContent = "X"; + + close.addEventListener('click', () => { + modal.style.display = 'none'; + }); + + modal.appendChild(close); + modalContent.append(pokemonId, pokemonName, imgPokemonModal, datosPoke); + modal.appendChild(modalContent); + root.appendChild(modal); + }); + }); + +} + +displayPokemon(randomPokemon); + +/// ordena data +orderaz.addEventListener('click', () => { + const pokemonOrdenadosAz = funcionesPokemon.orderPokemonAz(data.pokemon); + displayPokemon(pokemonOrdenadosAz); +}); +orderza.addEventListener('click', () => { + const pokemonOrdenadosZa = funcionesPokemon.orderPokemonZa(data.pokemon); + displayPokemon(pokemonOrdenadosZa); +}); + + +////////// B U S C A D O R P O K E M O N //////// +search.addEventListener('input', () => { + + //esta línea de código obtiene el valor del campo de entrada de texto representado por buscarPokemon, lo convierte a minúsculas utilizando .toLowerCase(), y lo almacena en la constante inputText. + const inputText = search.value.toLowerCase(); //es un método que se utiliza en las cadenas de texto en JavaScript para convertir todos los caracteres de la cadena a minúsculas. + + + const result = funcionesPokemon.searchPokemon(data.pokemon, inputText); + if (inputText.length > 0 && result.length > 0) { + displayPokemon(result); + } else if (inputText.length > 0 && result.length === 0) { + root.innerHTML = ''; + root.textContent = 'Pokemon not found :('; + } else { + displayPokemon(data.pokemon); + } +}); + +///////// Section RANKING de aparicion ///// +const sectionRanking = document.createElement('section'); +sectionRanking.setAttribute("id", "ranking-section"); +sectionRanking.classList.add('sectionRanking'); + +const picture = document.createElement('img'); +picture.classList.add('picture'); +picture.src = './img/ladyRanking.png'; +picture.width = 460; +picture.height = 600; + +const ranking = document.createElement('div'); +ranking.classList.add('ranking'); + +const table = document.createElement('table'); +//primera fila +const thead = document.createElement('thead'); +const headerRow = document.createElement('tr'); + +const positionHeader = document.createElement('th'); +positionHeader.textContent = '# Position'; + +const pokemonHeader = document.createElement('th'); +pokemonHeader.textContent = 'Pokémon'; + +const spawnChanceHeader = document.createElement('th'); +spawnChanceHeader.textContent = 'Spawn Chance'; + +headerRow.appendChild(positionHeader); +headerRow.appendChild(pokemonHeader); +headerRow.appendChild(spawnChanceHeader); +thead.appendChild(headerRow); + +const tbody = document.createElement('tbody'); + +const topPokemon = funcionesPokemon.getTopPokemon(data.pokemon); + +topPokemon.forEach((pokemon, index) => { + const rank = index + 1; + + const row = document.createElement('tr'); + + const position = document.createElement('td'); + position.textContent = `# ${rank}`; + + const pokemonImg = document.createElement('img'); + pokemonImg.src = pokemon.img; + pokemonImg.width = 50; + pokemonImg.height = 50; + + const pokemonName = document.createElement('td'); + pokemonName.textContent = pokemon.name; + + const spawnChance = document.createElement('td'); + spawnChance.textContent = pokemon['spawn-chance']; + + row.appendChild(position); + row.appendChild(pokemonImg); + row.appendChild(pokemonName); + row.appendChild(spawnChance); + + tbody.appendChild(row); +}); + +table.appendChild(thead); +table.appendChild(tbody); + +ranking.appendChild(table); + +sectionRanking.appendChild(picture); +sectionRanking.appendChild(ranking); + + +root.appendChild(sectionRanking); \ No newline at end of file diff --git a/src/query.css b/src/query.css new file mode 100644 index 00000000..46a9bc0b --- /dev/null +++ b/src/query.css @@ -0,0 +1,187 @@ +/*dispositivo movil*/ +@media only screen and (max-width:480px) { + + .divConteinerCards { + margin-top: 200px; + justify-content: center; + align-items: center; + align-content: center; + } + + +.header { + padding: 0; + margin: 0; + width: auto; + top: 0; + left: 0; + flex-direction: row; + align-items: center; + +} + + +.menu__container { + display: flex; + justify-content: space-between; + width: 100%; + max-width: 1200px; + height: 100%; + margin: 0 auto; + flex-direction: column; + flex-wrap: nowrap; + align-items: center; +} +.menu__link{ + padding: 0 10px; + font-size: 12px; +} + +.logo { + width: 80px; + height: 60px; +} + +.menu__links { + font-size: 9px; + padding: 5px; +} + +.menu__link--inside { + padding: 10px 20px 10px 20px; +} + +.menu__nesting--columns { + columns: 2; + column-gap: 2px; + align-items: center; +} +.az, .za{ + display: flex; + width: 20px; + height: 20px;} + +/*RANKIN SECTION*/ + +.sectionRanking{ + padding: 20px; + display: flex; + align-items: center; + text-align: center; + width: 100%; + flex-direction: column; + flex-wrap: wrap; + align-content: center; + justify-content: center; +} +.ranking table { + font-size: 12px; +} + +.ranking th, +.ranking td { + padding: 5px; +} + + +.picture{ + width: 260px; + height: 300px; +} + +.card { + width: 50%; + box-sizing: border-box; + padding: 10px; + display: inline-block; +} + +} + +/*tablet*/ +@media only screen and (min-width: 481px) and (max-width:767px) { + .menu__container { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + max-width: 1200px; + height: 100%; + margin: 0 auto; + flex-direction: column; + flex-wrap: wrap; + align-content: center; + gap: 10px; + } + + .logo{ + width: 160px; + height: 80px; + } + .menu__link--inside { + padding: 15px 25px 15px 25px; + } + + .menu__nesting--columns { + columns: 2; + column-gap: 2px; + align-items: center; + } + .divConteinerCards{ + margin: 300px 10px; + } + + .sectionRanking{ + padding: 150px 0; + display: flex; + align-items: center; + text-align: center; + width: 100%; + flex-direction: column; + flex-wrap: wrap; + align-content: center; + justify-content: center; + } + .ranking table { + font-size: 16px; + } + + .ranking th, + .ranking td { + padding: 5px; + } + + + .picture{ + width: 290px; + height: 420px; + } + + +} + +@media only screen and (min-width: 768px) and (max-width:1024px) +{ + .menu__link { + color: #fff; + text-decoration: none; + padding: 0 7px; + display: flex; + height: 100%; + align-items: center; + flex-direction: row; + } + + .menu__link--inside { + padding: 15px 25px 15px 25px; + } + .modalPokemon{ + height: 600px; + } + + .menu__nesting--columns { + columns: 3; + column-gap: 2px; + align-items: center; + } +} \ No newline at end of file diff --git a/src/style.css b/src/style.css index e69de29b..1cacca34 100644 --- a/src/style.css +++ b/src/style.css @@ -0,0 +1,326 @@ +:root { + + --theme-color: white; + --primary-color: #357CED; + --secundary-color: #FE0D0D; + --text-color: white; + --text-color-inverse: black; + --nav-shadow-color: #285FB6; + --nav-background: #357CED; + --pokemon-type-normal: #AAA67F; + --pokemon-type-fighting: #C12239; + --pokemon-type-flying: #A891EC; + --pokemon-type-ground: #DEC16B; + --pokemon-type-poison: #A43E9E; + --pokemon-type-rock: #B69E31; + --pokemon-type-bug: #A7B723; + --pokemon-type-ghost: #70559B; + --pokemon-type-steel: #B7B9D0; + --pokemon-type-fire: #F57D31; + --pokemon-type-water: #6493EB; + --pokemon-type-grass: #74CB48; + --pokemon-type-electric: #F9CF30; + --pokemon-type-psychic: #FB5584; + --pokemon-type-ice: #9AD6DF; + --pokemon-type-dragon: #7037FF; + --pokemon-type-dark: #75574C; + --pokemon-type-fairy: #E69EAC; + --pokemon-type-unknown: #526677; + --pokemon-type-shadow: #4F507B; + + +} + +* { + + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Roboto mono', 1em; + text-align: center; +} + + + +.header { + + + align-items: center; + justify-content: space-between; + padding: 1rem; + box-shadow: 0 4px 5px var(--nav-background); + + position: fixed; + top: 0; + right: 0; + width: 100%; + background: var(--nav-background); +} + +/* ////////// buscador //////////*/ + +.buscarPokemon { + width: 230px; + height: 40px; + border-radius: 8px; +} + +.menu { + margin: 0; + padding: 10px; +} +body{ + font-family: 'Electrolize', sans-serif; + font-family: 'Montserrat', sans-serif; + font-family: 'Roboto Mono', monospace; + padding-top: 60px; + position: relative; +} + + + + +/* //////// MENU ////////*/ + +.menu { + display: flex; + justify-content: space-between; + align-items: center; + width: 90%; + height: 100%; + margin: 0 auto; +} + + +.menu__container { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + max-width: 1200px; + height: 100%; + margin: 0 auto; + flex-direction: row; + flex-wrap: wrap; + align-content: center; +} + +.menu__links { + height: 100%; + transition: transform .5s; + display: flex; + justify-content: space-around; + left: 0; + top: 0; + +} + +.menu__item { + list-style: none; + position: relative; + height: 100%; + --clip: polygon(0 0, 100% 0, 100% 0, 0 0); + --transform: rotate(-90deg); +} + +.menu__item:hover { + --clip: polygon(0 0, 100% 0, 100% 100%, 0% 100%); + --transform: rotate(0); +} + +.menu__link { + color: #fff; + text-decoration: none; + padding: 0 20px; + display: flex; + height: 100%; + align-items: center; +} + +.menu__link:hover { + background-color: var(--pokemon-type-unknown); +} + +.menu__nesting { + list-style: none; + transition: clip-path .3s; + clip-path: var(--clip); + position: absolute; + right: 0; + bottom: 0; + width: max-content; + transform: translateY(100%); + background-color: var(--nav-background); +} + +.menu__nesting--columns { + columns: 3; + column-gap: 5px; + align-items: center; +} + +.menu__link--inside { + padding: 30px 100px 30px 20px; +} + +.menu__link--inside:hover { + background-color: var(--pokemon-type-electric); +} + +.menu__hamburguer { + height: 100%; + display: flex; + align-items: center; + padding: 0 15px; + cursor: pointer; + display: none; +} + +.menu__img { + display: block; + width: 36px; +} + + +/* ////////// FIN MENU ////////// */ + +/* ///// INICIO CARDS /////*/ + +.divConteinerCards { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + align-content: center; + margin: 180px 10px; +} + +.card { + border: 1px solid #ccc; + padding: 22px; + margin: 30px; + box-sizing: border-box; + width: 220px; + height: 300px; + border-radius: 5%; + box-shadow: 0 4px 5px #828181; +} + +.info-container { + justify-content: center; +} + +.numPokemon { + margin: 2px; + padding: 2px; + text-align: center; +} + +.img-container { + background-color: var(--theme-color); + border-radius: 60%; +} + + +/*//////FIN CARD /////*/ +/*///// INICIO MODAL ////*/ + + +/* modal */ +.modalPokemon { + display: flex; + justify-content: center; + align-items: center; + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + padding: 10px; + width: 50%; + height: 60%; + border-radius: 8px; + z-index: 1; +} + + + +/**/ +.modal-content { + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; + align-content: space-between; + flex-wrap: wrap; + gap: 10px; + + margin: auto; + padding: 10px; + width: auto; + height: auto; +} + + +.PokemonName { + color: var(--pokemon-type-steel); + text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; +} + + + +/**/ +.close { + position: absolute; + top: 0; + right: 0; + margin: 7px; + padding: 7px; + background-color: var(--theme-color); + border-radius: 4px; +} + +/* modal */ + +/* ////// Fin Modal //// */ +/*/////// INIcio section ranking//// */ + +.sectionRanking { + padding: 20px; + display: flex; + align-items: center; + text-align:center; + width: 100%; +} + +.picture { + left: 40px; + +} + + +.ranking { + background-color: var(--pokemon-type-electric); + border-radius: 8px; + box-shadow: 0 4px 5px #828181; +} + +table { + border-collapse: collapse; + width: 100%; + font-size: large; +} + +th, +td { + text-align: left; + padding: 8px; +} + +/*////// fin section ranking //////*/ +footer { + height: auto; +} \ No newline at end of file diff --git a/test/data.spec.js b/test/data.spec.js index 09b1f23f..715d2bcd 100644 --- a/test/data.spec.js +++ b/test/data.spec.js @@ -1,23 +1,70 @@ -import { example, anotherExample } from '../src/data.js'; +import funcionesPokemon from '../src/data'; +const pokemon = [ + { "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] }, + { "num": '002', "name": 'ivysaur', "spawn-chance": 0.042, "type": ['grass', 'poison'] }, + { "num": '005', "name": 'charmeleon', "spawn-chance": 0.012, "type": ['fire'] }, +]; -describe('example', () => { - it('is a function', () => { - expect(typeof example).toBe('function'); - }); - it('returns `example`', () => { - expect(example()).toBe('example'); - }); -}); +// ------ Comprueba la funcion buscar pokemon por Name +describe('funcionesPokemon', () => { + describe('funcionesPokemon.searchPokemon', () => { + it('deberia retornar bulb', () => { + const result = funcionesPokemon.searchPokemon(pokemon, 'bulb') + expect(result).toEqual([{ "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] }]); + }); -describe('anotherExample', () => { - it('is a function', () => { - expect(typeof anotherExample).toBe('function'); + // ------ Comprueba la funcion buscar pokemon por Num + it('deberia retornar 005', () => { + const result = funcionesPokemon.searchPokemon(pokemon, '005') + expect(result).toEqual([{ "num": '005', "name": 'charmeleon', "spawn-chance": 0.012, "type": ['fire'] }]); + }) }); - it('returns `anotherExample`', () => { - expect(anotherExample()).toBe('OMG'); + + // ------ Comprueba la funcion seleccionar por type + describe('funcionesPokemon.displayPokemonByType', () => { + it('deberia retornar los pokemones de tipo grass', () => { + const result = funcionesPokemon.displayPokemonByType(pokemon, 'grass') + expect(result).toEqual([ + { "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] }, + { "num": '002', "name": 'ivysaur', "spawn-chance": 0.042, "type": ['grass', 'poison'] }]); + }) + }) + + + // ------ Comprueba funcion para ordenar pokemon de A a Z + + describe('funcionesPokemon', () => { + describe('funcionesPokemon.orderPokemonAz', () => { + it('deberia retornar los pokemon ordenados por nombre de la A a Z', () => { + expect(funcionesPokemon.orderPokemonAz(pokemon)).toEqual([ + { "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] }, + { "num": '005', "name": 'charmeleon', "spawn-chance": 0.012, "type": ['fire'] }, + { "num": '002', "name": 'ivysaur', "spawn-chance": 0.042, "type": ['grass', 'poison'] } + ]); + }); + + // ------ Comprueba funcion para ordenar pokemon de Z a A + it(' deberia retornar pokemones ordenados de la Z a la A', () => { + expect(funcionesPokemon.orderPokemonZa(pokemon)).toEqual([ + { "num": '002', "name": 'ivysaur', "spawn-chance": 0.042, "type": ['grass', 'poison'] }, + { "num": '005', "name": 'charmeleon', "spawn-chance": 0.012, "type": ['fire'] }, + { "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] } + ]); + }); + }); + //-------- Comprueba funcion para ranking de aparicion de pokemon + describe('funcionesPokemon.getTopPokemon', () => { + it('deberia retornar la chance de aparicion de los pokemon de mayor a menor', () => { + expect(funcionesPokemon.getTopPokemon(pokemon)).toEqual([ + { "num": "001", "name": "bulbasaur", "spawn-chance": 0.69, "type": ['grass', 'poison'] }, + { "num": '002', "name": 'ivysaur', "spawn-chance": 0.042, "type": ['grass', 'poison'] }, + { "num": '005', "name": 'charmeleon', "spawn-chance": 0.012, "type": ['fire'] } + ]); + }); + }); }); -}); +}) \ No newline at end of file