diff --git a/README.md b/README.md index 7825c572..1058a295 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,96 @@ -# 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](#9-checklist) - -*** - -## 1. Preámbulo - -Según [Forbes](https://www.forbes.com/sites/bernardmarr/2018/05/21/how-much-data-do-we-create-every-day-the-mind-blowing-stats-everyone-should-read), -el 90% de la data que existe hoy ha sido creada durante los últimos dos años. -Cada día generamos 2.5 millones de terabytes de datos, una cifra sin -precedentes. - -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. Resumen del proyecto - -En este proyecto **construirás una _página web_ para visualizar un -_conjunto (set) de datos_** que se adecúe a lo que descubras que tu usuario -necesita. - -Como entregable final tendrás una página web que permita **visualizar la data, -filtrarla, ordenarla y hacer algún cálculo agregado**. Con cálculo agregado -nos referimos a distintos cálculos que puedes hacer con la data para mostrar -información aún más relevante para los usuarios (promedio, el valor máximo -o mínimo, etc). - -Esta vez te proponemos una serie de datos de diferentes _temáticas_ para que -explores y decidas con qué temática te interesa trabajar. Hemos elegido -específicamente estos sets de datos porque creemos que se adecúan bien a esta -etapa de tu aprendizaje. - -Una vez que definas tu área de interés, buscar entender quién es tu usuario -y qué necesita saber o ver exactamente; luego podrás construir la interfaz que -le ayude a interactuar y entender mejor esos datos. - -Estos son datos que te proponemos: - -* [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) - -* [League of Legends - Challenger leaderboard](src/data/lol/lol.json): - Este set de datos muestra la lista de campeones en una liga del - juego League of Legends (LoL). - - [Investigación con jugadores de LoL](src/data/lol/README.md) - -* [Rick and Morty](src/data/rickandmorty/rickandmorty.json). - Este set nos proporciona la lista de los personajes de la serie Rick and - Morty. - - [Investigación con seguidores de Rick and Morty](src/data/rickandmorty/README.md) - -* [Juegos Olímpicos de Río de Janeiro](src/data/athletes/athletes.json). - Este set nos proporciona la lista de los atletas que ganaron medallas en las - olímpiadas de Río de Janeiro. - - [Investigación con interesados en juegos olímpicos de Río de Janeiro](src/data/athletes/README.md) - -* [Studio Ghibli](src/data/ghibli/ghibli.json). - En este set encontrarás una lista de las animaciones y sus personajes del - [Studio Ghibli](https://ghiblicollection.com/). - - [Investigación con seguidores de las animaciones del Studio Ghibli](src/data/ghibli/README.md) - -* [Harry Potter](src/data/harrypotter/harry.json). - En este set encontrarás una lista de los personajes,libros pociones - y hechizos de toda la saga de - [Harry Potter](https://harrypotter.fandom.com). - - [Investigación con seguidoras de Harry Potter](src/data/harrypotter/README.md) - -El objetivo principal de este proyecto es que aprendas a diseñar y construir una -interfaz web donde se pueda visualizar y manipular data, entendiendo lo que el -usuario necesita. - -## 3. Objetivos de aprendizaje +# Studio Ghibli + +## Descripción +La pagina de Studio ghibli se ha creado con la finalidad de proporcionar información detallada y actualizada sobre sus animaciones .Esto será beneficioso tanto para los fanáticos de la animación como para los investigadores y críticos de cine.interesados en conocer más sobre la obra de esta casa productora. +La pagina es dinamica y te permite: + +1) Mostrar información sobre las animaciones de Studio Ghibli y sus personajes, como el título, el director, el productor, la fecha de lanzamiento, la puntuación de Rotten Tomatoes e información sobre los personajes, como sus nombres, edad, género y especie. + +2) Mostrar las 10 mejores animaciones de Studio Ghibli según su puntuación en Rotten Tomatoes, un botón para mostrar los personajes de cada animación y botones para mostrar ubicaciones y vehículos relacionados con cada animación. + +3) Calcular y muestrar la puntuación media de Rotten Tomatoes de todas las animaciones de Studio Ghibli. + +En general, la pagina web proporciona una interfaz para que los usuarios exploren y aprendan sobre las animaciones de Studio Ghibli y sus personajes, ubicaciones y vehículos relacionados. + +## 1. Historias de Usuario +Primeras versiones de las historias de usuario que diseñamos en cada sprint + +

+

+ + +## 2. Criterios de aceptacion y determinado + +

+

