diff --git a/README.md b/README.md index 554e57c..51e3a0a 100644 --- a/README.md +++ b/README.md @@ -2,474 +2,328 @@ ## Í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. Parte adicional-opcional](#6-parte-adicional-opcional) -* [7. Consideraciones técnicas](#7-consideraciones-técnicas) -* [8. Pistas, tips y lecturas complementarias](#8-pistas-tips-y-lecturas-complementarias) -* [9. Checklist](#9-checklist) +* [1. Introducción](#1-introducción) +* [2. Definición del Producto](#2-Definición-del-Producto) +* [3. Objetivos](#3-Objetivos) +* [4. Tipo de Usuario](#4-Tipo-de-Usuario) +* [5. Prototipos](#5-Prototipos) +* [6. Test de Usabilidad](#6-Test-de-Usabilidad) +* [7. Vista Producto Terminado](#7-Vista-Producto-Terminado) *** -## 1. Preámbulo +## 1. Introducción -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. +PoKeData GO es una aplicación que permite a los entrenadores PoKémon acceder a distintos tipos de información sobre sus Pokémon. -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 Producto -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 el usuario -al lado derecho. +PoKeData GO es una aplicación que esta dirigida a los entrenadores PoKémon, los cuales ya tienen conocimientos del juego, aquí pueden conocer toda la información de los Pokémon de la región Kanto. El usuario podrá acceder a distintos datos, como filtros ya sea por tipo de PoKémon, debilidad, entre otras. -![json-interfaz](https://lh4.googleusercontent.com/Tn-RPXS26pVvOTdUzRT1KVaJ-_QbFs9SpcGLxSPE43fgbHaXtFgMUInuDt7kV41DkT1j8Tt29V0LxQW7SMtC6digOIhfTXSBKdwI08wUwhD3RAqlwy0hjfmhZ2BFe91mtmCSEqysfgk) +## 3. Objetivos -## 2. Resumen del proyecto +El objetivo de esta aplicación, es que el usuario pueda conocer todos los datos de interés sobre su Pokémon de una forma accesible y sencilla. -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. +## 4. Tipo de Usuario :woman::boy::girl: -Como entregable final tendrás una página web que permita a los usuarios -**visualizar, filtrar, ordenar, etc.**. +Esta aplicación esta creada para entrenadores PoKémon, los cuales ya tienen experiencia y conocimientos en el juego. -Te proponemos una serie de datos de diferentes _temáticas_ para que los -explores y decidas con cuál te interesa trabajar. Cada _set_ de datos viene con -información básica sobre los datos y su estructura, y una lista de las -necesidades de los usuarios que proviene de una investigación (_research_) -hecha por el equipo de Laboratoria. +### Historias de Usuario :memo: -Una vez que elijas, diseña tu proyecto intentando ofrecerle la mejor experiencia -posible para ayudarle a satisfacer sus necesidades. +**Historia de usuario n°1.** -Estos son datos que te proponemos: +**Yo Como**: Usuario de Internet. -* [Pokémon](src/data/pokemon/pokemon.json): - En este set encontrarás una lista con los 151 Pokémon de la región de Kanto, 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) +**Quiero**: breve presentación de la página. -* [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) +**Para**: identificar de que trata la página y si me sirve o no. -* [Harry Potter](src/data/potter/potter.json). - Este set de datos muestra la lista de los personajes del mundo de [Harry Potter: Wizards Unite](https://www.wizardingworld.com/), junto con sus respectivas características mencionadas en la serie de novelas de Harry Potter escrita por la autora británica J.K.Rowling. - - [Investigación con jugadores de Harry Potter: Wizards Unite](src/data/potter/README.md) +**Definición de Terminado:** -## 3. Objetivos de aprendizaje +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. -El objetivo principal de este proyecto es que, entendiendo las necesidades de tus usuarios, aprendas a diseñar y construir una interfaz web donde se pueda visualizar y manipular data. -Revisa la lista y reflexiona sobre los objetivos que conseguiste en el proyecto anterior. Piensa en eso al decidir tu estrategia de trabajo individual y de equipo. +**Criterios de aceptación:** -### UX -- [ ] Diseñar la aplicación pensando y entendiendo al usuario. -- [ ] Crear prototipos para obtener feedback e iterar. -- [ ] Aplicar los principios de diseño visual (contraste, alineación, jerarquía). -- [ ] Planear y ejecutar tests de usabilidad. +- Nombre o logo de la página. +- Imagen referencial. +- Breve presentación que explique de que trata la página web. -### HTML y CSS -- [ ] Entender y reconocer por qué es importante el HTML semántico. -- [ ] Identificar y entender tipos de selectores en CSS. -- [ ] Entender como funciona `flexbox` en CSS. -- [ ] Construir tu aplicación respetando el diseño planeado (maquetación). +**Historia de usuario n°2** -### DOM -- [ ] Entender y reconocer los selectores del DOM (querySelector | querySelectorAll). -- [ ] Manejar eventos del DOM. (addEventListener) -- [ ] Manipular dinámicamente el DOM. (createElement, appendchild, innerHTML, value) +**Yo Como**: Jugador de Pokémon Go. -### Javascript -- [ ] Manipular arrays (`filter` | `map` | `sort` | `reduce`). -- [ ] Manipular objects (key | value). -- [ ] Entender el uso de condicionales (`if-else` | `switch`). -- [ ] Entender el uso de bucles (`for` | `forEach`). -- [ ] Entender la diferencia entre expression y statements. -- [ ] Utilizar funciones (parámetros | argumentos | valor de retorno). -- [ ] Entender la diferencia entre tipos de datos atómicos y estructurados. -- [ ] Utilizar ES Modules (`import` | `export`). +**Quiero**: un botón de tipos de Pokémon. -### Pruebas Unitarias (_testing_) -- [ ] Testear funciones (funciones puras). +**Para**:poder filtrar por el tipo de Pokémon que me interese y ver su respectiva información. -### Git y GitHub -- [ ] Ejecutar comandos de git (`add` | `commit` | `pull` | `status` | `push`). -- [ ] Utilizar los repositorios de GitHub (`clone` | `fork` | gh-pages). -- [ ] Colaborar en Github (pull requests). +**Definición de Terminado:** -### Buenas prácticas de desarrollo -- [ ] Organizar y dividir el código en módulos (Modularización). -- [ ] Utilizar identificadores descriptivos (Nomenclatura | Semántica). -- [ ] Utilizar linter para seguir buenas prácticas (ESLINT). +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. +- Cumple con los criterios de aceptación. -### Soft skills -- [ ] **Planificación, organización y manejo del tiempo** Organizarse utilizando historias de usuario, haciendo una estimación general de los tiempos que se necesitarán para la realización del proyecto. Conocer las ceremonias y artefactos ágiles (sprint planning, dailys, retrospectiva, tablero al menos, etc) a pesar de que no se utilicen con regularidad. -- [ ] **Trabajo en equipo** Trabajar con otros de forma colaborativa y en base a un objetivo común, entregando ideas para la construcción del proyecto +**Criterios de aceptación:** -- [ ] **Autoaprendizaje** Demostrar interés y adquirir nuevos conocimientos autónomamente, estudiando de manera independiente, lo que se traduce, en que cuando es necesario, la estudiante buscará aclarar conceptos y resolver dudas sobre la materia. +- Botón tipo de Pokémon. +- Que despliegue los tipos de Pokémon existentes. +- Que permita seleccionar un tipo de Pokémon en específico. +- Que muestre todos los Pokémon del tipo seleccionado por el usuario. -- [ ] **Presentaciones** Utilizar ciertas estrategias para hablar en público (tono y ritmo de voz adecuado, contacto visual con el público, interacción con medios de presentación), que permitan asegurar un mediano entendimiento de la audiencia. +**Historia de usuario n°3.** -- [ ] **Adaptabilidad** Afrontar los cambios inesperados o nuevos desafíos con una actitud positiva, aunque no necesariamente se logre accionar o adaptarse de la mejor manera a los diferentes contextos. +**Yo Como**: jugador de Pokémon Go. -- [ ] **Solución de problemas** Trabajar en la búsqueda y en la elaboración de soluciones alternativas a problemas de mediana complejidad. +**Quiero**: un botón de ordenar por. -- [ ] **Responsabilidad** Demostrar actitud de compromiso, reflejandolo en la entrega de trabajo a tiempo, llegando a la hora acordada y/o avisando cuando no se pueda asistir. +**Para**: poder filtrar alfabéticamente mis Pokémon. -- [ ] **Dar y recibir feedback** Escuchar los comentarios y críticas de los demás de manera respetuosa, y/o comunicar a los demás las opiniones de forma constructiva. +**Definición de Terminado:** -- [ ] **Comunicación eficaz** Comunicar ideas a los demás cuando es necesario, aunque no siempre se fomenten de manera proactiva estas instancias de comunicación. +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. +- Cumple con los criterios de aceptación. -## 4. Consideraciones generales +**Criterios de aceptación:** -* Este proyecto se debe resolver en duplas. -* El proyecto será entregado subiendo tu código a GitHub (`commit`/`push`) y la - interfaz será desplegada usando [GitHub Pages](https://pages.github.com/). -* Tiempo para completarlo: Toma como referencia 3 semanas (15 días hábiles). +- Crear botón de nombre ordenar por. +- Que se despliegue la opción de ordenar de A-Z o Z-A. +- Que se muestren todos los Pokémon ordenados alfabéticamente. -## 5. Criterios de aceptación mínimos del proyecto -Los criterios para considerar que has completado este proyecto son: +**Historia de usuario n°4.** -### Definición del producto +**Yo Como**: jugador de Pokémon Go. -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. +**Quiero**: tener un buscador. -### Historias de usuario +**Para**: buscar directamente el Pokémon que me interesa y revisar su información. -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. +**Definición de Terminado:** -Asegúrate de incluir la definición de terminado (_definition of done_) y los -Criterios de Aceptación para cada una. +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. +- Cumple con los criterios de aceptación. -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). -### Diseño de la Interfaz de Usuario +**Criterios de aceptación:** -#### Prototipo de baja fidelidad +- Input tipo texto de búsqueda. +- Agregar evento al input con Enter en el teclado. +- Que muestre el Pokémon ingresado en el input. -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`. +**Historia de usuario n°5.** -#### Prototipo de alta fidelidad +**Yo Como**: jugador de Pokémon Go. -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. Recuerda utilizar la -[identidad gráfica](https://drive.google.com/open?id=1eeWFqrWpy-OYOH4EHDckFGunyrm9iNeE) -correspondiente a cada set de datos que elijas. +**Quiero**: un botón de debilidades contra un tipo específico de Pokémon. -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_. +**Para**: poder filtrar por el tipo de debilidad que requiero investigar y determinar que Pokémon escoger para una batalla. -#### Testeos de usabilidad +**Definición de Terminado:** -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. +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. +- Cumple con los criterios de aceptación. -### Implementación de la Interfaz de Usuario (HTML/CSS/JS) -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 +**Criterios de aceptación:** -Como mínimo, tu implementación debe: +- Botón de nombre debilidades contra. +- Que se desplieguen los tipos de debilidades escogidas por el usuario. +- Que el usuario pueda seleccionar una debilidad. -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_. -### Pruebas unitarias +**Historia de usuario n°6.** -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. +**Yo Como**: jugador de Pokémon Go. -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). +**Quiero**: saber las características de mi Pokémon. -## 6. Parte adicional-opcional +**Para**: poder tomar decisiones en cuanto a mis Pokémon actuales o los que deseo conseguir. -Si **terminaste** con todo lo anterior y te queda tiempo, intenta explorar y -completar parte o todo de lo siguiente. Así podrás -profundizar y/o ejercitar más sobre los objetivos de aprendizaje del proyecto. +**Definición de Terminado:** -Features/características extra sugeridas: +- El código está en el repositorio remoto. +- El código pasa el mínimo porcentaje de test aceptado. +- La historia implementada fue testeada por mínimo 2 usuarios. +- Se realizaron las mejoras detectadas en el testeo de usabilidad. +- Cumple con los criterios de aceptación. -* 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. +**Criterios de aceptación:** -* 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/). +- Modal que despliegue la información del Pokémon que el usuario elija. +- Agregar altura y peso a la tarjeta de información. +- Agregar debilidades del Pokémon seleccionado por el usuario. +- Agregar tipo de Pokemon. +- Agregar evolución del Pokémon. +- Agregar número y tipo de caramelos para poder evolucionar al Pokémon. -* 100% Coverage de pruebas unitarias. +## 5. Prototipos -## 7. Consideraciones técnicas +**Diagrama de Flujo** :computer: :printer: -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. +Para comenzar armamos un diagrama de flujo para saber como queríamos que funcionara nuestra pagina web, y así comenzar el trabajo en el prototipo. -No se debe utilizar la _pseudo-variable_ `this`. -El _boilerplate_ contiene una estructura de archivos como punto de partida así -como toda la configuración de dependencias: +![Diagrama de flujo](https://github.com/paula-plaza/SCL013-data-lovers/blob/master/src/imagenes/Digrama_Flujo.png?raw=true) -```text -. -├── EXTRA.md -├── README.md -├── package.json -├── src -| ├── data (según con qué data trabajes) -| | ├── lol -| | | ├── lol.js -| | | ├── lol.json -| | | └── README.md -| | ├── pokemon -| | | ├── pokemon.js -| | | ├── pokemon.json -| | | └── README.md -| | └── potter -| | ├── potter.js -| | └── potter.json -| | └── README.md -| ├── data.js -| ├── index.html -| ├── main.js -| └── style.css -└── test - └── data.spec.js -directory: 6 file: 17 -``` +**Prototipo Papel**:pencil2::crayon: -### `src/index.html` +![Prototipo Papel](https://github.com/paula-plaza/SCL013-data-lovers/blob/master/src/imagenes/prototipo_papel1.png?raw=true) -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. +![Prototipo Papel](https://github.com/paula-plaza/SCL013-data-lovers/blob/master/src/imagenes/prototipo_papel2.png?raw=true) -Encontrarás 1 etiqueta inicial, la cual si deseas puedes borrar y empezar de cero: - -``` -
-``` - -### `src/main.js` - -Acá escribirás todo el código que tenga que ver con la interacción del DOM -(seleccionar, actualizar y manipular elementos del DOM y eventos). Es decir, -en este archivo deberás invocar a tus funciones exportadas en el boilerplate, -según sea necesario para realizar operaciones como creación de nodos, -registro de manejadores de eventos (_event listeners_ o _event handlers_), .... - -En este archivo encontrarás una serie de _sentencias_ `import` -_comentadas_. Para _cargar_ las diferentes fuentes de datos tendrás que -_descomentar_ estas _sentencias_. Cada una de estas sentencias importará un -objeto, el cual ya se encuentra exportado en el boilerplate. Este objeto -contiene la data correspondiente a esa fuente de datos. - -Por ejemplo, si "descomentamos" la siguiente línea: - -```js -// import data from './data/pokemon/pokemon.js'; -``` - -La línea quedaría así: - -```js -import data from './data/pokemon/pokemon.js'; -``` - -Y ahora tendríamos la variable `data` disponible en el script `src/main.js`. - -### `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. - -* Y así sucesivamente, según tu proyecto en particular. - -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 + + + + + + + + + + + + + + +
+
+

