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/README.md b/README.md index 0e78340d..722a3d6c 100644 --- a/README.md +++ b/README.md @@ -1,166 +1,108 @@ -# Data Lovers +
+ + + +# Proyecto Data Lovers DEV009 +## Rick and Morty + +Puedes ver el proyecto finalizado [aquí](https://raudelgado.github.io/DEV009-data-lovers/) ## Í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) +* [1. Nuestro Proyecto](#1-nuestro-proyecto) +* [2. Historias de Usuario](#2-historias-de-usuario) +* [3. Diseño de Interfaz de Usuario](#3-diseño-de-interfaz-de-usuario) +* [4. Test de Usabilidad](#4-test-de-usabilidad) +* [5. Objetivos de Aprendizaje](#5-objetivos-de-aprendizaje) +* [6. Proyecto finalizado](#6-proyecto-finalizado) -*** +## 1. Nuestro proyecto -## 1. Preámbulo +Este segundo proyecto perteneciente a la cohort DEV009, tenía como objetivo el construir una página web con cierta data para que los usuarios pudieran visualizarla. -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. +En nuestro caso, escogimos **Rick and Morty** para esta data, por lo que nos enfocamos en usuarios que observaran esta serie. -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_. +En base a ellos, y con ayuda de una encuesta, trabajamos nuestras Historias de Usuario para así crear una página web útil, y además, responsive. -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. -![pokemon-data-to-ui](https://user-images.githubusercontent.com/12631491/218505816-c6d11758-9de4-428f-affb-2a56ea4d68c4.png) +## 2. Historias de Usuario -## 2. Resumen del proyecto +Luego de realizar la encuesta correspondiente, analizamos los resultados para así llegar a cuatro historias de usuario: -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). +#### Primera Historia de Usuario -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. +> "Yo como usuario, quiero visualizar los datos de los personajes de Rick y Morty, para tener un orden de la serie" -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. +#### Segunda Historia de Usuario -Estos son datos que te proponemos: +> "Yo como usuario, quiero filtrar los datos de los personajes de Rick y Morty, para visualizar los datos en específico que se desee consultar" -* [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 - [Pokémon GO](http://pokemongolive.com). - - [Investigación con jugadores de Pokémon Go](src/data/pokemon/README.md) +#### Tercera Historia de Usuario -* [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) +> "Yo como usuario, quiero ordenar los datos de los personajes de Rick y Morty, para obtener la información rápidamente." -* [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) +#### Cuarta Historia de Usuario -* [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) +> "Yo como usuario, quiero saber, a través de un porcentaje, como se divide los personajes del universo de la serie" -* [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) +## 3. Diseño de Interfaz de Usuario -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. +### Prototipo de baja fidelidad. -## 3. Objetivos de aprendizaje +Al tener las cuatro historias de Usuario empezamos con el prototipo de baja fidelidad: -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. +Prototipo de baja fidelidad -### HTML +### Prototipo de alta fidelidad -- [ ] **Uso de HTML semántico** +Al tener esto, empezamos a iterar las distintas opciones para que nuestro proyecto se fuera encaminando a lo que habíamos diseñado -
Links

+**Vista completa** - * [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) -

+Prototipo de Alta fidelidad -### CSS +**Vista desktop** -- [ ] **Uso de selectores de CSS** +Prototipo de Alta fidelidad/Desktop -
Links

+**Vista Android** - * [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) -

