├── public
├── favicon.ico
├── logo192.png
├── logo512.png
├── robots.txt
├── manifest.json
└── index.html
├── src
├── assets
│ ├── icons
│ │ ├── pokeball.png
│ │ ├── pokemon
│ │ │ └── types
│ │ │ │ ├── bug.png
│ │ │ │ ├── dark.png
│ │ │ │ ├── fairy.png
│ │ │ │ ├── fire.png
│ │ │ │ ├── ghost.png
│ │ │ │ ├── grass.png
│ │ │ │ ├── ice.png
│ │ │ │ ├── rock.png
│ │ │ │ ├── steel.png
│ │ │ │ ├── water.png
│ │ │ │ ├── dragon.png
│ │ │ │ ├── flying.png
│ │ │ │ ├── ground.png
│ │ │ │ ├── normal.png
│ │ │ │ ├── poison.png
│ │ │ │ ├── psychic.png
│ │ │ │ ├── electric.png
│ │ │ │ ├── fighting.png
│ │ │ │ └── normal_la.png
│ │ └── busqueda.svg
│ └── screenshots
│ │ ├── card.PNG
│ │ ├── grid.PNG
│ │ ├── search.PNG
│ │ ├── card-venasaur.PNG
│ │ └── card-blastoise.PNG
├── layout
│ ├── container.jsx
│ └── grid.jsx
├── components
│ ├── footer.jsx
│ ├── navbar.jsx
│ ├── search.jsx
│ ├── card.jsx
│ └── modal.jsx
├── index.jsx
├── index.css
├── utils
│ └── icons.js
├── colors.css
├── App.jsx
└── App.css
├── .gitignore
├── package.json
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/assets/icons/pokeball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokeball.png
--------------------------------------------------------------------------------
/src/assets/screenshots/card.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/screenshots/card.PNG
--------------------------------------------------------------------------------
/src/assets/screenshots/grid.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/screenshots/grid.PNG
--------------------------------------------------------------------------------
/src/assets/screenshots/search.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/screenshots/search.PNG
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/bug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/bug.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/dark.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/fairy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/fairy.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/fire.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/ghost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/ghost.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/grass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/grass.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/ice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/ice.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/rock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/rock.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/steel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/steel.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/water.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/water.png
--------------------------------------------------------------------------------
/src/assets/screenshots/card-venasaur.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/screenshots/card-venasaur.PNG
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/dragon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/dragon.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/flying.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/flying.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/ground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/ground.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/normal.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/poison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/poison.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/psychic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/psychic.png
--------------------------------------------------------------------------------
/src/assets/screenshots/card-blastoise.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/screenshots/card-blastoise.PNG
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/electric.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/electric.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/fighting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/fighting.png
--------------------------------------------------------------------------------
/src/assets/icons/pokemon/types/normal_la.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Onnichan/pokeapi-react/HEAD/src/assets/icons/pokemon/types/normal_la.png
--------------------------------------------------------------------------------
/src/layout/container.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Container extends React.Component{
4 |
5 | render(){
6 | return(
7 |
{this.props.children}
8 | )
9 | }
10 | }
--------------------------------------------------------------------------------
/src/components/footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Footer extends React.Component{
4 |
5 | render(){
6 | return(
7 |
10 | )
11 | }
12 | }
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render(
8 |
9 | );
10 |
--------------------------------------------------------------------------------
/src/components/navbar.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Navbar extends React.Component{
4 |
5 | render(){
6 | return(
7 |
8 | {this.props.title}
9 |
10 | )
11 | }
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/layout/grid.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Card from '../components/card';
3 |
4 | export default class Grid extends React.Component{
5 |
6 | constructor(props){
7 | super(props);
8 | this.handleButton = this.handleButton.bind(this);
9 | }
10 |
11 | handleButton(){
12 | this.props.next();
13 | }
14 |
15 | render(){
16 |
17 | return(
18 |
19 |
20 | {
21 | this.props.pokemons.map(poke=> (
22 |
23 | ))
24 | }
25 |
26 | {
27 | (this.props.pokemons.length >= 20) &&
28 |
29 |
30 |
31 | }
32 |
33 | )
34 | }
35 | }
--------------------------------------------------------------------------------
/src/assets/icons/busqueda.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pokeapi",
3 | "homepage": "https://onnichan.github.io/pokeapi-react/",
4 | "version": "0.1.0",
5 | "private": true,
6 | "dependencies": {
7 | "@testing-library/jest-dom": "^5.16.4",
8 | "@testing-library/react": "^13.1.1",
9 | "@testing-library/user-event": "^13.5.0",
10 | "react": "^18.1.0",
11 | "react-dom": "^18.1.0",
12 | "react-scripts": "5.0.1",
13 | "web-vitals": "^2.1.4"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject",
20 | "deploy": "gh-pages -d build"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | },
40 | "devDependencies": {
41 | "gh-pages": "^3.2.3"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/search.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import SearchIcon from '../assets/icons/busqueda.svg';
3 |
4 | export default class Search extends React.Component{
5 |
6 | constructor(props){
7 | super(props);
8 | this.state = {
9 | search: '',
10 | }
11 | this.handleSearch = this.handleSearch.bind(this);
12 | this.handleClickSearch = this.handleClickSearch.bind(this);
13 | }
14 |
15 | handleSearch(e){
16 |
17 | this.setState({
18 | search: e.target.value,
19 | })
20 | if(e.target.value.length === 0) this.props.onHandleSearch(null);
21 |
22 | }
23 |
24 | handleClickSearch(e){
25 | if(e.keyCode === 13 || e.type === 'click'){
26 | e.preventDefault();
27 | this.props.onHandleSearch(this.state.search);
28 | }
29 | }
30 |
31 | render(){
32 | return(
33 |
34 |
35 |
42 |

43 |
44 |
45 |
46 | )
47 | }
48 | }
--------------------------------------------------------------------------------
/src/components/card.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Modal from './modal';
3 | import PokeballImage from '../assets/icons/pokeball.png';
4 | import {searchIcon} from '../utils/icons';
5 |
6 | export default class Card extends React.Component{
7 |
8 | constructor(props){
9 | super(props);
10 | this.state = {
11 | showModal: false,
12 | }
13 | this.handleModal = this.handleModal.bind(this);
14 | }
15 |
16 | handleModal(){
17 | this.setState({
18 | showModal: !this.state.showModal
19 | },()=> {
20 | document.body.classList.toggle('dark');
21 | })
22 | }
23 |
24 | render(){
25 |
26 | const {pokemon} = this.props;
27 |
28 | return(
29 | <>
30 |
31 |
32 |

33 |
{`#${pokemon.order}`}
34 |
35 |
36 |
})
37 |
{pokemon.types[0].type.name}
38 |
39 |
{pokemon.name}
40 |

41 |
42 | {
43 | this.state.showModal &&
44 | }
45 | >
46 | )
47 | }
48 | }
--------------------------------------------------------------------------------
/src/utils/icons.js:
--------------------------------------------------------------------------------
1 | import bug from '../assets/icons/pokemon/types/bug.png';
2 | import dark from '../assets/icons/pokemon/types/dark.png';
3 | import dragon from '../assets/icons/pokemon/types/dragon.png';
4 | import electric from '../assets/icons/pokemon/types/electric.png';
5 | import fairy from '../assets/icons/pokemon/types/fairy.png';
6 | import fighting from '../assets/icons/pokemon/types/fighting.png';
7 | import fire from '../assets/icons/pokemon/types/fire.png';
8 | import flying from '../assets/icons/pokemon/types/flying.png';
9 | import ghost from '../assets/icons/pokemon/types/ghost.png';
10 | import grass from '../assets/icons/pokemon/types/grass.png';
11 | import ground from '../assets/icons/pokemon/types/ground.png';
12 | import ice from '../assets/icons/pokemon/types/ice.png';
13 | import normal from '../assets/icons/pokemon/types/normal.png';
14 | import poison from '../assets/icons/pokemon/types/poison.png';
15 | import psychic from '../assets/icons/pokemon/types/psychic.png';
16 | import rock from '../assets/icons/pokemon/types/rock.png';
17 | import steel from '../assets/icons/pokemon/types/steel.png';
18 | import water from '../assets/icons/pokemon/types/water.png';
19 |
20 | const icons = {
21 | bug: bug,
22 | dark: dark,
23 | dragon: dragon,
24 | electric: electric,
25 | fairy: fairy,
26 | fighting: fighting,
27 | fire: fire,
28 | flying: flying,
29 | ghost: ghost,
30 | grass: grass,
31 | ground: ground,
32 | ice: ice,
33 | normal: normal,
34 | poison: poison,
35 | psychic: psychic,
36 | rock: rock,
37 | steel: steel,
38 | water: water
39 | }
40 |
41 | export function searchIcon(search){
42 |
43 | if(search){
44 | search = Object.entries(icons).filter(icon => icon[0] === search);
45 | return search[0][1];
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # POKEAPI 
2 |
3 | In this project we use a Pokedex to show the info of a pokemon, searching by its name. To get this info we use an API to bring the data from [pokeapi](https://pokeapi.co)
4 |
5 |
6 | ## Technologies
7 |
8 | To build this app I used [ReactJS](https://reactjs.org/) v18, CSS, and HTML.
9 |
10 | ## Screenshots
11 |
12 | Here are some screenshots of the app's UI based on the components shown below
13 |
14 | ### Search Component
15 | 
16 |
17 | ### Grid Component
18 |
19 | 
20 |
21 | ### Modal Component
22 | Charizard | Blastoise | Venusaur
23 | :-------------------------:|:-------------------------:|:-------------------------:
24 |  |  | 
25 |
26 | ## Demo
27 |
28 | You can see it deployed [here](https://onnichan.github.io/pokeapi-react/) 👈
29 |
30 | ## Do you want to use or run this project locally?
31 |
32 | Just follow this steps:
33 |
34 |
35 | - In your system console write
36 |
37 | `git init`
38 | `git clone https://github.com/Onnichan/pokeapi-react.git`
39 |
40 | - Then you will have to type the following command, depending on what you have installed, npm or yarn.
41 |
42 | `npm install`
43 | or
44 | `yarn install`
45 | - and that's it! you can run it with the following command and view the application.
46 |
47 | `npm start`
48 |
49 |
50 |
51 | ## Contact
52 | You can follow me on my [Linkedin](https://www.linkedin.com/in/walter-daniel-huaynapata-aguilar-391041197/).
53 |
54 |
55 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | PokeApi
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/colors.css:
--------------------------------------------------------------------------------
1 | :root{
2 | --bg-light-color: #fff;
3 | --bg-dark-color: #000;
4 | --bg-after-color: rgba(14, 12, 14, 0.6);
5 | --bg-poke-color-light-normal: rgba(247, 243, 233, 0.928);
6 | --bg-poke-color-light-fighting: rgba(247, 216, 216, 0.886);
7 | --bg-poke-color-light-flying: rgba(247, 233, 242, 0.928);
8 | --bg-poke-color-light-poison: rgba(242, 233, 247, 0.928);
9 | --bg-poke-color-light-ground: rgba(247, 242, 233, 0.928);
10 | --bg-poke-color-light-rock: rgba(239, 221, 195, 0.796);
11 | --bg-poke-color-light-bug: rgba(234, 247, 233, 0.928);
12 | --bg-poke-color-light-ghost: rgba(245, 233, 247, 0.823);
13 | --bg-poke-color-light-steel: rgba(247, 243, 233, 0.928);
14 | --bg-poke-color-light-fire: rgba(247, 233, 233, 0.928);
15 | --bg-poke-color-light-water: rgba(176, 224, 238, 0.928);
16 | --bg-poke-color-light-grass: rgba(233, 247, 239, 0.928);
17 | --bg-poke-color-light-electric: rgba(247, 245, 233, 0.928);
18 | --bg-poke-color-light-psychic: rgba(247, 233, 243, 0.928);
19 | --bg-poke-color-light-ice: rgba(233, 238, 247, 0.928);
20 | --bg-poke-color-light-dragon: rgba(240, 233, 247, 0.928);
21 | --bg-poke-color-light-dark: rgba(148, 147, 144, 0.27);
22 | --bg-poke-color-light-fairy: rgba(247, 233, 244, 0.928);
23 | --bg-poke-color-light-unknown: rgba(247, 243, 233, 0.928);
24 | --bg-poke-color-light-shadow: rgba(247, 233, 243, 0.928);
25 |
26 | --bg-poke-color-dark-normal: rgba(235, 204, 142, 0.835);
27 | --bg-poke-color-dark-fighting: rgba(221, 88, 88, 0.835);
28 | --bg-poke-color-dark-flying: rgba(175, 100, 225, 0.667);
29 | --bg-poke-color-dark-poison: rgba(165, 92, 205, 0.835);
30 | --bg-poke-color-dark-ground: rgba(235, 207, 142, 0.511);
31 | --bg-poke-color-dark-rock: rgba(203, 140, 95, 0.749);
32 | --bg-poke-color-dark-bug: rgba(156, 235, 142, 0.835);
33 | --bg-poke-color-dark-ghost: rgba(203, 142, 235, 0.835);
34 | --bg-poke-color-dark-steel: rgba(145, 148, 146, 0.835);
35 | --bg-poke-color-dark-fire: rgba(235, 142, 142, 0.835);
36 | --bg-poke-color-dark-water: rgba(142, 235, 215, 0.835);
37 | --bg-poke-color-dark-grass: rgba(144, 232, 123, 0.835);
38 | --bg-poke-color-dark-electric: rgba(235, 230, 142, 0.835);
39 | --bg-poke-color-dark-psychic: rgba(235, 142, 221, 0.835);
40 | --bg-poke-color-dark-ice: rgba(142, 235, 234, 0.835);
41 | --bg-poke-color-dark-dragon: rgba(149, 95, 203, 0.831);
42 | --bg-poke-color-dark-dark: rgba(148, 147, 144, 0.928);
43 | --bg-poke-color-dark-fairy: rgba(235, 142, 230, 0.42);
44 | --bg-poke-color-dark-unknown: rgba(247, 243, 233, 0.928);
45 | --bg-poke-color-dark-shadow: rgba(247, 233, 243, 0.928);
46 | }
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import Search from './components/search';
2 | import Navbar from './components/navbar';
3 | import Footer from './components/footer';
4 | import Grid from './layout/grid';
5 | import Container from './layout/container';
6 | import React from 'react';
7 | import './App.css';
8 |
9 | export default class App extends React.Component{
10 |
11 | constructor(props){
12 | super(props);
13 | this.state = {
14 | pokemons: [],
15 | total: 0,
16 | notFound: false,
17 | search: [],
18 | searching: false,
19 | }
20 | this.handleSearch = this.handleSearch.bind(this);
21 | this.showPokemons = this.showPokemons.bind(this);
22 | this.nextPokemon = this.nextPokemon.bind(this);
23 | }
24 |
25 | async handleSearch(textSearch){
26 | if(!textSearch) {
27 | this.setState({
28 | search: [],
29 | notFound:false,
30 | })
31 | return;
32 | }
33 |
34 | this.setState({
35 | notFound: false,
36 | searching: true,
37 | })
38 | const api = await fetch(`https://pokeapi.co/api/v2/pokemon/${textSearch.toLowerCase()}`);
39 | const data = await api.json().catch(()=> undefined);
40 | if(!data){
41 | this.setState({
42 | notFound: true,
43 | })
44 | return;
45 | }else{
46 | this.setState({
47 | search: [data],
48 | })
49 | }
50 | this.setState({
51 | searching: false,
52 | })
53 | }
54 |
55 | async showPokemons(limit = 20, offset = 0){
56 |
57 | const api = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=${limit}&offset=${offset}`);
58 | const data = await api.json();
59 | const promises = await data.results.map(async pokemon => {
60 | const result = await fetch(pokemon.url);
61 | const res = await result.json();
62 | return res;
63 | });
64 |
65 | const results = await Promise.all(promises);
66 |
67 | this.setState(prev => ({
68 | search: [],
69 | pokemons: [...prev.pokemons, ...results],
70 | notFound: false,
71 | total: prev.total + results.length,
72 | }));
73 | }
74 |
75 | nextPokemon(){
76 | this.showPokemons(20,this.state.total);
77 | }
78 |
79 | componentDidMount(){
80 | if(!this.state.searching){
81 | this.showPokemons();
82 | }
83 | }
84 |
85 | render(){
86 |
87 | const poke = this.state.search.length > 0 ? this.state.search : this.state.pokemons;
88 | return (
89 | <>
90 |
91 |
92 |
93 | {
94 | this.state.notFound ? (
95 | 'Pokemon not found'
96 | ) : (
97 |
98 | )
99 | }
100 |
101 |
102 | >
103 | );
104 | }
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/src/components/modal.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {searchIcon} from '../utils/icons';
3 |
4 | export default class Modal extends React.Component{
5 |
6 | constructor(props){
7 | super(props);
8 | this.handleModal = this.handleModal.bind(this);
9 | }
10 |
11 | handleModal(){
12 | this.props.onHandleModal();
13 | }
14 | render(){
15 | const pokemon = this.props.pokemon;
16 | const colors = ['#FC6B6E','#2196F3','#094BE8','#2196F3','#3ED1E0','#CF9B48'];
17 |
18 | return(
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {/* {pokemon.types[0].type.name} */}
27 |
28 | {
29 | pokemon['past_types'].length > 0 &&
{pokemon['past_types'][0].generation.name}
30 | }
31 |
32 |
33 | Height: {pokemon.height}
34 | weight : {pokemon.weight}
35 | {/* {
36 | pokemon['past_types'].length > 0 && {pokemon['past_types'][0].generation.name}
37 | } */}
38 |
39 |
40 |
41 |

42 |
{pokemon.name}
43 |
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ex quaerat eligendi
44 |
45 |
46 |
47 |
Abilities
48 | {
49 | pokemon.abilities.map(({ability})=> (
50 | {ability.name}
51 | ))
52 | }
53 |
54 |
55 |
Stats
56 | {
57 | pokemon.stats.map((stat, index)=> (
58 |
59 |
60 | {stat.stat.name}
61 | {stat.base_stat}
62 |
63 |
64 | {
65 | stat.base_stat >= 100 ?
66 |
:
67 |
68 | }
69 |
70 |
71 | ))
72 | }
73 |
74 |
75 |
76 |
77 | )
78 | }
79 | }
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | @import url('./colors.css');
2 |
3 | *,::before,::after{
4 | margin: 0;
5 | padding: 0;
6 | box-sizing: border-box;
7 | }
8 |
9 | body{
10 | background-color: var(--bg-light-color);
11 | position: relative;
12 | /* overflow-x: hidden; */
13 | }
14 |
15 | .container{
16 | display: flex;
17 | flex-direction: column;
18 | min-height: 100vh;
19 | padding: 0 50px;
20 | }
21 |
22 | .navbar{
23 | padding: 20px 0;
24 | margin-bottom: 30px;
25 | }
26 |
27 | .navbar__title{
28 | display: block;
29 | text-align: center;
30 | font-weight: 700;
31 | font-size: 2.5em;
32 | text-shadow: 5px 5px 10px lightseagreen;
33 | }
34 |
35 | .search{
36 | padding: 10px;
37 | border-color: 1px solid black;
38 | width: 100%;
39 | height: 60px;
40 | /* min-height: 60px; */
41 | margin-bottom: 30px;
42 | display: flex;
43 | }
44 |
45 | .search__wrapper{
46 | /* display: inline-block; */
47 | width: 90%;
48 | height: 100%;
49 | position: relative;
50 | }
51 |
52 | .search__input{
53 | outline: none;
54 | padding: 10px 10px 10px 40px;
55 | width: 100%;
56 | height: 100%;
57 | border-top-left-radius: 4px;
58 | border-bottom-left-radius: 4px;
59 | border: 1px solid gray;
60 | color: lightseagreen;
61 | }
62 |
63 | .search__input:focus{
64 | border: 1px solid black;
65 | }
66 |
67 | .search__input::placeholder{
68 | color: lightseagreen;
69 | font-weight: 700;
70 | }
71 |
72 | .search__icon{
73 | position: absolute;
74 | left: 10px;
75 | top: 25%;
76 | bottom: 25%;
77 | height: 50%;
78 | }
79 |
80 | .search__button{
81 | display: block;
82 | width: 10%;
83 | height: 100%;
84 | background-color: black;
85 | border: 1px solid transparent;
86 | font-weight: 700;
87 | color: white;
88 | }
89 |
90 | .search__button:hover{
91 | cursor: pointer;
92 | }
93 |
94 | .grid{
95 | padding-bottom: 40px;
96 | }
97 |
98 | .grid__pokemon{
99 | display: grid;
100 | grid-template-columns: repeat(4, 1fr);
101 | grid-template-rows: repeat(5, 1fr);
102 | gap: 30px;
103 | padding: 10px;
104 | }
105 |
106 | .grid__button{
107 | background-color: lightseagreen;
108 | padding: 10px 20px;
109 | border-radius: 10px;
110 | font-weight: 700;
111 | margin: 0 auto;
112 | outline: none;
113 | border: none;
114 | }
115 |
116 | .grid__wrapper-button{
117 | padding-top: 20px;
118 | display: flex;
119 | align-items: center;
120 | position: relative;
121 | z-index: 7;
122 | }
123 |
124 | .grid__button:hover{
125 | cursor: pointer;
126 | }
127 |
128 | .card{
129 | display: flex;
130 | align-items: flex-end;
131 | justify-content: space-around;
132 | border-radius: 5px;
133 | position: relative;
134 | padding: 20px 0; /* rgba(233, 247, 239, 0.928); */
135 | background-color: rgba(148, 147, 144, 0.27);
136 | }
137 |
138 | .card::after{
139 | content: '';
140 | position: absolute;
141 | width: 40px;
142 | height: 80px;
143 | top: 25%;
144 | right: 50px;
145 | background-color: rgba(255, 255, 255, 0.579);
146 | border-radius: 50%;
147 | transform: rotateZ(8deg);
148 | }
149 |
150 | /* .card::before{
151 | content: '';
152 | position: absolute;
153 | width: 150px;
154 | height: 150px;
155 | top: 60%;
156 | right: -90px;
157 | background-color: white;
158 | box-shadow: 1px 1px 10px white;
159 | border-radius: 50%;
160 | } */
161 |
162 | .card:hover{
163 | cursor: pointer;
164 | }
165 |
166 | .card__title{
167 | display: flex;
168 | align-items: center;
169 | position: absolute;
170 | top: 6%;
171 | left: 5%;
172 | height: 15%;
173 | }
174 |
175 | .card__title-img{
176 | display: block;
177 | width: 100%;
178 | height: 100%;
179 | }
180 |
181 | .card__title-text{
182 | margin-left: 10px;
183 | font-weight: 500;
184 | }
185 |
186 | .card__badge{
187 | position: absolute;
188 | top: 0;
189 | right: 0;
190 | padding: 2px 5px;
191 | border-radius: 5px;
192 | font-size: 0.8em;
193 | text-align: center;
194 | color: rgba(0, 0, 0, 0.739);
195 | font-weight: 700;
196 |
197 | display: flex;
198 | /* align-items: center; */
199 | justify-content: flex-start;
200 | }
201 |
202 | .card__badge-Icon{
203 | display: inline-block;
204 | margin-right: 10px;
205 | width: 20%;
206 | height: 100%;
207 | }
208 |
209 | .card__badge-text{
210 | display: inline-block;
211 | text-align: center;
212 | }
213 |
214 | .card__image{
215 | display: block;
216 | z-index: 2;
217 | width: 40%;
218 | height: 100%;
219 | }
220 |
221 | .modal{
222 | background-color: rgba(247, 242, 242, 0.961);
223 | position: fixed;
224 | top: 50%;
225 | transform: translateY(-50%);
226 | left: 35%;
227 | right: 35%;
228 | color: black;
229 | z-index: 10;
230 | border-radius: 10px;
231 | }
232 |
233 | .modal__content{
234 | display: flex;
235 | flex-direction: column;
236 | }
237 |
238 | .modal__content-features,
239 | .modal__content-description,
240 | .modal__content-other{
241 | padding: 20px;
242 | }
243 |
244 | .modal__content-features{
245 | border-top-left-radius: 10px;
246 | border-top-right-radius: 10px;
247 | margin-bottom: -94px;
248 | height: 150px;
249 | font-size: 0.9em;
250 | font-weight: 600;
251 | display: flex;
252 | justify-content: space-between;
253 | color: black;
254 | }
255 |
256 | .modal__content-featuresHabitat{
257 | width: 100%;
258 | display: flex;
259 | }
260 |
261 | .modal__content-featuresImage{
262 | width: 60px;
263 | height: 60px;
264 | display: block;
265 | }
266 |
267 | .modal__content-featuresRight,
268 | .modal__content-featuresLeft{
269 | display: flex;
270 | flex-direction: column;
271 | row-gap: 10px;
272 | }
273 |
274 | .modal__content-features span:not(.modal__content-featuresHabitat){
275 | /* background-color: #e3d7b2; */
276 | border-radius: 5px;
277 | padding: 0 10px;
278 | border: 1px solid black;
279 | }
280 |
281 | .modal__content-description{
282 | display: flex;
283 | flex-direction: column;
284 | align-items: center;
285 | }
286 |
287 | .modal__content-descriptionImage{
288 | display: block;
289 | width: 40%;
290 | margin-bottom: -10px;
291 | border-radius: 50%;
292 | background-color: rgba(247, 242, 242, 0.961);
293 | }
294 |
295 | .modal__content-descriptionTitle{
296 | font-size: 1.4em;
297 | text-transform: uppercase;
298 | }
299 |
300 | .modal__content-descriptionParagraph{
301 | text-align: center;
302 | font-size: 0.8em;
303 | margin-top: 1em;
304 | }
305 |
306 | .modal__content-other{
307 | display: flex;
308 | justify-content: space-around;
309 | gap: 20px;
310 | }
311 |
312 | .modal__content-otherBreadcrumbAbility{
313 | display: flex;
314 | flex-direction: column;
315 | margin-top: 5px;
316 | }
317 |
318 | .modal__content-otherBreadcrumbAbilities{
319 | margin-bottom: 10px;
320 | }
321 |
322 | .modal__content-otherStats{
323 | width: 60%;
324 | }
325 |
326 | .modal__content-otherStatsTitle{
327 | text-align: center;
328 | }
329 |
330 | .modal__content-otherStat{
331 | display: flex;
332 | flex-direction: column;
333 | }
334 |
335 | .modal__content-otherStatContent{
336 | font-size: 0.7em;
337 | display: flex;
338 | justify-content: space-between;
339 | }
340 |
341 | .modal__content-otherStatTimeLine{
342 | background-color: gray;
343 | width: 100%;
344 | height: 0.4em;
345 | border-radius: 5px;
346 | margin-bottom: 5px;
347 | position: relative;
348 | }
349 |
350 | /* .modal__content-otherStatTimeLine::after{
351 | content: '';
352 | position: absolute;
353 | top: 0;
354 | left: 0;
355 | width: 50px;
356 | height: inherit;
357 | border-radius: 5px;
358 | background-color: black;
359 | z-index: 10;
360 | } */
361 |
362 | .modal__content-otherStatTimeLineStat{
363 | position: absolute;
364 | top: 0;
365 | left: 0;
366 | height: inherit;
367 | border-radius: 5px;
368 | background-color: black;
369 | z-index: 10;
370 | }
371 |
372 | .dark::after{
373 | content: '';
374 | position: absolute;
375 | top: 0;
376 | left: 0;
377 | right: 0;
378 | bottom: 0;
379 | background-color: var(--bg-after-color);
380 | z-index: 9;
381 | }
382 |
383 | .modal__close{
384 | position: absolute;
385 | top: -25px;
386 | right: 10px;
387 | background-color: transparent;
388 | border: none;
389 | outline: none;
390 | z-index: 11;
391 | font-size: 1.1em;
392 | }
393 |
394 | .modal__close:hover{
395 | cursor: pointer;
396 | }
397 |
398 | .footer{
399 | margin-top: auto;
400 | background-color: var(--bg-dark-color);
401 | color: lightseagreen;
402 | padding: 12px 0;
403 | text-align: center;
404 | }
405 |
406 | @media only screen and (max-width: 1030px){
407 | .grid__pokemon{
408 | grid-template-columns: repeat(3, 1fr);
409 | }
410 | .card__image{
411 | width: 40%;
412 | height: 100%;
413 | }
414 |
415 | .modal{
416 | right: 27%;
417 | left: 27%;
418 | }
419 | }
420 |
421 | @media only screen and (max-width: 760px){
422 | .grid__pokemon{
423 | grid-template-columns: repeat(2, 1fr);
424 | }
425 |
426 | .card__image{
427 | width: 40%;
428 | }
429 |
430 | .modal{
431 | right: 15%;
432 | left: 15%;
433 | }
434 |
435 | .search__wrapper{
436 | width: 80%;
437 | }
438 |
439 | .search__button{
440 | width: 20%;
441 | }
442 | }
443 |
444 | @media only screen and (max-width: 550px){
445 | .grid__pokemon{
446 | grid-template-columns: 1fr;
447 | }
448 |
449 | .card__image{
450 | width: 40%;
451 | height: 100%;
452 | }
453 |
454 | .modal{
455 | right: 14%;
456 | left: 14%;
457 | }
458 |
459 | .search__wrapper{
460 | width: 80%;
461 | }
462 |
463 | .search__button{
464 | width: 20%;
465 | }
466 | }
467 |
468 | @media only screen and (max-width: 430px){
469 | .grid__pokemon{
470 | grid-template-columns: 1fr;
471 | }
472 |
473 | .card__image{
474 | width: 40%;
475 | height: 100%;
476 | }
477 |
478 | .modal{
479 | right: 0;
480 | left: 0;
481 | }
482 |
483 | .search__wrapper{
484 | width: 80%;
485 | }
486 |
487 | .search__button{
488 | width: 20%;
489 | }
490 |
491 | .container{
492 | padding: 0;
493 | }
494 | }
--------------------------------------------------------------------------------