PoKéData GO

+

Es una web dirigida a todos los jugadores amantes de Pokémon GO.

+

En nuestra página podrás encontrar tus pokémon por tipo y debilidades, así como conocer las características de + tu pokémon favorito o el de tu contrincante.

+

¡Explora y conviertete en el mejor Entrenador Pokémon!

+
+ +
+ +
+ +
+ +
+ +
+ + + + + + + diff --git a/src/main.js b/src/main.js index 71c59f2..1973166 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,386 @@ -import { example } from './data.js'; -// import data from './data/lol/lol.js'; -import data from './data/pokemon/pokemon.js'; -// import data from './data/rickandmorty/rickandmorty.js'; +import pokemon from './data/pokemon/pokemon.js'; -console.log(example, data); +import { + imgOfPokemon, + nameOfPokemon, + numOfPokemon, + typeOfPokemon, + heightOfPokemon, + weightOfPokemon, + candyOfPokemon, + candyCountOfPokemon, + weaknessesOfPokemon, + nextEvolutionOfPokemon, + sortData +} from './data.js'; + +const pokemonDatos = pokemon.pokemon; +//variable para el id del selectType, selección por tipo +const selectFilterByTypePokemon = document.getElementById("selectType"); +//variable para el id del container de la pagina principal de bienvenida +const welcomeContainer = document.getElementById("welcomePage"); + +//evento de select para filtrar por tipo de pokémon +selectFilterByTypePokemon.addEventListener('change', () => { + //variable que reconoce cual de todos los options fue seleccionado en el droplist y te devulve el valor de ese option + const droplistSelectType = selectFilterByTypePokemon.options[selectFilterByTypePokemon.selectedIndex].value; + //variable que toma el texto del option seleccionado para indicar cual se esta viendo en pantalla en el mensaje arriba de las cards + const droplistSelectTypeSpanish = selectFilterByTypePokemon.options[selectFilterByTypePokemon.selectedIndex].text; + //creando las variables de string de la información que debe aparecer en las cards de cada pokémon + const stringOfImgOfPokemon = imgOfPokemon("type", droplistSelectType); + const stringOfNameOfPokemon = nameOfPokemon("type", droplistSelectType); + const stringOfNumOfPokemon = numOfPokemon("type", droplistSelectType); + const stringOfTypeOfPokemon = typeOfPokemon("type", droplistSelectType); + const stringOfHeightOfPokemon = heightOfPokemon("type", droplistSelectType); + const stringOfWeightOfPokemon = weightOfPokemon("type", droplistSelectType); + const stringOfCandyOfPokemon = candyOfPokemon("type", droplistSelectType); + const stringOfCandyCountOfPokemon = candyCountOfPokemon("type", droplistSelectType); + const stringOfWeaknessesOfPokemon = weaknessesOfPokemon("type", droplistSelectType); + const stringOfNextEvolutionOfPokemon = nextEvolutionOfPokemon("type", droplistSelectType); + + //variable que llama la sección (root) que contendra todas las cards de los pokémon + const cardsContainer = document.getElementById("root"); + //ciclo para borrar todos los hijos que pueda tener la sección de root (cardsContainer) para poder imprimir los pokémon por filtro solicitado + while (cardsContainer.hasChildNodes()) { + cardsContainer.removeChild(cardsContainer.firstChild); + } + //devuelve los otros select de filtro debilidad y ordenar para que queden en su select inicial, vacía el input + document.getElementById("selectWeak").value = ""; + document.getElementById("selectOrder").value = ""; + document.getElementById("searchBar").value = ""; + + //mensaje que indica que tipo de pokémon se está viendo en pantalla + let showingTypeOfPokemon = document.getElementById("topMessageOfType"); + showingTypeOfPokemon.innerHTML = `