+Prototipo de Alta fidelidad/Android -- [ ] **Modelo de caja (box model): borde, margen, padding** +Puedes ver nuestro Figma [aquí](https://www.figma.com/proto/wPeetqLIez79gNBU77c0Vl/Prototipo-de-alta-fidelidad?type=design&node-id=144-103&t=AsGXROdn6ArSImXI-1&scaling=scale-down&page-id=0%3A1&mode=design) -
Links

+## 4. Test de Usabilidad - * [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/) -

+Al principio, decidimos hacer una prueba de testeo con nuestro prototipo de baja, entendiendo si la cantidad de botones que esperabamos agregar eran simplemente demasiado. -- [ ] **Uso de flexbox en CSS** +Cuando le hicimos los test de usabilidad con el prototipo de Alta Fidelidad tuvimos varios comentarios, el más destacado: -
Links

+* Al desplegar un select, los option que no seleccionabamos quedaban muy oscuros a comparación del resto. - * [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) -

+Esto lo volvimos a comprobar al realizar nuestro test en el deploy, donde ajustamos las tonalidades del option para que así se pudiese leer mucho mejor sin necesidad de estar seleccionado. -### Web APIs +## 5. Objetivos de Aprendizaje + +### HTML -- [ ] **Uso de selectores del DOM** +- [ ] **Uso de HTML semántico** -
Links

+### CSS - * [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) -

+- [ ] **Uso de selectores de CSS** -- [ ] **Manejo de eventos del DOM (listeners, propagación, delegación)** +- [ ] **Modelo de caja (box model): borde, margen, padding** -
Links

+- [ ] **Uso de flexbox en CSS** - * [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) -

+### Web APIs -- [ ] **Manipulación dinámica del DOM** +- [ ] **Uso de selectores del DOM** -
Links

+- [ ] **Manejo de eventos del DOM (listeners, propagación, delegación)** - * [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) -

+- [ ] **Manipulación dinámica del DOM** ### JavaScript @@ -168,73 +110,20 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t - [ ] **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)** -
Links

- - * [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) -

- - [ ] **Uso de bucles/ciclos (while, for, for..of)** -
Links

- - * [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) -

- - [ ] **Funciones (params, args, return)** -
Links

- - * [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) -

- - [ ] **Pruebas unitarias (unit tests)** -
Links

- - * [Empezando con Jest - Documentación oficial](https://jestjs.io/docs/es-ES/getting-started) -

- - [ ] **Módulos de ECMAScript (ES Modules)** -
Links

- - * [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) -

- - [ ] **Uso de linter (ESLINT)** - [ ] **Uso de identificadores descriptivos (Nomenclatura y Semántica)** @@ -253,373 +142,27 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t - [ ] **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). - -### 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. - -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_. - -#### Testeos de usabilidad - -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. - -### 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 - -Como mínimo, tu implementación debe: +#### Herramientas -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_. +* Git +* GitHub +* GitHub Pages +* Node.js +* Jest -### Pruebas unitarias +## 6. Proyecto finalizado -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. +**Vista final** -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). +Vista Final -## 6. Hacker edition +**Test Unitarios** -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. +Test Unitarios -Features/características extra sugeridas: +#### Desarrolladoras -* 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 - -## 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. - -El _boilerplate_ contiene una estructura de archivos como punto de partida así -como toda la configuración de dependencias: - -```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 -| | └── rickandmorty -| | | ├── rickandmorty.js -| | | ├── rickandmorty.json -| | | └── README.md -| | └── athletes -| | | ├── athletes.js -| | | ├── athletes.json -| | | └── README.md -| | └── ghibli -| | | ├── ghibli.js -| | | ├── ghibli.json -| | | └── README.md -| ├── data.js -| ├── index.html -| ├── main.js -| └── style.css -└── test - └── data.spec.js - -directory: 7 file: 20 -``` - -### `src/index.html` - -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/main.js` - -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_), .... - -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. - -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. - -Por ejemplo, si "descomentamos" la siguiente línea: - -```js -// import data from './data/lol/lol.js'; -``` - -La línea quedaría así: - -```js -import data from './data/lol/lol.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. - -* `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 ` + + + + + +
+
+ +
+
+ +
+ +
+

Status

+ +
+ + +
+

Species

+ +
+ +
+

Gender

+ +
+ +
+

Order

+ +
+ +
+ +

+
+ +
+ +
+

+
+ + +
+
+
+ + +
+ + + + + + diff --git a/src/main.js b/src/main.js index 71c59f2d..e928472e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,152 @@ -import { example } from './data.js'; +import {filteredStatus, filteredSpecies, filteredGender, filteredSearch, filteredOrder, porcentajeCalculo } from './data.js'; //importar funciones de filtrado de data.js // import data from './data/lol/lol.js'; -import data from './data/pokemon/pokemon.js'; +import data from './data/rickandmorty/rickandmorty.js'; // import data from './data/rickandmorty/rickandmorty.js'; -console.log(example, data); +//Escuchar los eventos del DOM - escuchar el evento de hacer click en la opcion +/* seleccionar el id del select +escuchar el evento change +declarar constante con el valor del select +declarar una constante que usar la función para filtrar la data y la compara con la opción seleccionada +llamar función crear tarjetas y darle los datos filtrados +*/ +//Status +const selectStatus= document.getElementById("status") +selectStatus.addEventListener("change", () => { + const optionStatus = selectStatus.value; + const filterStatus = filteredStatus(data.results, optionStatus); + crearTarjetas(filterStatus); + const porcentajeStatus = porcentajeCalculo(filterStatus); + if (optionStatus === "All"){ + crearTarjetaAll() + } else { + crearTarjetaPorcentaje(porcentajeStatus); + } +}); + +//Species +const selectSpecies= document.getElementById("species"); +selectSpecies.addEventListener("change", () => { + const optionSpecies = selectSpecies.value; + const filterSpecies = filteredSpecies(data.results, optionSpecies); + crearTarjetas(filterSpecies); + const porcentajeSpecies = porcentajeCalculo(filterSpecies); + if (optionSpecies === "All"){ + crearTarjetaAll() + } else{ + crearTarjetaPorcentaje(porcentajeSpecies); + } + +}); + +//Gender +const selectGender = document.getElementById("gender"); +selectGender.addEventListener("change", () => { + const optionGender = selectGender.value; + const filterGender = filteredGender(data.results, optionGender); + crearTarjetas(filterGender); + const porcentajeGender = porcentajeCalculo(filterGender); + if (optionGender === "All"){ + crearTarjetaAll() + } else{ + crearTarjetaPorcentaje(porcentajeGender); + } + +}); + +//Order +const selectOrder= document.getElementById("order"); +selectOrder.addEventListener("change", () => { + const optionOrder = selectOrder.value; + if (optionOrder === "All"){ + crearTarjetas(data.results); + } else { + const filterOrder = filteredOrder(data.results, optionOrder); + crearTarjetas(filterOrder); + } + crearTarjetaEnBlanco(); + +}); + +//Search +const optionSearch= document.getElementById("search") +optionSearch.addEventListener("keyup", () => { + const searchInput = optionSearch.value; + const searchOutput = filteredSearch(data.results, searchInput); + crearTarjetas (searchOutput); + crearTarjetaEnBlanco(); +}); + + +//crear una funcion que cree los li +//Crear los nodos + +const tarjetas = document.getElementById("divLista") // seleccionar el div padre +crearTarjetas(data.results); +function crearTarjetas(arregloTarjetas){ + + tarjetas.innerHTML = ""; //limpiar tarjetas previas + for (let i = 0; i < arregloTarjetas.length; i++){ + const tarjeta = arregloTarjetas[i]; + + //creando los nodos + const creaLi = document.createElement("li"); + //crear cards + const cardContent = document.createElement("div"); + cardContent.classList.add("card-content"); //agregar clase + + //agregar nombre - crear elementos y establecer contenido + const nameElement = document.createElement("h3"); + nameElement.textContent = "Name: " + tarjeta.name ; + //agregar status + const statusElement = document.createElement("p"); + statusElement.textContent = "Status: " + tarjeta.status; + //agregar species + const statusSpecies = document.createElement("p"); + statusSpecies.textContent = "Species: " + tarjeta.species; + //agregar type + const statusType = document.createElement("p"); + statusType.textContent = "Type: " + tarjeta.type; + //agregar gender + const statusGender = document.createElement("p"); + statusGender.textContent = "Gender: " + tarjeta.gender; + //agregar origin.name + const statusOriginName = document.createElement("p"); + statusOriginName.textContent = "Origin: " + tarjeta.origin.name; + //agregar location.name + const statusLocationName = document.createElement("p"); + statusLocationName.textContent = "Location: " + tarjeta.location.name; + //agregar imagen + const statusImagen = document.createElement("img"); + statusImagen.src = tarjeta.image; + + + //agregar los elementos a la tarjeta + cardContent.appendChild(nameElement); + cardContent.appendChild(statusElement); + cardContent.appendChild(statusSpecies); + cardContent.appendChild(statusType); + cardContent.appendChild(statusGender); + cardContent.appendChild(statusOriginName); + cardContent.appendChild(statusLocationName); + cardContent.appendChild(statusImagen); + + //agregar el contenido de la tarjeta a la lista + creaLi.appendChild(cardContent); + tarjetas.appendChild(creaLi); //agregar el nodo Li al div padre (ul) + } +} +function crearTarjetaPorcentaje(porcentaje){ + const selectPorcentaje = document.getElementById("pPorcentaje"); + selectPorcentaje.innerHTML = "Esta categoria contiene: " + porcentaje + "% de los personajes totales"; +} + +function crearTarjetaEnBlanco(){ + const selectPorcentajeEnBlanco = document.getElementById("pPorcentaje"); + selectPorcentajeEnBlanco.innerHTML = " "; +} + +function crearTarjetaAll(){ + const selectPorcentajeAll = document.getElementById("pPorcentaje"); + selectPorcentajeAll.innerHTML = "Se muestran todos los datos"; +} \ No newline at end of file diff --git a/src/protodesktop.png b/src/protodesktop.png new file mode 100644 index 00000000..de677e93 Binary files /dev/null and b/src/protodesktop.png differ diff --git a/src/prototelf.png b/src/prototelf.png new file mode 100644 index 00000000..d455dad3 Binary files /dev/null and b/src/prototelf.png differ diff --git a/src/rickandmorty.png b/src/rickandmorty.png new file mode 100644 index 00000000..a393852a Binary files /dev/null and b/src/rickandmorty.png differ diff --git a/src/style.css b/src/style.css index e69de29b..5b7e28e9 100644 --- a/src/style.css +++ b/src/style.css @@ -0,0 +1,194 @@ +* { + background-color: #20222c; + font-family: 'Quicksand', sans-serif; +} + +header { + display: flex; + justify-content: center; + margin-top: 30px; + margin-bottom: 30px; + font-family: 'Quicksand', sans-serif; +} + +#contenedor { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 40px; + gap: 30px; +} + +option { +background-color: #b2dd87; +font-weight: 500; +} + + +p { + text-align: center; +} + +.options { + background-color: #82BF45; + margin-bottom: 3px; + padding-bottom: 3px; + padding-left: 4px; + font-family: 'Quicksand', sans-serif; + font-weight: 700; + display: inline-block; + border-radius: 10px; +} + +.selection1{ + background-color: #82BF45; + margin-left: 7px; +} + +.selection2{ + background-color: #82BF45; + margin-left: 0.9px; +} + +.selection4{ + background-color: #82BF45; + margin-left: 7px; +} + +.selection5{ + background-color: #82BF45; + margin-left: 25px; +} + +.selection{ + background-color: #82BF45; + margin-top: 10px; +} + +.letras { + color:black; + background-color: #82BF45; + padding-bottom: 1px; + margin-bottom: 10px; + padding-left: 10px; + margin-left: 10px; + padding-top: 2px; + margin-top: 3px; + margin: 0 auto; +} + +.optionlight { + background-color: #82BF45; + color: black; + display: inline-block; + border-radius: 10px; +} + +.caja { + height: 60px; + width: 100px; + margin: 10px; + padding-top: 8px; +} + +.cajaSpecies { + height: 60px; + width: 130px; + margin: 10px; + padding-top: 8px; +} + +.cajagrande { + height: 50px; + width: 200px; + margin: 10px; + padding: 10px; +} + +::placeholder{ + color: #4B4B4B; +} + +.footer { + color: black; + background-color: #82BF45; + text-align: center; +} + +.fa-instagram { + display: inline-block; +} + +#nombres { + display: inline-block; + +} + +.lupita{ + margin-right: 7px; + margin-left: 12px; + font-weight: 500; +} + +#divLista{ + color: #FFF1A7; + display: flex; + flex-wrap: wrap; /* para que las tarjetas se puedan poner en filas*/ + justify-content: space-between; + list-style: none; /*quitar los puntos de los li*/ +} + +.card-content{ + background-color: #FFF1A7; + width: calc(90% - 10px); /* ancho de cada tarjeta con espacio de 10px entre tarjetas*/ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + margin-bottom: 20px; + padding: 15px; + border-radius: 10px; + +} + +.card-content img { + order: -1; + max-width: 90%; + height: auto; + border: #1C2140 solid 3px; + border-radius: 10px; +} + +.card-content h3 { + font-size: 20px; + color: black; + background-color: transparent; +} + +.card-content p { + font-size: 16px; + color: black; + background-color: transparent; +} + +#pPorcentaje{ + color: #82BF45; +} + +@media only screen and (max-width:800px) { +#contenedor { + flex-direction: column; + align-items: center; + justify-content: center; + } + +#imageRickAndMorty { + width: 70%; +} + +.card-content { + margin-left: 5%; +} + +} \ No newline at end of file diff --git a/src/testu.png b/src/testu.png new file mode 100644 index 00000000..bdf82812 Binary files /dev/null and b/src/testu.png differ diff --git a/test/data.spec.js b/test/data.spec.js index 09b1f23f..d438b69c 100644 --- a/test/data.spec.js +++ b/test/data.spec.js @@ -1,23 +1,371 @@ -import { example, anotherExample } from '../src/data.js'; +import {filteredStatus, filteredSpecies, filteredGender, filteredOrder, filteredSearch, porcentajeCalculo} from '../src/data.js'; + +const arrayTestData = [ + { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }, + { + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; -describe('example', () => { - it('is a function', () => { - expect(typeof example).toBe('function'); +describe('test para filtrar status', () => { + it('test para validar status alive de los personajes', () => { + const statusAlive = 'Alive' + //const dataStatusAlive = arrayTestData + const resultadoEsperadoAlive = [ + { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredStatus (arrayTestData, statusAlive)).toEqual(resultadoEsperadoAlive) }); + it('test para validar el status dead de los personajes', () => { + const statusDead = 'Dead' + //const dataStatusDead = arrayTestData.status; + const resultadoEsperadoDead = [ + { + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }] + expect(filteredStatus(arrayTestData, statusDead)).toEqual(resultadoEsperadoDead) + }); + it('test para validar que se ha seleccionado All', () => { + const statusAll = 'All'; + const resultadoStatusEsperadoAll = [ { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }, + { + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredStatus(arrayTestData, statusAll)).toEqual(resultadoStatusEsperadoAll); + }); +}); - it('returns `example`', () => { - expect(example()).toBe('example'); + +describe('tests de filter species', () => { + //test Alien + it('test para validar que species es Alien', () => { + const speciesOpcionPruebaAlien = 'Alien'; + //const datasetPruebaAlien = []; + const resultadoEsperadoAlien = [{ + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredSpecies (arrayTestData, speciesOpcionPruebaAlien)).toEqual(resultadoEsperadoAlien); + }); + it('test para validar que species es Human', () => { + const speciesOpcionPruebaHuman = 'Human'; + //const datasetCronenberg = ; + const resultadoEsperadoHuman = [ { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }]; + expect(filteredSpecies(arrayTestData, speciesOpcionPruebaHuman)).toEqual(resultadoEsperadoHuman); + }); + it('test para validar que se ha seleccionado All', () => { + const speciesOpcionAll = 'All'; + //const datasetCronenberg = ; + const resultadoEsperadoAll = [ { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }, + { + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredSpecies(arrayTestData, speciesOpcionAll)).toEqual(resultadoEsperadoAll); }); }); -describe('anotherExample', () => { - it('is a function', () => { - expect(typeof anotherExample).toBe('function'); +describe('tests de filter gender', () => { + it('debe devolver un error si la data es undefined', () => { + const gender = 'Male'; + const input = undefined; + expect(() =>filteredGender (input, gender)).toThrow('La data es incorrecta') + }); + it('test para validar gender Male de los personajes', () => { + const genderMale = 'Male' + // const dataGenderMale = 'Male' + const resultadoEsperadoMale = [{ + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }]; + expect(filteredGender (arrayTestData, genderMale)).toEqual(resultadoEsperadoMale); + }); + it('test para validar gender Female de los personajes', () => { + const genderFemale = 'Female' + const resultadoEsperadoFemale = [{ + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }]; + expect(filteredGender (arrayTestData, genderFemale)).toEqual(resultadoEsperadoFemale); + }); + it('test para validar gender unkwown de los personajes', () => { + const genderUnknown = 'unknown' + const resultadoEsperadoUnknown = [{ + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredGender (arrayTestData, genderUnknown)).toEqual(resultadoEsperadoUnknown); + }); + it('test para validar que se ha seleccionado All', () => { + const genderAll = 'All'; + const resultadoGenderEsperadoAll = [ { + "name": "Summer Smith", + "status": "Alive", + "species": "Human", + "gender": "Female", + }, + { + "name": "Amish Cyborg", + "status": "Dead", + "species": "Alien", + "gender": "Male", + }, + { + "name": "Bepisian", + "status": "Alive", + "species": "Alien", + "gender": "unknown", + }]; + expect(filteredGender(arrayTestData, genderAll)).toEqual(resultadoGenderEsperadoAll); + }); +}); + +describe('test para filtrar por orden', () => { + it('test para filtrar en orden ascendente', () => { + const order = 'AZ' + const orderAsc = [{ + "name": "Secretary of the Interior", + }, + { + "name": "Loggins", + }, + { + "name": "Abradolf Lincler", + }]; + const orderEsperado = [ + { + "name": "Abradolf Lincler", + }, + { + "name": "Loggins", + }, + { + "name": "Secretary of the Interior", + } + ]; + expect(filteredOrder(orderAsc, order)).toEqual(orderEsperado); }); + it('test para filtrar en orden descendente', () => { + const order = 'ZA' + const orderDesc = [ + { + "name": "Abradolf Lincler", + }, + { + "name": "Loggins", + }, + { + "name": "Secretary of the Interior", + }]; + const orderEsperadoDesc = [ + { + "name": "Secretary of the Interior", + }, + { + "name": "Loggins", + }, + { + "name": "Abradolf Lincler", + }, + + ] + expect(filteredOrder(orderDesc, order)).toEqual(orderEsperadoDesc); + }); + it('test para comprobar si tiene un undefined', () => { + const order = 'AZ' + const orderUndefined = [ + { + "name": "Secretary of the Interior", + }, + { + "name": "Loggins", + }, + { "name": undefined + }, + { + "name": "Abradolf Lincler", + }, + ]; + const orderEsperadoUndefined = [ + { + "name": "Abradolf Lincler", + }, + { + "name": "Loggins", + }, + { + "name": "Secretary of the Interior", + }, + { "name": undefined + } + ]; + expect(filteredOrder(orderUndefined, order)).toEqual(orderEsperadoUndefined); + }); + it('test para comprobar si tiene un undefined orden descendente', () => { + const order = 'ZA' + const orderUndefinedDesc = [ + { + "name": "Abradolf Lincler", + }, + { + "name": "Loggins", + }, + { "name": undefined + }, + { + "name": "Secretary of the Interior", + }, + ]; + const orderEsperadoUndefinedDesc = [ + { + "name": "Secretary of the Interior", + }, + { + "name": "Loggins", + }, + { + "name": "Abradolf Lincler", + }, + { "name": undefined + } + ]; + expect(filteredOrder(orderUndefinedDesc, order)).toEqual(orderEsperadoUndefinedDesc); + }); +}); - it('returns `anotherExample`', () => { - expect(anotherExample()).toBe('OMG'); +describe('test para buscar en el proyecto', () => { + it('test para buscar un personaje', () => { + //const search = "ri"; + const searchData = [ + { "name": "Secretary of the Interior"}, + { "name": "Rick Sanchez" }, + { "name": "Abradolf Lincler"} + ]; + const searchDataEsperado = filteredSearch(searchData, "ric"); + expect(searchDataEsperado).toEqual([{name: "Rick Sanchez"}]); + }); + it('test para buscar un personaje con undefined', () => { + //const search = "ri"; + const searchDataUndefined = [ + { "name": "Secretary of the Interior"}, + { "name": "Rick Sanchez" }, + { "name": "Abradolf Lincler"}, + { "name": undefined} + ]; + const searchDataEsperadoUndefined = filteredSearch(searchDataUndefined, "ric"); + expect(searchDataEsperadoUndefined).toEqual([{name: "Rick Sanchez"}]); }); }); + +describe('tests de porcentaje', () => { + it('test para validar que array con 10 objetos con status "Alive" es 2.03%', () => { + const porcentaje10objetosStatusAlive = [ + {"name": "Rick Sanchez", + "status": "Alive"}, + {"name": "Morty Smith", + "status": "Alive"}, + {"name": "Summer Smith", + "status": "Alive"}, + {"name": "Beth Smith", + "status": "Alive"}, + {"name": "Jerry Smith", + "status": "Alive"}, + {"name": "Abadango Cluster Princess", + "status": "Alive"}, + {"name": "Annie", + "status": "Alive"}, + {"name": "Antenna Morty", + "status": "Alive"}, + {"name": "Armagheadon", + "status": "Alive"}, + {"name": "Arthricia", + "status": "Alive"} + ]; + const resultadoEsperadoPorcentaje = "2.03"; + expect(porcentajeCalculo (porcentaje10objetosStatusAlive)).toBe(resultadoEsperadoPorcentaje); + }); +}); + + + + + + + + + +