diff --git a/README.md b/README.md index 0c237c1c3..96c0c038e 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ -# Trilha JS Developer - Pokedex +# Pokédex Web Page + +Esta página web é uma implementação simples de uma Pokédex, construída com **HTML**, **CSS** e **JavaScript**. A Pokédex exibe uma lista de Pokémons, com a possibilidade de carregar mais itens conforme necessário. A aplicação usa a PokéAPI para buscar os dados de cada Pokémon e apresenta as informações de forma organizada e intuitiva. + +## Tecnologias Utilizadas + +- **HTML**: Estruturação do conteúdo e elementos da página. +- **CSS**: Design responsivo e estilização usando um tema moderno e minimalista, com suporte a fontes externas (Roboto) e a biblioteca Normalize.css para garantir consistência entre diferentes navegadores. +- **JavaScript**: Manipulação da DOM, integração com a PokéAPI e implementação da funcionalidade de carregamento dinâmico de Pokémons. + +## Funcionalidades + +- **Visualização da lista de Pokémons**: A lista é carregada dinamicamente com a opção de exibir mais Pokémons por meio de um botão de "More...". +- **Paginação simples**: A página permite carregar mais Pokémons sem recarregar a página. + +## Estrutura do Projeto + +- `index.html`: Estrutura principal da página, incluindo referências aos arquivos CSS e JavaScript. +- `assets/css/`: Contém os arquivos de estilização (`global.css` e `pokedex.css`). +- `assets/js/`: Contém os arquivos JavaScript responsáveis pela lógica da aplicação, incluindo a interação com a PokéAPI (`PokemonModel.js`, `poke-api.js`, `main.js`). + +## Como Executar + +1. Clone o repositório ou baixe os arquivos. +2. - Para executar o projeto corretamente, é necessário rodá-lo em um **servidor local** (isso porque o JavaScript pode enfrentar problemas ao fazer requisições de APIs externas diretamente do sistema de arquivos). + + Você pode usar um dos seguintes métodos para criar um servidor local: + + - **VSCode com Live Server**: + - Instale a extensão **Live Server** no Visual Studio Code. + - Abra o projeto no VSCode. + - Clique com o botão direito no arquivo `index.html` e selecione a opção **Open with Live Server**. + - **Python (para quem tem Python instalado)**: + - Navegue até a pasta do projeto no terminal. + - Execute o comando: + - Para Python 3: `python -m http.server` + - Para Python 2: `python -m SimpleHTTPServer` + - Acesse `http://localhost:8000` no navegador. + - +3. A página será carregada e exibirá uma lista inicial de Pokémons. Para ver mais, clique no botão "More...". \ No newline at end of file diff --git a/assets/css/global.css b/assets/css/global.css index 980e87861..fbd49d6ae 100644 --- a/assets/css/global.css +++ b/assets/css/global.css @@ -3,22 +3,24 @@ box-sizing: border-box; } -body { - background-color: #f6f8fc; +body{ + background-color: #f5f5f5; } -.content { - width: 100vw; - height: 100vh; +.content{ padding: 1rem; background-color: #fff; + min-height: 100vh; } -@media screen and (min-width: 992px) { - .content { - max-width: 992px; - height: auto; + +@media screen and (min-width: 1200px){ + .content{ + max-width: 1200px; margin: 1rem auto; + height: auto; border-radius: 1rem; + border: 1px solid #bfbdbd60; + min-height: auto; } } \ No newline at end of file diff --git a/assets/css/pokedex.css b/assets/css/pokedex.css index 59eef2bde..e2706af03 100644 --- a/assets/css/pokedex.css +++ b/assets/css/pokedex.css @@ -1,165 +1,162 @@ -.pokemons { - display: grid; - grid-template-columns: 1fr; - margin: 0; - padding: 0; - list-style: none; -} -.normal { - background-color: #a6a877; +.normal{ + background-color: #929DA3; } - -.grass { - background-color: #77c850; +.grass{ + background-color: #63BC5A; } - -.fire { - background-color: #ee7f30; +.fire{ + background-color: #FF9D55; } - -.water { - background-color: #678fee; +.water{ + background-color: #5090D6; } - -.electric { - background-color: #f7cf2e; +.electric{ + background-color: #F4D23C; } - -.ice { - background-color: #98d5d7; +.ground{ + background-color: #D97845; } - -.ground { - background-color: #dfbf69; +.rock{ + background-color: #C5B78C; } - -.flying { - background-color: #a98ff0; +.steel{ + background-color: #5A8EA2; } - -.poison { - background-color: #a040a0; +.psychic{ + background-color: #FA7179; } - -.fighting { - background-color: #bf3029; +.flying{ + background-color: #8FA9DE; } - -.psychic { - background-color: #f65687; +.dragon{ + background-color: #0B6DC3; } - -.dark { - background-color: #725847; +.ice{ + background-color: #73CEC0; } - -.rock { - background-color: #b8a137; +.ghost{ + background-color: #5269AD; } - -.bug { - background-color: #a8b720; +.dark{ + background-color:#5A5465; } - -.ghost { - background-color: #6e5896; +.poison{ + background-color:#AA6BC8; } - -.steel { - background-color: #b9b7cf; +.bug{ + background-color:#91C12F; } - -.dragon { - background-color: #6f38f6; +.fairy{ + background-color:#EC8FE6; +} +.fighting{ + background-color: #CE416B; } -.fairy { - background-color: #f9aec7; +.pokemons{ + display: grid; + grid-template-columns: 1fr; + list-style: none; + padding: 0; + margin: 0; } -.pokemon { +.pokemon{ + margin: 0.5rem; + padding: 0.5rem; + color: #fff; + border-radius: 1rem; display: flex; flex-direction: column; - margin: .5rem; - padding: 1rem; - border-radius: 1rem; + filter: drop-shadow(2px 4px 4px grey); } -.pokemon .number { - color: #000; - opacity: .3; +.pokemon .number{ text-align: right; - font-size: .625rem; + color: #000; + opacity: 0.4; + font-size: 0.75rem; } -.pokemon .name { - text-transform: capitalize; - color: #fff; - margin-bottom: .25rem; +.pokemon .name{ + margin: 0 0 0.5rem 0; + text-transform: uppercase; } -.pokemon .detail { +.pokemon .details{ display: flex; flex-direction: row; - align-items: center; - justify-content: space-between; + justify-content: space-between; +} + +.pokemon .details img{ + max-width: 100px; + height: 80px; + align-self: flex-end; + filter: drop-shadow(1px 1px 3px black); } -.pokemon .detail .types { +.pokemon .details .types{ + list-style: none; padding: 0; margin: 0; - list-style: none; } -.pokemon .detail .types .type { - color: #fff; - padding: .25rem .5rem; - margin: .25rem 0; - font-size: .625rem; - border-radius: 1rem; - filter: brightness(1.1); +.pokemon .details .types .type{ + padding: 0.1rem 0.5rem; + border-radius: 0.5rem; text-align: center; + margin: 0.3rem 0; + font-size: 0.6rem; + text-transform: capitalize; + filter: brightness(0.92); } -.pokemon .detail img { - max-width: 100%; - height: 70px; -} - -.pagination { +.pagination{ display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - width: 100%; - padding: 1rem; + flex-direction: column; + margin: 1rem 0.5rem 0.2rem 0.5rem; } -.pagination button { - padding: .25rem .5rem; - margin: .25rem 0; - font-size: .625rem; - color: #fff; - background-color: #6c79db; +.pagination button{ + background-color: #f5f5f5; + border-radius: 0.3rem; border: none; - border-radius: 1rem; + filter: drop-shadow(2px 4px 4px grey); } -@media screen and (min-width: 380px) { - .pokemons { +/* SIVE I */ +@media screen and (min-width: 385px){ + .pokemons{ grid-template-columns: 1fr 1fr; } } -@media screen and (min-width: 576px) { - .pokemons { +/* SIVE II */ +@media screen and (min-width: 576px){ + .pokemons{ grid-template-columns: 1fr 1fr 1fr; } } -@media screen and (min-width: 992px) { - .pokemons { +/* SIVE III */ +@media screen and (min-width: 768px){ + .pokemons{ grid-template-columns: 1fr 1fr 1fr 1fr; } +} + +/* SIVE IV */ +@media screen and (min-width: 992px){ + .pokemons{ + grid-template-columns: 1fr 1fr 1fr 1fr 1fr; + } +} + +/* MAX SIZE */ +@media screen and (min-width: 1200px){ + .pokemons{ + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + } } \ No newline at end of file diff --git a/assets/js/PokemonModel.js b/assets/js/PokemonModel.js new file mode 100644 index 000000000..5a3a19518 --- /dev/null +++ b/assets/js/PokemonModel.js @@ -0,0 +1,8 @@ + +class Pokemon{ + name; + number; + type; + types = []; + image; +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index bcaa24508..832290cf7 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,47 +1,40 @@ + const pokemonList = document.getElementById('pokemonList') const loadMoreButton = document.getElementById('loadMoreButton') +let limit = 24 +let offset = 0 + + + function loadPokemonItems(offset, limmit){ + + pokeApi.getPokemons(offset, limmit).then((pokemons = []) => { + + //Função 'map' transformadora, transformando nosso result em um item list e concatena-o no HTML antigo com .innerHTML + pokemonList.innerHTML += pokemons.map((pokemon) => + `
  • + #${pokemon.number} + ${pokemon.name} + +
    +
      + ${pokemon.types.map((type) => `
    1. ${type}
    2. `).join('')} +
    + ${pokemon.name} +
    +
  • ` + ).join('') + }) + } -const maxRecords = 151 -const limit = 10 -let offset = 0; - -function convertPokemonToLi(pokemon) { - return ` -
  • - #${pokemon.number} - ${pokemon.name} - -
    -
      - ${pokemon.types.map((type) => `
    1. ${type}
    2. `).join('')} -
    - - ${pokemon.name} -
    -
  • - ` -} - -function loadPokemonItens(offset, limit) { - pokeApi.getPokemons(offset, limit).then((pokemons = []) => { - const newHtml = pokemons.map(convertPokemonToLi).join('') - pokemonList.innerHTML += newHtml - }) -} - -loadPokemonItens(offset, limit) + loadPokemonItems(offset, limit) loadMoreButton.addEventListener('click', () => { offset += limit - const qtdRecordsWithNexPage = offset + limit - - if (qtdRecordsWithNexPage >= maxRecords) { - const newLimit = maxRecords - offset - loadPokemonItens(offset, newLimit) - + + if(offset >= 137){ + limit = 7 loadMoreButton.parentElement.removeChild(loadMoreButton) - } else { - loadPokemonItens(offset, limit) } + + loadPokemonItems(offset, limit) }) \ No newline at end of file diff --git a/assets/js/poke-api.js b/assets/js/poke-api.js index 38fbfd465..b96fd7a14 100644 --- a/assets/js/poke-api.js +++ b/assets/js/poke-api.js @@ -1,35 +1,39 @@ - +//Objeto que vai representar nossa Poke-API const pokeApi = {} -function convertPokeApiDetailToPokemon(pokeDetail) { +function convertPokemonApiDetailToPokemonModel(pokeDetail) { const pokemon = new Pokemon() - pokemon.number = pokeDetail.id + pokemon.name = pokeDetail.name + pokemon.number = pokeDetail.id const types = pokeDetail.types.map((typeSlot) => typeSlot.type.name) - const [type] = types + const [type] = types - pokemon.types = types pokemon.type = type + pokemon.types = types - pokemon.photo = pokeDetail.sprites.other.dream_world.front_default + pokemon.image = pokeDetail.sprites.other.dream_world.front_default return pokemon } +// Transformamos a lista de resutlts em uma nova lista de json, com o detalhamento da 'url' pokeApi.getPokemonDetail = (pokemon) => { + return fetch(pokemon.url) - .then((response) => response.json()) - .then(convertPokeApiDetailToPokemon) + .then(response => response.json()) + .then((convertPokemonApiDetailToPokemonModel)) } -pokeApi.getPokemons = (offset = 0, limit = 5) => { - const url = `https://pokeapi.co/api/v2/pokemon?offset=${offset}&limit=${limit}` - - return fetch(url) - .then((response) => response.json()) - .then((jsonBody) => jsonBody.results) - .then((pokemons) => pokemons.map(pokeApi.getPokemonDetail)) - .then((detailRequests) => Promise.all(detailRequests)) - .then((pokemonsDetails) => pokemonsDetails) -} +// arrow funcition => uma forma mais simples de escrever uma function, otimizando o código e deixando=o mais limpo +pokeApi.getPokemons = (offset = 0, limit = 24) => { + const url = `https://pokeapi.co/api/v2/pokemon?offset=${offset}&limit=${limit}` // '?' Parâmetro de consulta; Query string na qual pode-se passar parâmetros para consultar, filtrar ou autenticar + + return fetch(url) // Recebemos do servidor a promisse + .then((response) => response.json()) // Convertemos para json + .then((jsonBody) => jsonBody.results) // Extraimos a lista que esta dentro do json + .then((pokemons) => pokemons.map(pokeApi.getPokemonDetail)) // Chama função para converter o 'results' + .then((detailRequest) => Promise.all(detailRequest)) + .then((pokemonsDetails) => (pokemonsDetails)) +} \ No newline at end of file diff --git a/index.html b/index.html index 1a017821d..90200194a 100644 --- a/index.html +++ b/index.html @@ -1,46 +1,49 @@ - - Pokedex + - + - + - - - + + + + +
    -

    Pokedex

    + +

    Pokedex

      - +
    - + +
    + + + + + - - - - - \ No newline at end of file