Tipo de Pokémon: ${droplistSelectTypeSpanish}

` + + //ciclo para imprimir las cards pequeñas de pokémon por separado, cuando se selecciona el filtro de tipo + for (let i = 0; i < stringOfTypeOfPokemon.length; i++) { + //variable para crear div para las cards de pokémon + const smallCard = document.createElement("div"); + smallCard.classList.add("smallCardStyle"); //agrega atributo de clase + smallCard.setAttribute("id", "divSmallCardPokemon"); + smallCard.innerHTML += ` +
${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}
+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Ver...`; + cardsContainer.appendChild(smallCard); + welcomeContainer.innerHTML = " "; //borrar la sección de bienvenida para mostrar la sección de root (cards container) + + //creación del div que contendra el modal + const modalCard = document.createElement("div"); + modalCard.setAttribute("class", "modalCardStyle"); + cardsContainer.appendChild(modalCard); + + //creación del div que es el modal con la información + const modalCardInformation = document.createElement("div"); + modalCardInformation.setAttribute("class", "modal-card-information"); + modalCard.appendChild(modalCardInformation); + modalCardInformation.innerHTML = ` +

${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}

+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Altura: ${stringOfHeightOfPokemon[i]}

+

Peso: ${stringOfWeightOfPokemon[i]}

+

Caramelo: ${stringOfCandyOfPokemon[i]}