+ +## 3. Prototipos de baja fidelidad +

+

+ +## 4. Prototipo de alta +

+ +

+ +### 5. Implementación de la Interfaz de Usuario (HTML/CSS/JS) +

+ +

+ +## 6. Resumen del proyecto +

Objetivos:

+Este es un proyecto que tiene como objetivo mostrar información sobre películas del Studio Ghibli. A continuación, se detallan las funciones disponibles en el proyecto.
+

Funciones


+filterOfdata(data, id) +Esta función filtra la información de las películas y devuelve un objeto con el título y los personajes de la película que corresponde con el id proporcionado. + +filterOfdata2(data, id)
+Esta función filtra la información de las películas y devuelve un array con los vehículos de la película que corresponde con el id proporcionado. + +filterOfdata3(data, id)
+Esta función filtra la información de las películas y devuelve un array con las locaciones de la película que corresponde con el id proporcionado. + + sortData(data)
+Esta función ordena la información de las películas por fecha de lanzamiento, de más reciente a más antigua. + + sortData2(data)
+Esta función ordena la información de las películas alfabéticamente por título, de la A a la Z. + + sortData3(data)
+Esta función ordena la información de las películas por fecha de lanzamiento, de más antigua a más reciente. + + sortData4(data)
+Esta función ordena la información de las películas alfabéticamente por título, de la Z a la A. + + calculoData(data)
+Esta función calcula el promedio de las calificaciones (rt_score) de todas las películas. + + filterMoviesByScore(data, topScore)
+Esta función filtra las películas por una puntuación mínima (topScore) y devuelve un array con las 10 películas con las puntuaciones más altas, ordenadas de mayor a menor. + +## 7. Proyecto: + +https://kellyfabiolafc.github.io/DEV004-data-lovers/src/ + +## 8. Contribuidores +Kelly Flores(floresdelacruzkellyfabiola@gmail.com)
+Alexa Suarez(alexas1903@gmail.com) + +## 9. Pruebas unitarias + +

Uso:


+La primera prueba es verificar si la filterOfdatafunción devuelve correctamente el título y los personajes de una película con una identificación específica.
+La segunda prueba es verificar si la filterOfdata2función devuelve correctamente los vehículos de una película con una identificación específica.
+La tercera prueba es verificar si la filterOfdata3función devuelve correctamente las ubicaciones de una película con una identificación específica.
+La cuarta prueba es verificar si la sortDatafunción clasifica correctamente una serie de objetos de películas en orden ascendente y descendente por fecha de lanzamiento.
+La quinta prueba es verificar si la sortData2función clasifica correctamente una matriz de objetos de película en orden ascendente por título.
+La sexta prueba es verificar si la sortData3función clasifica correctamente una serie de objetos de películas en orden ascendente y descendente por fecha de lanzamiento.
+La séptima prueba es verificar si la sortData4función clasifica correctamente una matriz de objetos de película en orden descendente por título.
+La octava prueba es comprobar si la calculoDatafunción calcula correctamente la puntuación media de todas las películas.
+La novena prueba está verificando que la función filterMoviesByScore filtre correctamente las películas que superan el promedio general y devuelva un nuevo arreglo con estas películas. + +## 9. Objetivos de aprendizaje Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en tu proyecto. Piensa en eso al decidir tu estrategia de trabajo. @@ -280,89 +285,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [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 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 4 semanas. -## 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: - -1. Mostrar la data en una interfaz: puede ser un card, una tabla, una lista, - etc. -2. Ser _responsive_, es decir, debe visualizarse sin problemas desde distintos - tamaños de pantallas: móviles, tablets y desktops. -3. Que la interfaz siga los fundamentos de _visual design_. - -### Pruebas unitarias - -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. - -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). ### Checklist @@ -384,197 +307,6 @@ en la sección de [Consideraciones técnicas](#srcdatajs). * [ ] UI: Permite filtrar data en base a una condición. * [ ] UI: Es _responsive_. -## 6. Hacker edition - -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. - -Features/características extra sugeridas: - -* 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 ` diff --git a/src/main.js b/src/main.js index 71c59f2d..c2e3836f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,285 @@ -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'; +/*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*/ +import data from "./data/ghibli/ghibli.js"; +import { + filterOfdata, + filterOfdata2, + filterOfdata3, + sortData, + sortData2, + sortData3, + sortData4, + calculoData, + filterMoviesByScore, +} from "./data.js"; +// Se crea una funcion para mostrar las animaciones y para insertar sus informaciones +const mostrarAnimaciones = (data) => { + const buttonTop10= document.getElementById("top-10"); + buttonTop10.classList.remove("top10oculto"); + const volver = document.getElementById("btnvolver"); + volver.classList.add("volveroculto"); + const selectvolver=document.getElementById("ordenar"); + selectvolver.classList.remove("selectOculto");//select oculto gracias a la clase CSS "volveroculto". + const peliculasContainer = document.querySelector(".main-container"); + peliculasContainer.innerHTML = ""; + const h1 = document.getElementById("Anuncio"); + h1.textContent = ""; + for (const pelicula of data) { + //se utiliza el ciclo con sintaxis for of para recorrer el objeto iterable + const peliculaElem = document.createElement("section"); + peliculaElem.className = "contenedorHijo"; //agregamos una clase al elemento creado y abajo usamos template string para + peliculaElem.innerHTML = ` +

