diff --git a/src/Imagenes del README/Alta_Fidelidad_1.png b/src/Imagenes del README/Alta_Fidelidad_1.png new file mode 100644 index 00000000..ff0919b4 Binary files /dev/null and b/src/Imagenes del README/Alta_Fidelidad_1.png differ diff --git a/src/Imagenes del README/Alta_Fidelidad_2.png b/src/Imagenes del README/Alta_Fidelidad_2.png new file mode 100644 index 00000000..48c5f845 Binary files /dev/null and b/src/Imagenes del README/Alta_Fidelidad_2.png differ diff --git a/src/Imagenes del README/Baja_Fidelidad_1.png b/src/Imagenes del README/Baja_Fidelidad_1.png new file mode 100644 index 00000000..4115ff0e Binary files /dev/null and b/src/Imagenes del README/Baja_Fidelidad_1.png differ diff --git a/src/Imagenes del README/Baja_Fidelidad_2.jpg b/src/Imagenes del README/Baja_Fidelidad_2.jpg new file mode 100644 index 00000000..624e0373 Binary files /dev/null and b/src/Imagenes del README/Baja_Fidelidad_2.jpg differ diff --git a/src/README.md b/src/README.md index b246d703..7ec54704 100644 --- a/src/README.md +++ b/src/README.md @@ -1,3 +1,38 @@ +**PROTOTIPOS DE BAJA FIDELIDAD** +![Prototipo de Baja Fidelidad 1](../src/Imagenes%20del%20README/Baja_Fidelidad_1.png) +![Prototipo de Baja Fidelidad 2](../src/Imagenes%20del%20README/Baja_Fidelidad_2.jpg) + +**PROTOTIPOS DE ALTA FIDELIDAD** + +![Prototipo de Alta Fidelidad 1](../src/Imagenes%20del%20README/Alta_Fidelidad_1.png) +![Prototipo de Alta Fidelidad 2](../src/Imagenes%20del%20README/Alta_Fidelidad_2.png) + +**LINK A FIGMA** https://www.figma.com/file/3MKRsG310lKLm2AF6eCIG0/Bocetos%3A-Alta%2Fbaja-fidelidad-e-historias-de-usuario?type=whiteboard&node-id=0%3A1&t=IXbccqh1CHJI4C0o-1 + +**HISTORIAS DE USUSARIO** + +[HISTORIA_1] + +Pensando en nuestro usuario, jugadora o jugador de Pokémon Go, quién necesite obtener información específica de los pokemones que va capturando, la busqueda sencilla lo ayuda a obtener esta información de manera rápida, con solo teclear el número o nombre del pokémon en cuestión. + +[HISTORIA_2] + +Buscar el elemento de cada pokemon es útil para saber y aprender las debilidades de los pokemones entre sí y así poder construir una mejor estrategia de juego o poder tomar mejores decisiones a la hora de que pokemon elegir para un combate en específico + +[HISTORIA_3] + +Pensando en nuestro usuario, jugadora o jugador de Pokémon Go, al seleccionar una tarjeta se obtiene la descripción y el tipo de pokemon. + +[HISTORIA_4] + +Pensando en nuestro usuario, jugadora o jugador de Pokémon Go, que necesite realizar una búsqueda de algún pokémon, creemos que es útil poder visualizar los pokémones ordenados de la A a la Z. +Y finalmente un botón que regrese las tarjetas de pokémones a su estado original para realizar una nueva búsqueda + +**Definición del producto** +Data Lovers es un buscador y base de datos de la serie animada Pokémon. Esta base de datos alberga informacion de 251 pokémones y datos especificos como nombre, tipo, número y una descripción de cada pokémon. El buscador esta pensado para que sea utilizado por usuarios del videojuego Pokemon Go; cuando necesiten buscar algún dato en especifico o detalles de un pokémon capturado y cuando requieran más información para mejorar su estrategia de juego, nuestra aplicación cuenta con un buscador de fácil acceso, sencillo y fácil de comprender. + + + **¿Quiénes son los principales usuarios de producto?** **¿¿Cuáles son los objetivos de estos usuarios en relación con el producto?** diff --git a/src/data.js b/src/data.js index 9aafa313..7fba0b3c 100644 --- a/src/data.js +++ b/src/data.js @@ -1,57 +1,40 @@ -// estas funciones son de ejemplo - -export const example = () => { - return 'example'; -}; - -export const anotherExample = () => { - return 'OMG'; -}; -import data from './data/pokemon/pokemon.js'; //Funcion busqueda de nombre o numero -function busquedaNomNum (){ - const inputElement = document.getElementById("input"); - const btnBuscar = document.getElementById("btn-buscar"); - - const recibeNomNum = inputElement.value; - - if(recibeNomNum === "string") +export function busquedaNomNum (data, nameOrNum){ + return data.pokemon.find(pokemon => { + return pokemon.name.toLowerCase() === nameOrNum.toLowerCase() || pokemon.num === nameOrNum; + }); } -btnBuscar.addEventListener("click", ) - - - - - - +export function filtrarPorTipo (data, condition){ + return data.pokemon.filter(pokemon => { + return condition (pokemon); + }); +} +export function sortData(data, sortBy, sortOrder) { + const sortedData = [...data.pokemon]; //Clonar el arreglo no modifica el original -//Llama elementos del DOM -/*const elementosSelect = document.getElementById("types"); -const btnBuscar = document.getElementById("btn-buscarType"); -const pokemonList = data.pokemon.pokemon + sortedData.sort((a, b) => { + const valueA = a[sortBy]; + const valueB = b[sortBy]; -//Funcion de filtrado -function filtrarPorTipo(pokemonType) { - return pokemonList.filter(pokemon => pokemon.type.includes(pokemonType)); + if (sortOrder === 'asc') { + return valueA.localeCompare(valueB); + } if (sortOrder === 'desc') { + return valueB.localeCompare(valueA); + } + + }); + + return sortedData; } -//Agregar un evento al boton de busqueda -btnBuscar.addEventListener("click", () => { - const tipoSeleccionado = elementosSelect.value; - const pokemonesFiltrados = filtrarPorTipo(tipoSeleccionado); - actualizarTarjetas(pokemonesFiltrados) - function actualizarTarjetas (pokemones){ - const rootElement = document.getElementById("root"); - rootElement.innerHTML = ""; - } -})*/ + diff --git a/src/index.html b/src/index.html index fde92705..be120259 100644 --- a/src/index.html +++ b/src/index.html @@ -2,29 +2,34 @@ + Data Lovers
-