+

N° de Caramelos para evolucionar: ${stringOfCandyCountOfPokemon[i]}

+

Debilidades: ${replace(stringOfWeaknessesOfPokemon[i])}

+

Evolución: ${stringOfNextEvolutionOfPokemon[i] ? stringOfNextEvolutionOfPokemon[i][0].name : "No tiene más evoluciones"}

`; + + + //creación del botón de cerrar el modal card de información de pokémon + const closeModal = document.createElement("span"); + closeModal.setAttribute("id", "closeModalSpan"); + closeModal.innerHTML = "×"; + modalCardInformation.insertBefore(closeModal, modalCardInformation.childNodes[0]); + + //evento para abrir y cerrar el modal + smallCard.addEventListener("click", () => { + modalCard.classList.add("modal-bg-active"); + }); + closeModal.addEventListener("click", () => { + modalCard.classList.remove("modal-bg-active"); + }); + } +}); + +//variable para el id del selectWeak, seleccionando contra que es débil el pokémon +const selectFilterByWeaknessOfPokemon = document.getElementById("selectWeak"); + +//evento de select para filtrar por debilidad que tengan los pokémon +selectFilterByWeaknessOfPokemon.addEventListener('change', () => { + //devuelve los otros select de filtro por tipo y ordenar para que queden en su select inicial, vacía el input + document.getElementById("selectType").value = ""; + document.getElementById("selectOrder").value = ""; + document.getElementById("searchBar").value = ""; + document.getElementById("topMessageOfType").innerHTML = ""; + + //variable que reconoce cual de todos los options fue seleccionado en el droplist y te devulve el valor de ese option + const droplistSelectWeakness = selectFilterByWeaknessOfPokemon.options[selectFilterByWeaknessOfPokemon.selectedIndex].value; + //variable para tomar el texto del option seleccionado, para el mensaje que se muestra arriba del contenedor de las cards + const droplistSelectWeaknessSpanish = selectFilterByWeaknessOfPokemon.options[selectFilterByWeaknessOfPokemon.selectedIndex].text; + //creando las variables de string de la información que debe aparecer en las cards de cada pokémon + const stringOfImgOfPokemon = imgOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfNameOfPokemon = nameOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfNumOfPokemon = numOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfTypeOfPokemon = typeOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfHeightOfPokemon = heightOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfWeightOfPokemon = weightOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfCandyOfPokemon = candyOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfCandyCountOfPokemon = candyCountOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfWeaknessesOfPokemon = weaknessesOfPokemon("weaknesses", droplistSelectWeakness); + const stringOfNextEvolutionOfPokemon = nextEvolutionOfPokemon("weaknesses", droplistSelectWeakness); + + //variable que llama la sección (root) que contendra todas las cards de los pokémon + const cardsContainer = document.getElementById("root"); + //ciclo para borrar todos los hijos que pueda tener la sección de root (cardsContainer) para poder imprimir los pokémon por filtro solicitado + while (cardsContainer.hasChildNodes()) { + cardsContainer.removeChild(cardsContainer.firstChild); + } + + //mensaje que indica contra que debilidad se está viendo en pantalla + let showingWeaknessOfPokemon = document.getElementById("topMessageOfType"); + showingWeaknessOfPokemon.innerHTML = `

Debilidad contra tipo: ${droplistSelectWeaknessSpanish}

` + + //ciclo para imprimir las cards pequeñas de pokémon por separado, cuando se selecciona el filtro por debilidad + for (let i = 0; i < stringOfNameOfPokemon.length; i++) { + //variable para crear div para las cards de pokémon + const smallCard = document.createElement("div"); + smallCard.classList.add("smallCardStyle"); //agrega atributo de clase + smallCard.setAttribute("id", "divSmallCardPokemon"); + smallCard.innerHTML += ` +
${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}
+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Ver...`; + cardsContainer.appendChild(smallCard); + welcomeContainer.innerHTML = " "; //borrar la sección de bienvenida para mostrar la sección de root (cards container) + + //creación del div que contendra el modal + const modalCard = document.createElement("div"); + modalCard.setAttribute("class", "modalCardStyle"); + cardsContainer.appendChild(modalCard); + + //creación del div que es el modal con la información + const modalCardInformation = document.createElement("div"); + modalCardInformation.setAttribute("class", "modal-card-information"); + modalCard.appendChild(modalCardInformation); + modalCardInformation.innerHTML = ` +

${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}

+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Altura: ${stringOfHeightOfPokemon[i]}

+

Peso: ${stringOfWeightOfPokemon[i]}

+

Caramelo: ${stringOfCandyOfPokemon[i]}

+

N° de Caramelos para evolucionar: ${stringOfCandyCountOfPokemon[i]}

+

Debilidades: ${replace(stringOfWeaknessesOfPokemon[i])}

+

Evolución: ${stringOfNextEvolutionOfPokemon[i] ? stringOfNextEvolutionOfPokemon[i][0].name : "No tiene más evoluciones"}

`; + + //creación del botón de cerrar el modal card de información de pokémon + const closeModal = document.createElement("span"); + closeModal.setAttribute("id", "closeModalSpan"); + closeModal.innerHTML = "×"; + modalCardInformation.insertBefore(closeModal, modalCardInformation.childNodes[0]); + + //evento par abrir y cerrar el modal + smallCard.addEventListener("click", () => { + modalCard.classList.add("modal-bg-active"); + }); + closeModal.addEventListener("click", () => { + modalCard.classList.remove("modal-bg-active"); + }); + } +}); + +//ordenar de A a la Z +document.getElementById("selectOrder").addEventListener('change', () => { + //devuelve los otros select de filtro por tipo y ordenar por para que queden en su select inicial, vacía el input + document.getElementById("selectType").value = ""; + document.getElementById("selectWeak").value = ""; + document.getElementById("searchBar").value = ""; + document.getElementById("topMessageOfType").innerHTML = " "; + + //variable que toma el valor seleccionado por el usuario + const orderbyName = document.getElementById("selectOrder").value; + //inicializando variable para ordenar los pokémon + let pokeOrdered = sortData(pokemonDatos, "name", orderbyName); + + //variable que llama la sección (root) que contendra todas las cards de los pokémon + const cardsContainer = document.getElementById("root"); + while (cardsContainer.hasChildNodes()) { + cardsContainer.removeChild(cardsContainer.firstChild); + } + + //ciclo para imprimir las cards pequeñas de pokémon por separado, cuando se selecciona el filtro por orden + for (let i = 0; i < pokeOrdered.length; i++) { + //variable para crear div para las cards de pokémon + const smallCard = document.createElement("div"); + smallCard.classList.add("smallCardStyle"); //agrega atributo de clase + smallCard.setAttribute("id", "divSmallCardPokemon"); + smallCard.innerHTML += ` +
${pokeOrdered[i].name} #${pokeOrdered[i].num}
+