${pelicula.title}

+
+ ${pelicula.title} +
+

${pelicula.description}

+

Director: ${pelicula.director}

+

Productor: ${pelicula.producer}

+

Año de lanzamiento: ${pelicula.release_date}

+

Puntuación de Rotten Tomatoes: ${pelicula.rt_score}

+
+ + + +
+
+
+ + `; + peliculaElem.addEventListener("mouseenter", () => { + //agregamos un escuchador de eventos para agregar el evento mouseenter y mostrar lo que esta volveroculto + peliculaElem.querySelector(".info").style.display = "block"; + }); + peliculaElem.addEventListener("mouseleave", () => { + // hacemos lo mismo que arriba solo que este evento ocurrira cuando el cursor se quite del elemento antes seleccionado + peliculaElem.querySelector(".info").style.display = "none"; + }); + peliculasContainer.appendChild(peliculaElem); + // seleccionamos todos los botones de las animaciones creadas y los recorremos. -console.log(example, data); + + + peliculaElem.querySelectorAll(".btnpersonajes").forEach((btn) => { + btn.addEventListener("click", function (e) { + // Por cada boton iterado se activara un addeventlis + volver.classList.remove("volveroculto"); //eliminamos la clase + selectvolver.classList.add("selectOculto"); + const characterContainer = document.querySelector(".main-container"); + characterContainer.innerHTML = ""; + const h1 = document.getElementById("Anuncio"); + h1.addEventListener("mouseenter", function () { + document.getElementById("AnuncioPromedio").style.display = "none"; + }); + //target se refiere al elemento que desencadenó el evento, es decir, el botón en sí mismo. + //La propiedad id de e.target se utiliza para obtener el valor del atributo id del botón que se ha hecho clic. + const personajes = filterOfdata(data, e.target.id); // Este filtro devuelve un nuevo arreglo de personajes + // e.target.id para identificar qué película se ha seleccionado y obtener los datos asociados a ella. + h1.textContent = "Personajes de la animación: " + pelicula.title; + personajes.characters.forEach((personaje) => { + const personajeElem = document.createElement("div"); + personajeElem.className = "contenedorHijo"; + personajeElem.innerHTML = `

${personaje.name}

+
+ ${personaje.name} +
+

Gender: ${personaje.gender}

+

Age: ${personaje.age}

+

Eye Color: ${personaje.eye_color}

+

Hair Color: ${personaje.hair_color}

+

Species: ${personaje.specie}