+
pokemon -

+
pokebola pokebola
+

+ You are in the right place to find information
and become the best Pokemón traineer +

+
-
- + diff --git a/src/main.js b/src/main.js index 8b729b0d..cd00a4ae 100644 --- a/src/main.js +++ b/src/main.js @@ -1,9 +1,11 @@ import data from './data/pokemon/pokemon.js'; +import {busquedaNomNum, filtrarPorTipo, sortData} from './data.js'; + + const rootElement = document.getElementById("root"); -function pokemonCards(){ - const pokemonArray = data.pokemon;//data.pokemon accede a la matriz del objeto pokemon y se en la var pokemon Array +function pokemonCards(pokemonArray){ pokemonArray.forEach(pokemonInfo=>{ //Crear elementos HTML para guardar la informacion de cada pokemon const pokemonCard = document.createElement('div'); //HTML @@ -24,8 +26,120 @@ function pokemonCards(){ pokemonNumber.textContent = `#${pokemonInfo.num}`; pokemonCard.appendChild(pokemonNumber); + pokemonCard.addEventListener('click', async () => { //asincrónica con await + const pokemonDetails = await busquedaNomNum(data, pokemonInfo.num); + cardDetalladas(pokemonDetails); + }); + rootElement.appendChild(pokemonCard); - console.log(pokemonCard); + }); } -document.addEventListener('DOMContentLoaded', pokemonCards); \ No newline at end of file + +document.addEventListener('DOMContentLoaded', () => { + pokemonCards(data.pokemon); +}); +//FUNCION PARA EL DETALLE DE LAS CARTAS +function cardDetalladas(pokemonInfo) { + const modal = document.getElementById('modal'); + const modalName = document.getElementById('modal-pokemon-name'); + const modalDetails = document.getElementById('modal-pokemon-details'); + + modalName.textContent = pokemonInfo.name; + modalDetails.innerHTML = `Number: ${pokemonInfo.num}
Type: ${pokemonInfo.type.join(',')}
Description: ${pokemonInfo.about} + `; + + + modal.style.display = 'block'; + + const closeModalButton = document.querySelector('.close-modal'); + closeModalButton.addEventListener('click', () => { + modal.style.display = 'none'; + + }); + + +} + + +document.addEventListener('DOMContentLoaded', () => { + pokemonCards(data.pokemon); +}); + + +// BUSQUEDA POR NOMBRE O NUMERO +const inputElement = document.getElementById("input"); +const btnBuscar = document.getElementById("btn-buscar"); + +btnBuscar.addEventListener("click", () => { + const recibeNomNum = inputElement.value; + + const busquedaInfo = busquedaNomNum(data, recibeNomNum); + rootElement.innerHTML = ""; + inputElement.value = ""; + + if (busquedaInfo) { + pokemonCards([busquedaInfo]); + } + if (!isNaN(recibeNomNum)){ + const num = parseInt(recibeNomNum); + if(num < 1 || num > 251){ + alert("Ingresa un número valido del 1 al 251"); + } if (num.toString().length === 2 || num.toString().length === 1){ + const formatoDeNum = num.toString().padStart(3, "00"); + const busquedaInfo = busquedaNomNum(data, formatoDeNum); + if (busquedaInfo){ + pokemonCards([busquedaInfo]); + } + } + } + +}); + +inputElement.addEventListener("keydown", function(event){ + if(event.key === "Enter"){ + event.preventDefault(); + } +}) + + + +//BUSQUEDA POR ELEMENTO +const btnType = document.getElementById("btn-buscarType"); +const tipoDeSeleccion = document.getElementById("types"); + +btnType.addEventListener("click", () => { + //const selectType = ""; + const seleccion = tipoDeSeleccion.value; + + const filtrarPokemon = filtrarPorTipo(data, (pokemon) => { + return pokemon.type.includes(seleccion); + }); + rootElement.innerHTML = ""; + pokemonCards(filtrarPokemon); +}); +//ORDENAR ALFABETICAMENTE +const btnOrdenarNombre = document.getElementById('btn-ordenar-asc'); +btnOrdenarNombre.addEventListener('click', () => { + const pokemonOrdenados = sortData(data, 'name', 'asc'); + rootElement.innerHTML = ''; + pokemonCards(pokemonOrdenados); +}); +//ORDENAR ALFABETICAMENTE DESCENDENTEMENTE +const btnOrdenarNombre2 = document.getElementById('btn-ordenar-desc'); +btnOrdenarNombre2.addEventListener('click', () => { + const pokemonOrdenados = sortData(data, 'name', 'desc'); + rootElement.innerHTML = ''; + pokemonCards(pokemonOrdenados); +}); + +//ORDENAR ASCENDENTEMENTE POR NUMERO +const btnOrdenarNumero = document.getElementById('btn-ordenar-numero'); +btnOrdenarNumero.addEventListener('click', () => { + const pokemonesOrdenados = sortData(data, 'num', 'asc',); + rootElement.innerHTML = ''; + pokemonCards(pokemonesOrdenados); +}); + + + diff --git a/src/style.css b/src/style.css index f5ed2b78..aee12b2a 100644 --- a/src/style.css +++ b/src/style.css @@ -1,13 +1,25 @@ +@import url('https://fonts.googleapis.com/css2?family=Handjet:wght@500&family=Sarabun:wght@100;300;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Handjet:wght@300;500&family=Sarabun:wght@100;300;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Forum&family=Handjet:wght@300;500&family=Sarabun:wght@100;300;700&family=Unica+One&display=swap'); +body { + background-image: url(https://pbs.twimg.com/ext_tw_video_thumb/1548081971045142530/pu/img/BD7UoqShVKLH7T7x.jpg:large); + max-width: 100%; /*Determina un ancho maximo*/ + overflow-x: hidden; /* Esto oculta el desplazamiento horizontal */ + +} + .pokemon{ - width: 20%; + width: 30%; position: absolute; - left: 500px; - top: 50px; + left: 450px; + top: 30px; } + .pokebola-1{ width: 10%; - margin: 0 0 40px 20px; + margin: 21px 0 40px 95px; + } .pokebola-2{ @@ -17,16 +29,97 @@ right: 100px; top: 10px; } + +h1 { + font-family:'Handjet'; + font-size: 25px; + text-align: center; +} + + +.nomNum { + display: inline; +} + +textarea { + margin: 20px; + position: relative; + left: 420px; +} + +#input { + font-family: 'Handjet'; + font-weight: 300; + font-size: 20px; + text-align: center; + height: 30px; + resize: none; + +} + +#btn-buscar { + position: relative; + left: 870px; + bottom: 55px; + padding: 10px; + height: 20px; + font-family:'Handjet'; + font-size: 20px; + display: flex; + align-items: center; + border-radius: 5px; + + +} +.elementos { + font-family:'Handjet'; + display: flex; + justify-content: center; + margin: 5px; + position: relative; + bottom: 30px; + width: 95vw; +} + +.elementos label { + margin-right: 10px; + font-size: 25px; + +} + +#types { + font-family:'Handjet'; + font-size: 20px; + width: 200px; + text-align: center; +} + +#btn-buscarType { + font-family:'Handjet'; + font-size: 20px; + margin-left: 20px; + border-radius: 5px; +} + +#root { + text-align: center; + margin: 50px; +} + .pokemon-container { border: 2px solid black; display: inline-block; flex-wrap: wrap; margin: 10px; - width: 180px; - height: 260px; + width: 15%; + height: 250px; text-align: center; - background-color: darkgrey; + background-color: antiquewhite; border-radius: 10px; + border-color: white; + -webkit-box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75); + -moz-box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75); + box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75); } .pokemon-img{ @@ -34,10 +127,135 @@ height: 150px; display: block; margin: 0 auto; - background-color: black; border-radius: 10px; } .pokemon-name { - font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; + font-family: 'Handjet'; + font-size: 25px; text-align: center; + border-radius: 8px; + color: black; + padding: 5px 2px; + text-transform: capitalize; + bottom: 12px; +} + +.pokemon-number { + font-family: 'Forum'; + font-size: 25px; + position: relative; + bottom: 18px; +} + +#modal { + display: none; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); + + + + +} +.btnOrdenarLimpiar{ + position: relative; + left: 440px; + +} + +#btn-ordenar-asc{ + font-family: 'Handjet'; + font-size: 20px; + margin-left: 20px; + border-radius: 5px; + + +} + +#btn-ordenar-desc{ + font-family: 'Handjet'; + font-size: 20px; + margin-left: 20px; + border-radius: 5px; +} + +#btn-ordenar-numero{ + font-family: 'Handjet'; + font-size: 20px; + margin-left: 20px; + border-radius: 5px; + +} + +.modal-content { + background-color: #DAFDFC; + margin: 15% auto; + padding: 20px; + border: 1px solid #888; + width: 80%; + max-width: 400px; + border-radius: 8px; + font-family: 'Handjet' ; + font-size: 25px; + +} + + +.close-modal{ + color: #aaa; + float: right; + font-size: 28px; + font-weight: bold; + cursor: pointer; + +} +#modal-pokemon-name { + text-transform: capitalize; +} + +#modal-pokemon-details { + font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +@media (max-width: 1000px){ +.pokemon { + position: absolute; + left: 200px; +} + +.pokebola-2{ + position: absolute; + right: 100px; + +} +#input{ + + left: 50px; + +} +#btn-buscar{ + + left: 470px; +} +.btnOrdenarLimpiar{ + left: 50px; +} + +.pokemon-container { + width: 35%; + margin: 5px; +} +.modal-content { + width: 40%; + font-size: 18px; +} + +.pokemon-name{ + position: relative; + bottom: 12px; } +} \ No newline at end of file diff --git a/test/data.spec.js b/test/data.spec.js index 09b1f23f..86bf6c39 100644 --- a/test/data.spec.js +++ b/test/data.spec.js @@ -1,23 +1,96 @@ -import { example, anotherExample } from '../src/data.js'; +import { busquedaNomNum, filtrarPorTipo, sortData } from '../src/data.js'; - -describe('example', () => { +//FUNCION BusquedaNomNum +describe('busquedaNomNum', () => { it('is a function', () => { - expect(typeof example).toBe('function'); + expect(typeof busquedaNomNum).toBe('function'); }); - it('returns `example`', () => { - expect(example()).toBe('example'); + it('throws an error when search input is empty', () => { + expect(() => { + busquedaNomNum(""); + }).toThrow(TypeError); + }); + + it('throws an error when search input is greater than 251', () => { + expect(() => { + busquedaNomNum(252); + }).toThrowError(TypeError); }); -}); + it('should return true if the name or number matches', () => { + const data = { + pokemon: [ + { name: 'Pikachu', num: '025' }, + { name: 'Charizard', num: '006' }, + { name: 'Bulbasaur', num: '001' } + ] + }; + + const result = busquedaNomNum(data, 'pikachu'); // Llamando a la función bajo prueba + const result1 = busquedaNomNum(data, 'charizard'); + const result2 = busquedaNomNum(data, 'pikachu'); + expect(result).toBeTruthy(); // Realizando la afirmación de la prueba + expect(result1).toBeTruthy(); + expect(result2).toBeTruthy(); + }); + + //FUNCION FiltraPorTipo + describe('filtrarPorTipo', () => { + it('is a function', () => { + expect(typeof filtrarPorTipo).toBe('function'); + }); + it('should return the pokemons with that type',() => { + const data = { + pokemon: [ + { name: 'Pikachu', type:'electric' }, + { name: 'Charizard', type:'fire' }, + { name: 'Bulbasaur', type:('grass','posion') } + ] + + }; + const filtrarPokemon = filtrarPorTipo(data, (pokemon) => { + return pokemon.type.includes('electric') + }); + expect(filtrarPokemon.length).toBe(1); + }); + }); -describe('anotherExample', () => { - it('is a function', () => { - expect(typeof anotherExample).toBe('function'); + + //FUNCION sortData + describe('sortData', () => { + it('is a function', () => { + expect(typeof sortData).toBe('function'); + }) + }); + + it('should sort the data in ascending order',() => { + const unSortedData = { + pokemon: [ + {name: 'Pikachu'}, + {name: 'Charizard'}, + {name: 'Bulbasaur'} + ] + }; + const sortedData = sortData(unSortedData, 'name', 'asc'); + expect(sortedData[0].name).toBe('Bulbasaur'); + expect(sortedData[1].name).toBe('Charizard'); + expect(sortedData[2].name).toBe('Pikachu'); }); - it('returns `anotherExample`', () => { - expect(anotherExample()).toBe('OMG'); + it('should sort the data in descending order',() => { + const unSortedData = { + pokemon: [ + {name: 'Pikachu'}, + {name: 'Charizard'}, + {name: 'Bulbasaur'} + ] + }; + const sortedData = sortData(unSortedData, 'name', 'desc'); + expect(sortedData[0].name).toBe('Pikachu'); + expect(sortedData[1].name).toBe('Charizard'); + expect(sortedData[2].name).toBe('Bulbasaur'); + }); + });