Tipo: ${replace(pokeOrdered[i].type)}

+

Ver...`; + cardsContainer.appendChild(smallCard); + welcomeContainer.innerHTML = " "; + + //creación del div que contendra el modal + const modalCard = document.createElement("div"); + modalCard.setAttribute("class", "modalCardStyle"); + cardsContainer.appendChild(modalCard); + + //creación del div que es el modal con la información + const modalCardInformation = document.createElement("div"); + modalCardInformation.setAttribute("class", "modal-card-information"); + modalCard.appendChild(modalCardInformation); + modalCardInformation.innerHTML = ` +

${pokeOrdered[i].name} #${pokeOrdered[i].num}

+

Tipo: ${replace(pokeOrdered[i].type)}

+

Altura: ${pokeOrdered[i].height}

+

Peso: ${pokeOrdered[i].weight}

+

Caramelo: ${pokeOrdered[i].candy}

+

N° de Caramelos para evolucionar: ${pokeOrdered[i].candy_count}

+

Debilidades: ${replace(pokeOrdered[i].weaknesses)}

+

Evolución: ${pokeOrdered[i].next_evolution ? pokeOrdered[i].next_evolution[0].name : "No tiene más evoluciones"}

`; + + //creación del botón de cerrar el modal card de información de pokémon + const closeModal = document.createElement("span"); + closeModal.setAttribute("id", "closeModalSpan"); + closeModal.innerHTML = "×"; + modalCardInformation.insertBefore(closeModal, modalCardInformation.childNodes[0]); + + //evento par abrir y cerrar el modal + smallCard.addEventListener("click", () => { + modalCard.classList.add("modal-bg-active"); + }); + closeModal.addEventListener("click", () => { + modalCard.classList.remove("modal-bg-active"); + }); + } +}); + +//evento para el buscador por nombre de pokémon +document.getElementById('searchBar').addEventListener('keydown', (evt) => { + if (evt.keyCode === 13) { + //devuelve los otros select para que queden en su valor inicial + document.getElementById("selectType").value = ""; + document.getElementById("selectOrder").value = ""; + document.getElementById("selectWeak").value = ""; + document.getElementById("topMessageOfType").innerHTML = ""; + + //constante que toma el valor que el usuario ingresa en el input + const inputSearchValue = document.getElementById("searchBar").value; + + //colocando la primera letra en mayúscula y el resto en minúscula para buscar dentro de la data + const inputSearchName = inputSearchValue.charAt(0).toUpperCase() + inputSearchValue.slice(1).toLowerCase(); + + //creando las variables de string de la información que debe aparecer en las cards de cada pokémon + const stringOfImgOfPokemon = imgOfPokemon("name", inputSearchName); + const stringOfNameOfPokemon = nameOfPokemon("name", inputSearchName); + const stringOfNumOfPokemon = numOfPokemon("name", inputSearchName); + const stringOfTypeOfPokemon = typeOfPokemon("name", inputSearchName); + const stringOfHeightOfPokemon = heightOfPokemon("name", inputSearchName); + const stringOfWeightOfPokemon = weightOfPokemon("name", inputSearchName); + const stringOfCandyOfPokemon = candyOfPokemon("name", inputSearchName) + const stringOfCandyCountOfPokemon = candyCountOfPokemon("name", inputSearchName); + const stringOfWeaknessesOfPokemon = weaknessesOfPokemon("name", inputSearchName); + const stringOfNextEvolutionOfPokemon = nextEvolutionOfPokemon("name", inputSearchName); + + //borra todos los hijos que pueda tener la sección de root + const cardsContainer = document.getElementById("root"); + cardsContainer.classList.add("rootHeight"); + while (cardsContainer.hasChildNodes()) { + cardsContainer.removeChild(cardsContainer.firstChild); + } + + for (let i = 0; i < stringOfNameOfPokemon.length; i++) { + //variable para crear div para las cards de pokémon + const smallCard = document.createElement("div"); + smallCard.classList.add("smallCardStyle"); //agrega atributo de clase + smallCard.setAttribute("id", "divSmallCardPokemon"); + smallCard.innerHTML += ` +
${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}
+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Ver...`; + cardsContainer.appendChild(smallCard); + welcomeContainer.innerHTML = " "; //borrar la sección de bienvenida para mostrar la sección de root (cards container) + + //creación del div que contendra el modal + const modalCard = document.createElement("div"); + modalCard.setAttribute("class", "modalCardStyle"); + cardsContainer.appendChild(modalCard); + + //creación del div que es el modal con la información de cada pokémon + const modalCardInformation = document.createElement("div"); + modalCardInformation.setAttribute("class", "modal-card-information"); + modalCard.appendChild(modalCardInformation); + modalCardInformation.innerHTML = ` +

${stringOfNameOfPokemon[i]} #${stringOfNumOfPokemon[i]}

+

Tipo: ${replace(stringOfTypeOfPokemon[i])}

+

Altura: ${stringOfHeightOfPokemon[i]}

+

Peso: ${stringOfWeightOfPokemon[i]}

+

Caramelo: ${stringOfCandyOfPokemon[i]}

+

N° de Caramelos para evolucionar: ${stringOfCandyCountOfPokemon[i]}

+

Debilidades: ${replace(stringOfWeaknessesOfPokemon[i])}

+

Evolución: ${stringOfNextEvolutionOfPokemon[i] ? stringOfNextEvolutionOfPokemon[i][0].name : "No tiene más evoluciones"}