+
+
+ `; + personajeElem.addEventListener("mouseenter", () => { + personajeElem.querySelector(".info").style.display = "block"; + }); + personajeElem.addEventListener("mouseleave", () => { + personajeElem.querySelector(".info").style.display = "none"; + }); + characterContainer.appendChild(personajeElem); + }); + }); + }); + + + + const buttonTop10 = document.getElementById("top-10"); // accedemos al boton para añadirle un evento click el cual desencadera una funcion + buttonTop10.addEventListener("click", function () { + buttonTop10.classList.add("top10oculto"); + volver.classList.remove("volveroculto"); + selectvolver.classList.add("selectOculto"); + const h2 = document.getElementById("Anuncio"); //accedemos al elemnto vacio en el dom + h2.innerHTML = //establecemos el contenido dentro del elemnto seleccionado + "¿Sabías que Studio Ghibli es considerado uno de los
mejores estudios de animación en todo el mundo?"; + h2.addEventListener("mouseenter", function () { + //añadimos un evento al elemento para mostrar un elemento volveroculto al pasar el cursor + const h1 = document.getElementById("AnuncioPromedio"); + h1.innerHTML = + "El promedio general de puntuación de las animaciones de Studio Ghibli es del " + + PromedioGeneral + + " ¡Eso es increíble! Significa que la gran mayoría de las películas de Studio Ghibli han sido muy bien recibidas tanto por la crítica como por el público en general. ¡Definitivamente vale la pena verlas!"; + document.getElementById("AnuncioPromedio").style.display = "block"; + }); + h2.addEventListener("mouseleave", () => { + //este evento hara que cuando saquemos el cursor del elemnto seleccionado ,el elemento anteriormente seleccionado vuelva a estar volveroculto + document.getElementById("AnuncioPromedio").style.display = "none"; + }); + + const contenedortop = document.querySelector(".main-container"); //nos adentramos al contenedor descrito y lo alamacenamos para manipularlo. + contenedortop.innerHTML = ""; //limpiamos el contenedor + const PromedioGeneral = calculoData(data); // llamamos la funcion de calcular y le pasamos la data como argumento + const top = filterMoviesByScore(data, PromedioGeneral); // llamamos a la funcion filterscore y le pasamos como argumento la data y el calculo + top.forEach((top10) => { + const calculoElem = document.createElement("section"); + calculoElem.className = "contenedorHijo"; + calculoElem.innerHTML = ` +

${top10.title}

+
+ ${pelicula.title} +
+

${top10.description}

+

Puntuación de Rotten Tomatoes: ${top10.rt_score}

+
+
+ + `; + calculoElem.addEventListener("mouseenter", () => { + calculoElem.querySelector(".info").style.display = "block"; + }); + calculoElem.addEventListener("mouseleave", () => { + calculoElem.querySelector(".info").style.display = "none"; + }); + + contenedortop.appendChild(calculoElem); + }); + }); + + + + + peliculaElem.querySelectorAll(".btnlocaciones").forEach((button) => { + button.addEventListener("click", function (e) { + volver.classList.remove("volveroculto"); + selectvolver.classList.add("selectOculto"); + const containerLocations = document.querySelector(".main-container"); + containerLocations.innerHTML = ""; + const locaciones = filterOfdata3(data, e.target.id); // arreglo de locaciones + if (locaciones.length === 0) { + //utilizamos condicionales para verificar si la longitud del arreglo locaciones es igual a 0 + const containerLocations = document.querySelector(".main-container"); // en caso de que si insertamos imagen y texto diciendo que la informacion no se encuentra + containerLocations.innerHTML = `
+
+ +
+

Lo siento, parece que no hay información disponible para este campo. Pero no te desanimes, sigue explorando y seguro que encontrarás lo que buscas. +

+
`; + } else { + //en caso de que si hayan arreglos con contenido , se recorre el array y extraemos las coincidencias en cada iteracion de locaciones + locaciones.forEach((locaciones) => { + const locationElem = document.createElement("section"); + locationElem.className = "contenedorHijo"; + locationElem.innerHTML = `

${locaciones.name}

+
+ ${locaciones.name} +
+

Climate: ${locaciones.climate}

+

Terrain: ${locaciones.terrain}

+

Sorface: ${locaciones.sorface_water}

+

Residents: ${locaciones.residents}

+
+
+ `; + locationElem.addEventListener("mouseenter", () => { + locationElem.querySelector(".info").style.display = "block"; + }); + locationElem.addEventListener("mouseleave", () => { + locationElem.querySelector(".info").style.display = "none"; + }); + containerLocations.appendChild(locationElem); + }); + } + }); + }); + + + + peliculaElem.querySelectorAll(".btnvehiculos").forEach((buttonTop10) => { + buttonTop10.addEventListener("click", function (e) { + volver.classList.remove("volveroculto"); + selectvolver.classList.add("selectOculto"); + const animationContainer = document.querySelector(".main-container"); + animationContainer.innerHTML = ""; + const vehicles = filterOfdata2(data, e.target.id); // arreglo de vehiculos , el target es una propiedad del objeto de evento que hace referencia al elemento que desencadenó el evento + if (vehicles.length === 0) { + const animationContainer = document.querySelector(".main-container"); + animationContainer.innerHTML = `
+
+ +
+

"Lo siento, parece que no hay información disponible para este campo. Pero no te desanimes, sigue explorando y seguro que encontrarás lo que buscas. +

+
`; + } else { + vehicles.forEach((vehicles) => { + const vehiculosElem = document.createElement("section"); + vehiculosElem.className = "contenedorHijo"; + vehiculosElem.innerHTML = `