`; + + + //creación del botón de cerrar el modal card de información de pokémon + const closeModal = document.createElement("span"); + closeModal.setAttribute("id", "closeModalSpan"); + closeModal.innerHTML = "×"; + modalCardInformation.insertBefore(closeModal, modalCardInformation.childNodes[0]); + + //evento par abrir y cerrar el modal + smallCard.addEventListener("click", () => { + modalCard.classList.add("modal-bg-active"); + }); + closeModal.addEventListener("click", () => { + modalCard.classList.remove("modal-bg-active"); + }); + } + } +}); + +//función para reemplazar de inglés a español +function replace(data) { + let newArray = []; + for (let i = 0; i < data.length; i++) { + if (data[i] == ["Grass"]) { + newArray.push(["Planta"]); + } else if (data[i] == ["Poison"]) { + newArray.push(["Veneno"]); + } else if (data[i] == ["Fire"]) { + newArray.push(["Fuego"]); + } else if (data[i] == ["Ice"]) { + newArray.push(["Hielo"]); + } else if (data[i] == ["Flying"]) { + newArray.push(["Volador"]); + } else if (data[i] == ["Psychic"]) { + newArray.push(["Psíquicos"]); + } else if (data[i] == ["Water"]) { + newArray.push(["Agua"]); + } else if (data[i] == ["Ground"]) { + newArray.push(["Tierra"]); + } else if (data[i] == ["Rock"]) { + newArray.push(["Roca"]); + } else if (data[i] == ["Electric"]) { + newArray.push(["Eléctrico"]); + } else if (data[i] == ["Bug"]) { + newArray.push(["Bicho"]); + } else if (data[i] == ["Normal"]) { + newArray.push(["Normal"]); + } else if (data[i] == ["Fighting"]) { + newArray.push(["Pelea"]); + } else if (data[i] == ["Fairy"]) { + newArray.push(["Hada"]); + } else if (data[i] == ["Ghost"]) { + newArray.push(["Fantasma"]); + } else if (data[i] == ["Dark"]) { + newArray.push(["Siniéstro"]); + } else if (data[i] == ["Steel"]) { + newArray.push(["Metal"]); + } else if (data[i] == ["Dragon"]) { + newArray.push(["Dragón"]); + } else { + newArray.push(["No aplica"]); + } + } + return newArray; +} diff --git a/src/style.css b/src/style.css index e69de29..367c5eb 100644 --- a/src/style.css +++ b/src/style.css @@ -0,0 +1,434 @@ +/*Pokedata GO header*/ +* { + font-family: sans-serif; +} + +body { + margin: 0px; + -webkit-margin-bottom-collapse: discard; + font-family: sans-serif; +} + +#logo { + background-attachment: scroll, fixed; + background-position-x: left, center; + background-position-y: top, center; + background-size: auto, cover; + width: 100%; + height: auto; + left: 0px; + top: 0px; +} + +/*menú responsive hamburguesa*/ +section label { + display: none; + width: 60px; +} + +#btn-menu-responsive { + display: none; +} + +.btn-menu { + color: #FFFFFF; + font-size: 33px; + font-weight: bold; + padding: 10px 0px 10px 10px; +} + +#menuResponsive { + background-color: #FB272A; + height: 55px; + display: flex; + width: 100%; +} + +.btn-menu:hover { + cursor: pointer; + color: #FFC800; + font-size: 35px; +} + +/*estilo menú desktop*/ +#menu { + position: center; + background: #FB272A; + width: 75%; + left: 0px; + line-height: 30px; + display: flex; + justify-content: space-evenly; + background-color: #FB272A; + -webkit-appearance: none; + -moz-appearance: none; +} + +.droplists { + background-color: #FB272A; + border-color: transparent; + color: #FFFFFF; + font-family: sans-serif; + font-style: normal; + font-weight: bold; + font-size: 16px; + display: flex; + -webkit-appearance: none; + -moz-appearance: none; +} + +.droplists:hover { + color: #FFC800; + font-size: 20px; + box-shadow: #FFFFFF; + display: flex; + cursor: pointer; +} + +#searchBar { + width: 250px; + height: 20px; + display: flex; + justify-self: flex-end; + border-radius: 5px; + background: #FFFFFF; + margin-right: 10px; +} + +#searchInput { + display: flex; + align-items: center; + color: #FFFFFF; +} + +option { + background-color: #FF7A64; + color: whitesmoke; + font-family: sans-serif; +} + + +#welcomePage { + display: flex; + margin-top: 5%; + justify-items: center; +} + +/*estilo texto bienvenida*/ +#welcome { + display: flex; + justify-content: flex-start; + text-align: left; + font-size: 140%; + font-family: sans-serif; + color: rgba(0, 0, 0, 0.6); + padding-right: 5%; + padding-left: 5%; + flex-direction: column; +} + +/*estilo imagen bienvenida*/ +.pokeFriends { + display: flex; + justify-content: flex-end; + align-self: center; + padding-right: 5%; +} + +#footer { + background-color: #FB272A; + height: 30px; + display: flex; + margin-top: 50px; + bottom: 0; + left: 0; + right: 0; +} + +.footerCopyright { + display: flex; + font-style: normal; + font-weight: normal; + font-family: sans-serif; + font-size: 12px; + color: #FFFFFF; + margin-left: 10px; + align-self: center; +} + +.socialMedia { + display: flex; + margin-left: 50%; + justify-content: space-between; + align-items: center; +} + +/*iconos de la barra social media*/ +.icon { + color: #FFFFFF; + text-decoration: none; + font-size: 1.5rem; + margin-right: 20px; +} + +/*mensaje de tipo de pokémon*/ +#topMessageOfType { + text-align: center; + font-size: 100%; + font-family: sans-serif; + font-style: normal; + margin-bottom: 2%; + color: rgba(0, 0, 0, 0.4); +} + +/*contenedor principal de las cards de pokémon*/ +#root { + text-align: left; + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: 2%; +} + +.rootHeight { + min-height: calc(100vh - 278px - 30px); +} + +/*card de pokémon*/ +.smallCardStyle { + background-color: rgba(255, 255, 255, 0.9); + border-radius: 2%; + border: 2px solid rgba(185, 211, 210, 0.8); + box-sizing: border-box; + box-shadow: 0px 8px 8px rgba(0, 0, 0, 0.70); + width: 15%; + height: 27%; + margin: 2%; + display: flex; + flex-direction: column; + font-family: sans-serif; + font-size: 16px; + font-style: normal; + font-weight: bold; + color: rgba(0, 0, 0, 0.6); +} + +.smallCardStyle:hover { + cursor: pointer; + border: 8px solid rgba(185, 211, 210, 0.8); +} + +/*estilo en el párrafo de la card chica*/ +#divSmallCardPokemon p { + margin: 5%; +} + +/*estilo al nombre del pokémon en la card chica*/ +#pokemonNameCard { + align-self: center; + font-size: 18px; + font-weight: bold; +} + +/*estilo imagen pokemon en card chica*/ +#imgPokemonCard { + display: flex; + align-self: center; +} + +/*estilo de "Ver" en las cartas*/ +.seeMorePopUp { + color: #FB272A; + font-weight: bolder; + display: flex; + justify-content: flex-end; +} + +/*div que contiene al modal*/ +.modalCardStyle { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + visibility: hidden; + opacity: 0; + transition: visibility 0s, opacity 0.8s; +} + +/*nueva clase que activara el modal y su visivilidad*/ +.modal-bg-active { + visibility: visible; + opacity: 1; +} + +/*div de modal que contiene la información por pokémon*/ +.modal-card-information { + background-color: rgba(255, 255, 255); + border-radius: 3%; + border: 3px solid rgba(60, 201, 201, 0.65); + box-sizing: border-box; + box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.20); + width: 30%; + display: flex; + flex-direction: column; + font-family: sans-serif; + margin: auto; + padding-bottom: 20px; + padding-left: 20px; + padding-right: 20px; + color: rgba(0, 0, 0, 0.7); +} + +/*estilo del nombre y número de pokémon en modal*/ +.modal-card-information h2 { + text-align: center; + font-weight: bolder; +} + +/*estilo de los párrafos de características en modal*/ +.modal-card-information p { + font-size: 18px; + font-style: normal; + text-align: left; + margin: 1.5%; +} + +/*estilo del título de característica en el modal*/ +.modalPokemon { + font-weight: bolder; + color: rgba(0, 0, 0, 0.7); +} + +/*estilo de la X que cierra el modal*/ +#closeModalSpan { + font-weight: bold; + font-size: 30px; + display: flex; + align-self: flex-end; + color: rgba(0, 0, 0, 0.5); +} + +#closeModalSpan:hover { + cursor: pointer; + color: black; + font-size: 40px; +} + +@media screen and (max-width: 980px) { + + #logo { + width: 100%; + } + + section label { + display: block; + } + + #menuResponsive { + display: flex; + } + + #menu { + position: absolute; + display: flex; + margin-top: 50px; + flex-direction: column; + height: 15%; + width: 60%; + margin-left: -60%; + transition: all 1s; + -webkit-appearance: none; + } + + #btn-menu-responsive:checked~#menu { + margin-left: 0; + } + + #searchInput { + display: flex; + } + + .droplists { + font-size: 10px; + margin-left: 10px; + margin-bottom: 5px; + -webkit-appearance: none; + } + + .droplists:hover { + font-size: 12px; + margin-bottom: 0; + } + + #welcomePage { + flex-direction: column; + } + + h1 { + font-size: 120%; + padding-top: 10%; + } + + p { + font-size: 70%; + } + + h3 { + font-size: 90%; + } + + #welcomeImage { + height: 70%; + width: 70%; + margin-top: 40px; + margin-right: auto; + margin-left: auto; + padding-left: 5%; + } + + .copyright { + display: none; + } + + .socialMedia { + display: flex; + align-self: center; + } + + #footer { + display: flex; + justify-content: flex-end; + clear: both; + } + + #topMessageOfType { + margin-top: 63px; + -webkit-margin-top-collapse: separate; + } + + #root { + display: flex; + flex-direction: row; + align-content: center; + } + + .smallCardStyle { + background-color: rgba(255, 255, 255, 0.9); + border-radius: 4%; + min-width: 150px; + } + + .modal-card-information { + min-width: 380px; + min-height: 450px; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + } + +} diff --git a/test/data.spec.js b/test/data.spec.js index 9344710..06aa538 100644 --- a/test/data.spec.js +++ b/test/data.spec.js @@ -1,23 +1,415 @@ -import { example, anotherExample } from '../src/data.js'; +import { + imgOfPokemon, + nameOfPokemon, + numOfPokemon, + typeOfPokemon, + heightOfPokemon, + weightOfPokemon, + candyOfPokemon, + candyCountOfPokemon, + weaknessesOfPokemon, + nextEvolutionOfPokemon, + sortData +} from '../src/data.js'; +describe('imgOfPokemon', () => { + test("debería ser una funcion", () => { + expect(typeof imgOfPokemon).toBe('function'); + }); + + test("imgOfPokemon con parámetros de name y Bulbasaur debería devolver [http://www.serebii.net/pokemongo/pokemon/001.png]", () => { + expect(imgOfPokemon("name", "Bulbasaur")).toEqual(["http://www.serebii.net/pokemongo/pokemon/001.png"]); + }); +}); + +describe('nameOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof nameOfPokemon).toBe('function'); + }); + + test("nameOfPokemon con parámetros de type y dragon debería devolver ['Dratini','Dragonair','Dragonite']", () => { + expect(nameOfPokemon("type", "Dragon")).toEqual(["Dratini", "Dragonair", "Dragonite"]); + }); +}); + +describe('numOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof numOfPokemon).toBe('function'); + }); + + test("numOfPokemon con parámetros de weaknesses y Poison debería devolver ['046','047','102','103','114']", () => { + expect(numOfPokemon("weaknesses", "Poison")).toEqual(["046", "047", "102", "103", "114"]); + }); +}); + +describe('typeOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof typeOfPokemon).toBe('function'); + }); + + test("typeOfPokemon con parámetros de type y Ghost debería devolver [['Ghost','Poison'],['Ghost','Poison'],['Ghost','Poison']]", () => { + expect(typeOfPokemon("type", "Ghost")).toEqual([ + ["Ghost", "Poison"], + ["Ghost", "Poison"], + ["Ghost", "Poison"] + ]); + }); +}); + +describe('heightOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof heightOfPokemon).toBe('function'); + }); + + test("heightOfPokemon con parámetros de type y Ice debería devolver ['1.70 m','1.50 m','1.40 m','2.49 m','1.70 m']", () => { + expect(heightOfPokemon("type", "Ice")).toEqual(["1.70 m", "1.50 m", "1.40 m", "2.49 m", "1.70 m"]); + }); +}); -describe('example', () => { - test('is a function', () => { - expect(typeof example).toBe('function'); +describe('weightOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof weightOfPokemon).toBe('function'); }); - test('returns `example`', () => { - expect(example()).toBe('example'); + test("weightOfPokemon con parámetros de weaknesses y Dragon debería devolver ['3.3 kg','16.5 kg','210.0 kg']", () => { + expect(weightOfPokemon("weaknesses", "Dragon")).toEqual(["3.3 kg", "16.5 kg", "210.0 kg"]); }); }); +describe('candyOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof candyOfPokemon).toBe('function'); + }); + + test("candyOfPokemon con parámetros de weaknesses y Dragon deberia devolver ['Dratini Candy','Dratini Candy','Dratini Candy']", () => { + expect(candyOfPokemon("weaknesses", "Dragon")).toEqual(["Dratini Candy", "Dratini Candy", "Dratini Candy"]); + }); +}); + +describe('candyCountOFPokemon', () => { + test("debería ser una función", () => { + expect(typeof candyCountOfPokemon).toBe('function'); + }); + + test("candyCountOfPokemon con parámetros de type y Ghost debería devolver [25,100,'No aplica']", () => { + expect(candyCountOfPokemon("type", "Ghost")).toEqual([25, 100, "No aplica"]); + }); +}); + +describe('weaknessesOfPokemon', () => { + test("debería ser una función", () => { + expect(typeof weaknessesOfPokemon).toBe('function'); + }); + + test('weaknessesOfPokemon con parámetros de type y Electric debería devolver [["Ground"],["Ground"],["Fire","Water","Ground"],["Fire","Water","Ground"],["Ground"],["Ground"],["Ground"],["Ground"],["Ice","Rock"]]', () => { + expect(weaknessesOfPokemon("type", "Electric")).toEqual([ + ["Ground"], + ["Ground"], + ["Fire", "Water", "Ground"], + ["Fire", "Water", "Ground"], + ["Ground"], + ["Ground"], + ["Ground"], + ["Ground"], + ["Ice", "Rock"] + ]); + }); +}); + +describe('nextEvolutionOfPokemon', () => { + test("debería ser una función", () => { + expect(typeof nextEvolutionOfPokemon).toBe('function'); + }); + + test('nextEvolutionOfPokemon con parámetros de type y Dragon debería devolver [[{"num": "148","name": "Dragonair"}, {"num": "149","name": "Dragonite"}],[{"num": "149","name": "Dragonite"}]]', () => { + expect(nextEvolutionOfPokemon("type", "Dragon")).toEqual([ + [{ + "num": "148", + "name": "Dragonair" + }, { + "num": "149", + "name": "Dragonite" + }], + [{ + "num": "149", + "name": "Dragonite" + }], undefined + ]); + }); +}); + +describe('sortData', () => { + test("debería ser una función", () => { + expect(typeof sortData).toBe('function'); + }); + + const untidyPoke = [{ + "id": 7, + "num": "007", + "name": "Squirtle", + "img": "http://www.serebii.net/pokemongo/pokemon/007.png", + "type": [ + "Water" + ], + "height": "0.51 m", + "weight": "9.0 kg", + "candy": "Squirtle Candy", + "candy_count": 25, + "egg": "2 km", + "spawn_chance": 0.58, + "avg_spawns": 58, + "spawn_time": "04:25", + "multipliers": [2.1], + "weaknesses": [ + "Electric", + "Grass" + ], + "next_evolution": [{ + "num": "008", + "name": "Wartortle" + }, { + "num": "009", + "name": "Blastoise" + }] + }, { + "id": 8, + "num": "008", + "name": "Wartortle", + "img": "http://www.serebii.net/pokemongo/pokemon/008.png", + "type": [ + "Water" + ], + "height": "0.99 m", + "weight": "22.5 kg", + "candy": "Squirtle Candy", + "candy_count": 100, + "egg": "Not in Eggs", + "spawn_chance": 0.034, + "avg_spawns": 3.4, + "spawn_time": "07:02", + "multipliers": [1.4], + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }], + "next_evolution": [{ + "num": "009", + "name": "Blastoise" + }] + }, { + "id": 9, + "num": "009", + "name": "Blastoise", + "img": "http://www.serebii.net/pokemongo/pokemon/009.png", + "type": [ + "Water" + ], + "height": "1.60 m", + "weight": "85.5 kg", + "candy": "Squirtle Candy", + "egg": "Not in Eggs", + "spawn_chance": 0.0067, + "avg_spawns": 0.67, + "spawn_time": "00:06", + "multipliers": null, + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }, { + "num": "008", + "name": "Wartortle" + }] + }]; + const tidyPoke = [{ + "id": 9, + "num": "009", + "name": "Blastoise", + "img": "http://www.serebii.net/pokemongo/pokemon/009.png", + "type": [ + "Water" + ], + "height": "1.60 m", + "weight": "85.5 kg", + "candy": "Squirtle Candy", + "egg": "Not in Eggs", + "spawn_chance": 0.0067, + "avg_spawns": 0.67, + "spawn_time": "00:06", + "multipliers": null, + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }, { + "num": "008", + "name": "Wartortle" + }] + }, + { + "id": 7, + "num": "007", + "name": "Squirtle", + "img": "http://www.serebii.net/pokemongo/pokemon/007.png", + "type": [ + "Water" + ], + "height": "0.51 m", + "weight": "9.0 kg", + "candy": "Squirtle Candy", + "candy_count": 25, + "egg": "2 km", + "spawn_chance": 0.58, + "avg_spawns": 58, + "spawn_time": "04:25", + "multipliers": [2.1], + "weaknesses": [ + "Electric", + "Grass" + ], + "next_evolution": [{ + "num": "008", + "name": "Wartortle" + }, { + "num": "009", + "name": "Blastoise" + }] + }, { + "id": 8, + "num": "008", + "name": "Wartortle", + "img": "http://www.serebii.net/pokemongo/pokemon/008.png", + "type": [ + "Water" + ], + "height": "0.99 m", + "weight": "22.5 kg", + "candy": "Squirtle Candy", + "candy_count": 100, + "egg": "Not in Eggs", + "spawn_chance": 0.034, + "avg_spawns": 3.4, + "spawn_time": "07:02", + "multipliers": [1.4], + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }], + "next_evolution": [{ + "num": "009", + "name": "Blastoise" + }] + } + ]; + const tidyPokeDownward = [{ + "id": 8, + "num": "008", + "name": "Wartortle", + "img": "http://www.serebii.net/pokemongo/pokemon/008.png", + "type": [ + "Water" + ], + "height": "0.99 m", + "weight": "22.5 kg", + "candy": "Squirtle Candy", + "candy_count": 100, + "egg": "Not in Eggs", + "spawn_chance": 0.034, + "avg_spawns": 3.4, + "spawn_time": "07:02", + "multipliers": [1.4], + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }], + "next_evolution": [{ + "num": "009", + "name": "Blastoise" + }] + }, { + "id": 7, + "num": "007", + "name": "Squirtle", + "img": "http://www.serebii.net/pokemongo/pokemon/007.png", + "type": [ + "Water" + ], + "height": "0.51 m", + "weight": "9.0 kg", + "candy": "Squirtle Candy", + "candy_count": 25, + "egg": "2 km", + "spawn_chance": 0.58, + "avg_spawns": 58, + "spawn_time": "04:25", + "multipliers": [2.1], + "weaknesses": [ + "Electric", + "Grass" + ], + "next_evolution": [{ + "num": "008", + "name": "Wartortle" + }, { + "num": "009", + "name": "Blastoise" + }] + }, { + "id": 9, + "num": "009", + "name": "Blastoise", + "img": "http://www.serebii.net/pokemongo/pokemon/009.png", + "type": [ + "Water" + ], + "height": "1.60 m", + "weight": "85.5 kg", + "candy": "Squirtle Candy", + "egg": "Not in Eggs", + "spawn_chance": 0.0067, + "avg_spawns": 0.67, + "spawn_time": "00:06", + "multipliers": null, + "weaknesses": [ + "Electric", + "Grass" + ], + "prev_evolution": [{ + "num": "007", + "name": "Squirtle" + }, { + "num": "008", + "name": "Wartortle" + }] + }]; + + test('sortData con parámetros de aToZ debería devolver los pokémon ordenado por nombre descendente', () => { + expect(sortData(untidyPoke, "name", "aToZ")).toEqual(tidyPoke); + }); -describe('anotherExample', () => { - test('is a function', () => { - expect(typeof anotherExample).toBe('function'); + test('sortData con parámetros de zToA debería devolver los pokémon ordenado por nombre de la Z a la A', () => { + expect(sortData(untidyPoke, "name", "zToA")).toEqual(tidyPoke.reverse()); }); - test('returns `anotherExample`', () => { - expect(anotherExample()).toBe('OMG'); + test('sortData con parámetros de zToA debería devolver los pokémon ordenado por nombre de la Z a la A', () => { + expect(sortData(untidyPoke, "name", "zToA")).toEqual(tidyPokeDownward); }); });