${vehicles.name}

+
+ ${vehicles.name} +
+

${vehicles.description}

+

Vehicles_class: ${vehicles.vehicles_class}

+

Length: ${vehicles.length}

+

Pilot: ${vehicles.pilot.name}

+
+
+ `; + vehiculosElem.addEventListener("mouseenter", () => { + vehiculosElem.querySelector(".info").style.display = "block"; + }); + vehiculosElem.addEventListener("mouseleave", () => { + vehiculosElem.querySelector(".info").style.display = "none"; + }); + animationContainer.appendChild(vehiculosElem); + }); + } + }); + }); + } +}; + +mostrarAnimaciones(data.films); //llamamos la funcion y le pasamos como argumento la data que ha sido importada + + + + +//Invocamos a las funciones importadas y las añadimos a las que coincidan con las opciones selecionadas. +const select = document.querySelector("#ordenar"); +select.addEventListener("change", function () { + const value = select.value; + if (value === "recientes") { + const dataOrdenada = sortData(data.films); // Ordenar por más recientes + mostrarAnimaciones(dataOrdenada); // Muestra las películas ordenadas + } else if (value === "alfabetico") { + const dataOrdenada1 = sortData2(data.films); // Ordenar alfabéticamente + mostrarAnimaciones(dataOrdenada1); // Muestra las películas ordenadas + } else if (value === "menoramayor") { + const dataOrdenada2 = sortData3(data.films); // Ordenar por menos recientes + mostrarAnimaciones(dataOrdenada2); // Muestra las películas ordenadas + } else if (value === "z_a") { + const dataOrdenada3 = sortData4(data.films); // Ordenar alfabéticamente de Z a A + mostrarAnimaciones(dataOrdenada3); // Muestra las películas ordenadas + } +}); + +document.addEventListener("DOMContentLoaded", function () { + /*evento que ocurre en JavaScript cuando el documento HTML + ha sido completamente cargado y analizado, sin necesidad de esperar que se hayan descargado todos los recursos externos + (como imágenes o estilos). */ + const volver = document.getElementById("btnvolver"); + volver.addEventListener("click", function () { + mostrarAnimaciones(data.films); + }); +}); diff --git a/src/style.css b/src/style.css index e69de29b..ee8f68e6 100644 --- a/src/style.css +++ b/src/style.css @@ -0,0 +1,441 @@ +header { + background-color: #00796b; + color: #fdfffd; + font-size: 300%; + width: 100%; + display: flex; + align-items: center; /*alinea los elemntos dentro del header*/ + justify-content: center; + height: 250px; + font-family: "Phudu"; +} +.noInformacion { + text-align: center; + display: flex; /*diseño flexible y adaptable para los elementos hijos de un contenedor.*/ + flex-wrap: wrap; /*especifica que los elementos hijos del contenedor deben envolverse en + varias líneas si no tienen suficiente espacio horizontal en una sola fila.*/ + justify-content: space-evenly;/*distribuye los elementos hijos del contenedor con un espacio uniforme entre ellos*/ + font-family: "Rubik"; +} + +.noInformacion img { + width: 320px; + height: 400px; + margin: 20px; +} + +.contenedorInfo { + background-image: linear-gradient(rgb(77, 139, 95), #9b9775); + margin: 1.5%; +} +#subtitulo-general { + font-size: 200%; + margin: 2%; + color: black; + text-shadow: none; +} +header img { + width: 350px; + height: 300px; +} +h2 { + font-family: "Abel"; + text-align: center; + margin-top: 2%; + text-shadow: 2px 2px 5px rgb(249, 239, 242); +} +/* Estilo general del scrollbar */ +::-webkit-scrollbar { + width: 10px; /* Ancho del scrollbar */ +} + +/* Estilo del thumb del scrollbar */ +::-webkit-scrollbar-thumb { + background-color: #77bd9d; /* Color de fondo del thumb del scrollbar */ + border-radius: 10px; /* Radio de borde del thumb del scrollbar */ +} + +/* Estilo del botón del scrollbar */ +::-webkit-scrollbar-button { + background-color: #fa7bbb; /* Color de fondo del botón del scrollbar */ +} + +#Anuncio { + margin: auto; + margin-top: 2.5%; + color: white; + text-shadow: 2px 2px 5px rgb(215 238 172); + border-radius: 8px; + background-color: #969774; + box-shadow: 0px 1px 10px rgb(0 0 0); + width: fit-content; + font-size: 190%; + color: black; + +} +#AnuncioPromedio { + + display: none; + /* text-shadow: 2px 2px 5px rgb(237 48 114); */ + border-radius: 8px; + background-color: rgb(142 229 238 / 90%); + box-shadow: 0px 1px 10px rgb(0 0 0); + width: 500px; + color: black; + text-align: center; + margin: auto; + font-size: 20px; +} + +body { + margin: 0px; + padding: 0px; + background-color: #c7dfdf; + font-family: "Abel"; +} + +.main-container { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + align-items: center; + font-family: "Rubik"; + margin-top: 4%; + margin-bottom: 5%; +} +.volveroculto{ + display: none; +} +.top10oculto{ + display: none; +} +.selectOculto{ + display: none; +} +nav { + display: flex; + align-items: center; + justify-content: space-evenly; +} +.selectordeOrden { + text-align: center; + color: black; + height: 40px; + width: 140px; + font-size: 17px; + background-color: #83d1ae; + border-radius: 10px; + border: none; + box-shadow: inset 0 -3em 3em rgba(0, 0, 0, 0.1), 0 0 0 2px rgb(255, 255, 255), + 0.3em 0.3em 1em rgba(0, 0, 0, 0.3); +} +.site-footer { + background-color: rgb(0, 121, 107); + color: white; + padding: 20px; +} + +.footer-container { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.footer-address { + flex-basis: 100%; + text-align: center; +} + +.footer-address p { + font-size: 18px; + margin: 0; +} + +.footer-address p:last-child { + font-size: 14px; + margin: 0; +} + +button { + cursor: pointer; +} +nav button { + text-align: center; + color: black; + height: 40px; + width: 140px; + font-size: 17px; + background-color: #83d1ae; + border: none; + border-radius: 10px; + box-shadow: inset 0 -3em 3em rgba(0, 0, 0, 0.1), 0 0 0 2px rgb(255, 255, 255), + 0.3em 0.3em 1em rgba(0, 0, 0, 0.3); +} + +.pelicula-img-container { + position: relative; /*definimos el tipo de posicionamiento de un elemento */ + /*posiciona el elemento de forma relativa a su posición original en el flujo normal del documento*/ +} + +.pelicula-img-container img { + display: block; + width: 320px; + height: 400px; + margin: 20px; +} + +.pelicula-img-container .info { + position: absolute; /*posiciona el elemento de forma absoluta en relación al primer elemento padre (pelicula-img-container)*/ + top: 0; + left: 20px; + bottom: 0; + right: 20px; + color: white; + background-color: rgba(14, 18, 17, 0.8); + display: none; + width: auto; + height: auto; + overflow: auto; + text-align: center; + padding: 30px; +} +.vehiculos-img-container { + position: relative; +} +.vehiculos-img-container img { + display: block; + width: 320px; + height: 400px; + margin: 20px; +} + +.vehiculos-img-container .info { + position: absolute; + top: 0; + left: 20px; + bottom: 0; + right: 20px; + color: white; + background-color: rgba(14, 18, 17, 0.8); + display: none; + width: auto; + height: auto; + overflow: auto; + text-align: center; + padding: 20%; +} +.vehiculos-img-container .info p { + margin: 0; + line-height: 1.5; +} +.vehiculos-img-container .info p span { + font-weight: bold; +} +.personajes-img-container { + position: relative; +} +.pelicula-img-container button { + background: #fa7bbb; + color: #fff; + padding: 10px 10px; + border-radius: 50px; + width: 120px; + margin: auto; + height: 50px; + font-family: "Phudu"; +} +.personajes-img-container img { + display: block; + width: 320px; + height: 400px; + margin: 20px; +} +.personajes-img-container .info { + position: absolute; + top: 0; + left: 20px; + bottom: 0; + right: 20px; + color: white; + background-color: rgba(14, 18, 17, 0.8); + display: none; + width: auto; + height: auto; + overflow: auto; + text-align: center; + padding-top: 8em; +} +.pelicula-img-container .info p { + margin: 0; + line-height: 1.5; +} + +.pelicula-img-container .info p span { + font-weight: bold; +} + +.contenedorBtn { + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-direction: row; +} + +.pelicula-img-container button:hover { + background-color: #83d1ae; +} + +.personajes-img-container .info p { + margin: 0; + line-height: 1.5; +} +.personajes-img-container .info p span { + font-weight: bold; +} +.locaciones-img-container { + position: relative; +} +.locaciones-img-container .info { + position: absolute; + top: 0; + left: 20px; + bottom: 0; + right: 20px; + color: white; + background-color: rgba(14, 18, 17, 0.8); + display: none; + width: auto; + height: auto; + overflow: auto; + text-align: center; + padding: 20%; +} +.locaciones-img-container img { + display: block; + width: 320px; + height: 400px; + margin: 20px; +} +.contenedorHijo { + /*background: linear-gradient(90deg, #cfecd0, #a0cea7, #9ec0db);*/ + background-image: linear-gradient(rgb(77, 139, 95), #9b9775); + margin: 1.5%; +} + +/*He incluido este media query para telefonos*/ +@media (max-width: 768.98px) { + .main-container { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + padding-top: 10px; + font-family: "Rubik"; + margin-top: 2%; + } + + #subtitulo-general { + font-size: 150%; + } + #Anuncio { + font-size: 30px; + margin-top: 5%; + margin: 10%; + margin-bottom: 0%; + } + + + .contenedorHijo { + /*background: linear-gradient(90deg, #cfecd0, #a0cea7, #9ec0db);*/ + background-image: linear-gradient(rgb(77, 139, 95), #9b9775); + margin: auto; + margin-bottom: 5%; + } + header { + background-color: #00796b; + color: #fdfffd; + font-size: 190%; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + height: 200px; + font-family: "Phudu"; + } + header img { + width: 190px; + height: 210px; + } +} +/* dispositivos móviles y tablets con un ancho de pantalla máximo de 991.98 píxeles. +Esto significa que se aplica a dispositivos con una pantalla más pequeña que la de los ordenadores + de escritorio, pero más grande que la de los teléfonos móviles más pequeños.*/ +@media (max-width: 991.98px) { + .main-container { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + align-items: center; + font-family: "Rubik"; + margin: 2%; + margin-top: 5%; + } + .contenedorHijo { + /*background: linear-gradient(90deg, #cfecd0, #a0cea7, #9ec0db);*/ + background-image: linear-gradient(rgb(77, 139, 95), #9b9775); + margin: auto; + margin-bottom: 5%; + } + nav { + display: flex; + align-items: center; + justify-content: space-evenly; + border-radius: 10px; + font-family: "Nunito Sans"; + margin: auto; + margin: 3%; + } + nav button { + margin: 2%; + text-align: center; + color: black; + height: 40px; + width: 140px; + font-size: 17px; + background-color: #83d1ae; + border: none; + border-radius: 10px; + box-shadow: inset 0 -3em 3em rgba(0, 0, 0, 0.1), + 0 0 0 2px rgb(255, 255, 255), 0.3em 0.3em 1em rgba(0, 0, 0, 0.3); + } + .selectordeOrden { + text-align: center; + color: black; + height: 40px; + width: 120px; + font-size: 17px; + background-color: #83d1ae; + border-radius: 10px; + border: none; + margin-right: 2%; + box-shadow: inset 0 -3em 3em rgba(0, 0, 0, 0.1), + 0 0 0 2px rgb(255, 255, 255), 0.3em 0.3em 1em rgba(0, 0, 0, 0.3); + } + #Anuncio { + font-size: 150%; + margin-top: 5%; + color: black; + text-shadow: 2px 2px 5px rgb(124 180 43); + font-family: "Abel"; + width: fit-content; + /*margin: auto;*/ + text-align: center; + } + + #AnuncioPromedio { + margin: 10px; + margin-right: 10px; + width: fit-content; + font-size: 140%; + } +} diff --git a/test/data.spec.js b/test/data.spec.js index 09b1f23f..73b1ec5f 100644 --- a/test/data.spec.js +++ b/test/data.spec.js @@ -1,23 +1,159 @@ -import { example, anotherExample } from '../src/data.js'; +import { + filterOfdata, + filterOfdata2, + filterOfdata3, + sortData, + sortData2, + sortData3, + sortData4, + calculoData, + filterMoviesByScore, +} from "../src/data.js"; - -describe('example', () => { - it('is a function', () => { - expect(typeof example).toBe('function'); +describe("filterOfdata", () => { + const data = [ + { + id: "58611129-2dbc-4a81-a72f-77ddfc1b1b49", + title: "My Neighbor Totoro", + people: ["Mei Kusakabe", "Satsuki Kusakabe"], + }, + { + id: "12cfb892-aac0-4c5b-94af-521852e46d6a", + title: "Grave of the Fireflies", + people: ["Seita Yokokawa", "Setsuko Yokokawa"], + }, + ]; + it("deberia devolver el titulo y los personasjes", () => { + const result = filterOfdata(data, "58611129-2dbc-4a81-a72f-77ddfc1b1b49"); + expect(result).toEqual({ + title: "My Neighbor Totoro", + characters: ["Mei Kusakabe", "Satsuki Kusakabe"], + }); }); +}); - it('returns `example`', () => { - expect(example()).toBe('example'); +describe("filterOfdata2", () => { + const data = [ + { + id: "2baf70d1-42bb-4437-b551-e5fed5a87abe", + vehicles: ["Air Destroyer Goliath"], + }, + { + id: "ebbb6b7c-945c-41ee-a792-de0e43191bd8", + vehicles: ["Red Wing", "Dabohaze"], + }, + ]; + it("deberia devolver vehiculos de la pelicula especificada", () => { + const result = filterOfdata2(data, "ebbb6b7c-945c-41ee-a792-de0e43191bd8"); + expect(result).toEqual(["Red Wing", "Dabohaze"]); }); }); - -describe('anotherExample', () => { - it('is a function', () => { - expect(typeof anotherExample).toBe('function'); +describe("filterOfdata3", () => { + const data = [ + { + id: "4e236f34-b981-41c3-8c65-f8c9000b94e7", + locations: ["Taeko's House"], + }, + { + id: "ebbb6b7c-945c-41ee-a792-de0e43191bd8", + locations: ["Piccolo S.P.A."], + }, + ]; + it("deberia devolver ubicacion de la pelicula especificada", () => { + const result = filterOfdata3(data, "ebbb6b7c-945c-41ee-a792-de0e43191bd8"); + expect(result).toEqual(["Piccolo S.P.A."]); }); +}); - it('returns `anotherExample`', () => { - expect(anotherExample()).toBe('OMG'); +describe("sortData", () => { + it("deberia devolver un array en orden ascedente - descendente", () => { + const films = [ + { title: "My Neighbor Totoro", release_date: "1988" }, + { title: "Only Yesterday", release_date: "1991" }, + ]; + const esperado = [ + { title: "Only Yesterday", release_date: "1991" }, + { title: "My Neighbor Totoro", release_date: "1988" }, + ]; + expect(sortData(films)).toEqual(esperado); + }); +}); +describe("sortData2", () => { + const data = [ + { + title: "Only Yesterday", + }, + { + title: "Grave of the Fireflies", + }, + { + title: "Porco Rosso", + }, + ]; + it("deberia devolver un arreglo ordenado a_z", () => { + const a_z = sortData2(data); + const devuelve = [ + { title: "Grave of the Fireflies" }, + { title: "Only Yesterday" }, + { title: "Porco Rosso" }, + ]; + expect(a_z).toEqual(devuelve); }); }); +describe("sortData3", () => { + it("deberia devolver un array en orden descendente - ascedente - ", () => { + const films = [ + { title: "Only Yesterday", release_date: "1991" }, + { title: "My Neighbor Totoro", release_date: "1988" }, + ]; + const esperado = [ + { title: "My Neighbor Totoro", release_date: "1988" }, + { title: "Only Yesterday", release_date: "1991" }, + ]; + expect(sortData3(films)).toEqual(esperado); + }); +}); +describe("sortData4", () => { + const data = [ + { + title: "Only Yesterday", + }, + { + title: "Grave of the Fireflies", + }, + { + title: "Porco Rosso", + }, + ]; + it("deberia devolver un arreglo ordenado z_a", () => { + const z_a = sortData4(data); + const devuelve = [ + { title: "Porco Rosso" }, + { title: "Only Yesterday" }, + { title: "Grave of the Fireflies" }, + ]; + expect(z_a).toEqual(devuelve); + }); +}); + +describe("calculoData", () => + it("deberia calcular el promedio general de toda la puntuacion de rottem ", () => { + const data = [{ rt_score: 91 }, { rt_score: 94 }, { rt_score: 100 }]; + const calculo = calculoData(data); + const promedio = calculo; + expect(calculo).toEqual(promedio); + })); + +describe("filterMoviesByScore", () => + it("deberia retornar un nuevo array con las 10 peliculas que superen el promedio general", () => { + const data = [ + { rt_score: 91 }, + { rt_score: 94 }, + { rt_score: 100 }, + { rt_score: 75 }, + ]; + const filtro = filterMoviesByScore(data, 88); + const result = filtro; + expect(filtro).toEqual(result); + }));