├── .firebase └── hosting.YnVpbGQ.cache ├── .firebaserc ├── .gitignore ├── README.md ├── firebase.json ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json ├── pokedex-icon.png └── robots.txt └── src ├── App.css ├── App.js ├── App.test.js ├── DetailView.js ├── PokemonCard.js ├── Sansation_Regular.woff ├── index.css ├── index.js ├── serviceWorker.js └── setupTests.js /.firebase/hosting.YnVpbGQ.cache: -------------------------------------------------------------------------------- 1 | asset-manifest.json,1584594627032,2276d1da74ab850b1751d82c070b0923b4f561c67e8e0338287a20e90fb06b87 2 | index.html,1584594627032,0ab0451bca0c2319519eb48f068ab535fa51f472c550d65c65b098d534be8af4 3 | favicon.ico,1584594609516,1939e941502147d83301304106423da028f11187ecb80a6dee74e5727554ce23 4 | manifest.json,1584594609521,341d52628782f8ac9290bbfc43298afccb47b7cbfcee146ae30cf0f46bc30900 5 | precache-manifest.6cce5224a2f142fdb85032ee1888edda.js,1584594627032,8efa77e20cedde01c0ade276cb24e0af7b6eee29f4232f8aad01a9ad0ffc3b85 6 | service-worker.js,1584594627032,007126abbb98dd3fa7990f1d88a0ad68ef301b68711454bf0d4acee27e0d7dfe 7 | logo192.png,1584594609518,caff018b7f1e8fd481eb1c50d75b0ef236bcd5078b1d15c8bb348453fee30293 8 | static/css/main.25827d29.chunk.css,1584594627035,25eb55075af646c372890d7afe3b678b095461d6fa31a721ba12e210255301e8 9 | static/css/main.25827d29.chunk.css.map,1584594627044,8713e9b7356637f56f412e2991e78eb92dd1910c1315ad375f7badb9839d78d7 10 | static/js/2.371954d0.chunk.js.LICENSE.txt,1584594627044,c96bb263ae98c52191b5a65af7fbcce00fa4735a52e8e30f884909825eb24a81 11 | static/js/runtime-main.801dd740.js,1584594627044,2f1b41f2b009b859ddcb6d0bafd0fbf0457cc37dae5529f103a975394c63b382 12 | static/js/runtime-main.801dd740.js.map,1584594627044,256800455c89858a486caa38f7d1359cd749ed41335ebce5a2f88c7de6a96726 13 | static/js/main.03485571.chunk.js.map,1584594627044,dc043d2ef4a98d4dafdf47e39a031d7234a0729834a0429fc0557ba884049fec 14 | logo512.png,1584594609520,191fc21360b4ccfb1cda11a1efb97f489ed22672ca83f4064316802bbfdd750e 15 | static/js/main.03485571.chunk.js,1584594627036,eeedff81176d364e8ddccd530d79a8e14e91b786909fbf85515c6fc1b926971e 16 | robots.txt,1584594609525,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2 17 | static/media/Sansation_Regular.cbbd297b.woff,1584594627034,cb5c89c26bad22d213b57f71ed4cee9e9b3170eb36af6c8d91116cc21f3e8fbf 18 | pokedex-icon.png,1584594609524,7da6762e2bb22aceef7abc59dcb645d75138fc2c91f252fe7475ddcafbb4f612 19 | static/js/2.371954d0.chunk.js,1584594627044,ecc9fe1631a3dbed67a771788722791f39e84746fc9d219a615c93fd6371e865 20 | static/js/2.371954d0.chunk.js.map,1584594627045,93d76c670cbfcbef1bf0317f639e4e37087847fe861b38c28f2105bb821c73c0 21 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "react-pokedex-hcde" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `npm run build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pokedex", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^4.9.3", 7 | "@material-ui/icons": "^4.9.1", 8 | "@testing-library/jest-dom": "^4.2.4", 9 | "@testing-library/react": "^9.4.0", 10 | "@testing-library/user-event": "^7.2.1", 11 | "antd": "^4.0.3", 12 | "npm": "^6.14.2", 13 | "pokemon-gif": "^1.0.14", 14 | "react": "^16.12.0", 15 | "react-div-100vh": "^0.3.8", 16 | "react-dom": "^16.12.0", 17 | "react-poke-sprites": "0.0.8", 18 | "react-scripts": "3.3.1", 19 | "styled-components": "^5.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": "react-app" 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aargyle/React-Pokedex/8e5267cd4369f2aaf6a77ea84b309c3a01414307/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React Pokédex 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aargyle/React-Pokedex/8e5267cd4369f2aaf6a77ea84b309c3a01414307/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aargyle/React-Pokedex/8e5267cd4369f2aaf6a77ea84b309c3a01414307/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/pokedex-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aargyle/React-Pokedex/8e5267cd4369f2aaf6a77ea84b309c3a01414307/public/pokedex-icon.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | /* mobile */ 2 | html { 3 | font-size: 12px 4 | } 5 | 6 | /* tablet */ 7 | @media only screen and (min-width: 600px){ 8 | html { 9 | font-size: 14px 10 | } 11 | } 12 | 13 | /* desktop */ 14 | @media only screen and (min-width: 768px){ 15 | html { 16 | font-size: 16px 17 | } 18 | } 19 | 20 | /* Font */ 21 | 22 | @font-face { 23 | font-family: 'Sansation'; 24 | font-style: normal; 25 | font-weight: normal; 26 | src: local('Sansation'), url('Sansation_Regular.woff') format('woff'); 27 | } 28 | 29 | /* App CSS */ 30 | .app { 31 | top: 0; 32 | left: 0; 33 | width: 100%; 34 | position: absolute; 35 | } 36 | 37 | .content { 38 | width: 100%; 39 | } 40 | 41 | body { 42 | text-align: center; 43 | background-color: #373737; 44 | font-family: 'Sansation', sans-serif; 45 | } 46 | 47 | header{ 48 | width: 100%; 49 | height: 10vh; 50 | position: fixed; 51 | z-index: 1; 52 | left: 0; 53 | top: 0; 54 | background-color: white; 55 | display: flex; 56 | align-items: center; 57 | color: #EC4444; 58 | font-family: Helvetica; 59 | box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); 60 | justify-content: space-between; 61 | border-bottom-right-radius: 15px; 62 | border-bottom-left-radius: 15px; 63 | } 64 | 65 | header img { 66 | width: 4rem; 67 | height: 4rem; 68 | margin-right: 1vw; 69 | margin-left: 1vw; 70 | } 71 | 72 | .header-wrapper { 73 | display: block; 74 | } 75 | 76 | h2 { 77 | font-family: 'Sansation', sans-serif; 78 | color: #EC4444; 79 | font-size: 3rem; 80 | cursor: default; 81 | } 82 | 83 | h5 { 84 | font-size: 1rem; 85 | } 86 | /* 87 | .input-wrap { 88 | width: 90vw; 89 | display: flex; 90 | margin-top: 13vh; 91 | margin-left: 5vw; 92 | margin-right: 5vw; 93 | }*/ 94 | 95 | .input { 96 | margin-right: 5px; 97 | width: 98% 98 | } 99 | 100 | .poke-list { 101 | max-width: 100vw; 102 | margin-top: 2vh; 103 | display: flex; 104 | flex-wrap: wrap; 105 | justify-content: space-evenly; 106 | } 107 | 108 | .poke-list-detail { 109 | max-width: 50vw; 110 | margin-top: 2vh; 111 | display: flex; 112 | flex-wrap: wrap; 113 | justify-content: space-evenly; 114 | } 115 | 116 | .pokemon-card { 117 | border-radius: 5px; 118 | background-color: white; 119 | } 120 | 121 | .card-data { 122 | display: flex; 123 | width: 100%; 124 | justify-content: space-between; 125 | height: 15px; 126 | } 127 | 128 | .detail-card { 129 | top: 19vh; 130 | width: 45vw; 131 | max-height: 60%; 132 | margin-left: 2vw; 133 | border-radius: 15px; 134 | background-color: #EC4444; 135 | position: fixed; 136 | right: 2vw; 137 | box-shadow: 10px 10px 39px -8px rgba(0,0,0,0.75); 138 | } 139 | 140 | .detail-card-mobile { 141 | top: 35vh; 142 | left: 5vw; 143 | width: 90vw; 144 | max-height: 60%; 145 | border-radius: 15px; 146 | background-color: #EC4444; 147 | position: fixed; 148 | box-shadow: 10px 10px 39px -8px rgba(0,0,0,0.75); 149 | } 150 | 151 | .upper-details { 152 | width: 100%; 153 | display: flex; 154 | justify-content: space-evenly; 155 | min-height: 20vh; 156 | } 157 | 158 | .stats { 159 | width: 50%; 160 | height: 100%; 161 | display: flex; 162 | flex-direction: column; 163 | } 164 | 165 | .flavor-text { 166 | margin-left: 20px; 167 | margin-right: 20px; 168 | margin-bottom: 20px; 169 | background-color: white; 170 | border-radius: 15px; 171 | padding: 2px; 172 | } 173 | 174 | .detail-image { 175 | margin: 20px; 176 | width: 40%; 177 | background-color: white; 178 | border-radius: 15px; 179 | } 180 | 181 | .detail-image img { 182 | height: 70%; 183 | width: 70%; 184 | } 185 | 186 | p { 187 | color: #373737; 188 | size: 1rem; 189 | } 190 | 191 | .line { 192 | display: flex; 193 | height: 1.5rem; 194 | } 195 | 196 | .stats-details { 197 | color: white; 198 | margin-left: 5px; 199 | } 200 | 201 | .close { 202 | width: 1.5rem; 203 | height: 1.5rem; 204 | color: white; 205 | cursor: pointer; 206 | margin-top: 3px; 207 | margin-right: 3px 208 | } 209 | 210 | .search-wrapper { 211 | width: 80vw; 212 | margin-top: 12vh; 213 | margin-left: 10vw; 214 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import './App.css'; 3 | import PokemonCard from './PokemonCard.js'; 4 | import DetailView from './DetailView.js'; 5 | import TextField from '@material-ui/core/TextField'; 6 | import styled from 'styled-components'; 7 | 8 | // custom styles for TextField 9 | const StyledTextField = styled(TextField)` 10 | label { 11 | color: white; 12 | font-family: 'Sansation' 13 | } 14 | .MuiOutlinedInput-root { 15 | fieldset { 16 | border-color: white; 17 | border-radius: 130px; 18 | } 19 | &:hover fieldset { 20 | border-color: white; 21 | } 22 | &.Mui-focused fieldset { 23 | border-color: white; 24 | } 25 | } 26 | span { 27 | color: white; 28 | } 29 | span.focused { 30 | color: white; 31 | } 32 | input { 33 | color: white; 34 | } 35 | label.Mui-focused{ 36 | color: white; 37 | } 38 | `; 39 | 40 | function App() { 41 | const [detailIndex, setIndex] = useState(null) 42 | const [text, setText] = useState('') 43 | const [pokedata, setPokedata] = useState([]) 44 | const [tempdata, setTempdata] = useState([]) 45 | 46 | useEffect(()=>{ 47 | for(let i = 1; i < 101; i++) { 48 | fetch('https://pokeapi.co/api/v2/pokemon/' + i + '/') 49 | .then(res => res.json()) 50 | .then(data => { 51 | setPokedata(current=>{ 52 | const sortedData = [...current, data] 53 | sortedData.sort((a,b)=> a.id-b.id) 54 | return sortedData 55 | }) 56 | setTempdata(current=>{ 57 | const sortedData = [...current, data] 58 | sortedData.sort((a,b)=> a.id-b.id) 59 | return sortedData 60 | }) 61 | }) 62 | .catch(err => console.log(err)); 63 | } 64 | }, []) 65 | 66 | function searchClick(res) { 67 | setText(res) 68 | console.log('query: ' + res) 69 | function filterItems(arr, query) { 70 | return arr.filter(function(el) { 71 | let name = el.name 72 | return name.toLowerCase().indexOf(query.toLowerCase()) !== -1 73 | }) 74 | } 75 | const filteredItems = filterItems(pokedata, res) 76 | if (filteredItems.length > 0) { 77 | setTempdata(filterItems(pokedata, res)) 78 | } 79 | } 80 | 81 | let details = {} 82 | let showDetails = false 83 | if (detailIndex || detailIndex === 0) { 84 | details = tempdata[detailIndex] 85 | showDetails = true 86 | } 87 | 88 | let pokeClass = 'poke-list' 89 | let detailClass = 'detail-card' 90 | let isMobile = false 91 | if (window.innerWidth < 768) { 92 | isMobile = true 93 | } 94 | 95 | // change classname conditionally 96 | if (showDetails && !isMobile) { 97 | pokeClass = 'poke-list-detail' 98 | } 99 | 100 | // change class of DetailView if mobile screen 101 | if (showDetails && isMobile) { 102 | console.log('Switching to mobile') 103 | detailClass = 'detail-card-mobile' 104 | } 105 | 106 | return ( 107 |
108 |
109 |
110 | searchClick(e.target.value)} 114 | /> 115 |
116 |
117 | {tempdata.map((data, i)=> setIndex(i)} key={i} name={data.name} id={data.id} type={data.types} image={data.sprites.front_default} />)} 118 |
119 | {showDetails && setIndex(null)} {...details} />} 120 |
121 | ); 122 | } 123 | 124 | function Header() { 125 | return
126 |
127 |
128 | logo window.scrollTo(0, 0)}/> 129 |

window.scrollTo(0, 0)}> Pokédex

130 |
131 |
132 |
133 | } 134 | 135 | export default App; 136 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/DetailView.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import pokemonGif from 'pokemon-gif'; 3 | import CloseIcon from '@material-ui/icons/Close'; 4 | 5 | function DetailView(props) { 6 | const [speciesData, setData] = useState([]) 7 | useEffect(()=>{ 8 | fetch('https://pokeapi.co/api/v2/pokemon-species/' + props.id + '/') 9 | .then(res => res.json()) 10 | .then(data => { 11 | setData(() =>{ 12 | let category = data['genera'][2]['genus'].split(' ')[0] 13 | // make sure flavor text is in english 14 | let flavorText 15 | 16 | let i = 0 17 | while (data['flavor_text_entries'][i]['language']['name'] !== 'en') { 18 | i++; 19 | } 20 | 21 | flavorText = data['flavor_text_entries'][i]['flavor_text'] 22 | flavorText = flavorText.replace( /[\r\n]+/gm, " " ); 23 | return [flavorText, category] 24 | }) 25 | }) 26 | .catch(err => console.log(err)); 27 | }, [props.id]) 28 | 29 | //capitalize stats 30 | let type 31 | if (props.types.length < 2) { 32 | type = props.types[0]['type']['name'] 33 | type = type.charAt(0).toUpperCase() + type.substring(1) 34 | } else { 35 | let type1 = props.types[1]['type']['name'] 36 | type1 = type1.charAt(0).toUpperCase() + type1.substring(1) 37 | let type2 = props.types[0]['type']['name'] 38 | type2 = type2.charAt(0).toUpperCase() + type2.substring(1) 39 | type = type1 + '/' + type2 40 | } 41 | let name = props.name.charAt(0).toUpperCase() + props.name.substring(1) 42 | 43 | //height in decimeters 44 | let height = props.height / 3.048 45 | height = height.toFixed(2) + ' ft' 46 | 47 | //weight in hectograms 48 | let weight = props.weight / 4.536 49 | weight = weight.toFixed(2) + ' lbs' 50 | 51 | let gifURL 52 | if (props.name === 'nidoran-f') { 53 | name = 'Nidoran-F' 54 | gifURL = pokemonGif(29) 55 | } else if (props.name === 'nidoran-m') { 56 | name = 'Nidoran-M' 57 | gifURL = pokemonGif(32) 58 | } else { 59 | gifURL = pokemonGif(props.name) 60 | } 61 | 62 | return
63 |
64 |
65 | animated gif of pokemon 66 |
67 |
68 |
69 |
Name:
{name}
70 |
71 |
72 |
Type:
{type}
73 |
74 |
75 |
Category:
{speciesData[1]}
76 |
77 |
78 |
Height:
{height}
79 |
80 |
81 |
Weight:
{weight}
82 |
83 |
84 |
props.onClick()}>
85 |
86 |
87 |

{speciesData[0]}

88 |
89 |
90 | } 91 | 92 | export default DetailView -------------------------------------------------------------------------------- /src/PokemonCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import Card from '@material-ui/core/Card'; 4 | import CardActionArea from '@material-ui/core/CardActionArea'; 5 | import CardContent from '@material-ui/core/CardContent'; 6 | 7 | const useStyles = makeStyles({ 8 | root: { 9 | width: 156, 10 | height: 156, 11 | marginBottom: 10, 12 | }, 13 | media: { 14 | height: 100, 15 | }, 16 | data: { 17 | fontFamily: 'Sansation', 18 | height: 56, 19 | padding: 0, 20 | }, 21 | id: { 22 | margin: 5, 23 | }, 24 | type: { 25 | margin: 5, 26 | }, 27 | name: { 28 | fontFamily: 'Sansation', 29 | fontSize: 18, 30 | fontWeight: 'normal', 31 | }, 32 | img: { 33 | height: 100, 34 | width: 100, 35 | } 36 | }); 37 | 38 | function PokemonCard(props) { 39 | const classes = useStyles(); 40 | 41 | // add formatting to id 42 | let idstring = props.id 43 | if (props.id < 10) { 44 | idstring = '#00' + props.id 45 | } else if (props.id > 9 && props.id < 100) { 46 | idstring = '#0' + props.id 47 | } else { 48 | idstring = '#' + props.id 49 | } 50 | 51 | // capitalize first letter of name 52 | let name = props.name 53 | if (props.name === 'nidoran-f') { 54 | name = 'Nidoran-F' 55 | } else if (props.name === 'nidoran-m') { 56 | name = 'Nidoran-M' 57 | } else { 58 | name = name.charAt(0).toUpperCase() + name.substring(1) 59 | } 60 | 61 | // change background color and abbreviate type 62 | let bgcolor = '#FFFFFF'; 63 | let typeShort = ''; 64 | let type = props.type[0]['type']['name'] //could just use the second elements in array, then get rid of first if statement 65 | 66 | if (type === 'grass') { 67 | bgcolor = '#98FF87' 68 | typeShort = 'GRS' 69 | } else if (type === 'fire') { 70 | bgcolor = '#FDA777' 71 | typeShort = 'FIR' 72 | } else if (type === 'water') { 73 | bgcolor = '#9DEDFF' 74 | typeShort = 'WTR' 75 | } else if (type === 'normal') { 76 | bgcolor = '#D3C969' 77 | typeShort = 'NRM' 78 | } else if (type === 'ice') { 79 | bgcolor = '#B9F6F6' 80 | typeShort = 'ICE' 81 | } else if (type === 'bug') { 82 | bgcolor = '#CADC33' 83 | typeShort = 'BUG' 84 | } else if (type === 'fighting') { 85 | bgcolor = '#EA5850' 86 | typeShort = 'FGT' 87 | } else if (type === 'flying') { 88 | bgcolor = '#CBBEF1' 89 | typeShort = 'FLY' 90 | } else if (type === 'poison') { 91 | bgcolor = '#DD78DD' 92 | typeShort = 'PSN' 93 | } else if (type === 'ground') { 94 | bgcolor = '#EFD58B' 95 | typeShort = 'GRD' 96 | } else if (type === 'psychic') { 97 | bgcolor = '#FFA3BE' 98 | typeShort = 'PSY' 99 | } else if (type === 'rock') { 100 | bgcolor = '#DDB400' 101 | typeShort = 'RCK' 102 | } else if (type === 'ghost') { 103 | bgcolor = '#9473CA' 104 | typeShort = 'GHT' 105 | } else if (type === 'dragon') { 106 | bgcolor = '#7038F8' 107 | typeShort = 'DRG' 108 | } else if (type === 'dark') { 109 | bgcolor = '#8F8F8F' 110 | typeShort = 'DRK' 111 | } else if (type === 'steel') { 112 | bgcolor = '#B8B8D0' 113 | typeShort = 'STL' 114 | } else if (type === 'fairy') { 115 | bgcolor = '#FF9EF5' 116 | typeShort = 'FRY' 117 | } else if (type === 'electric') { 118 | bgcolor = '#FCFF76' 119 | typeShort = 'ELC' 120 | } 121 | 122 | // If Pokemon has two types, use a gradient for background, and change abbreviation 123 | if (props.type.length === 2) { 124 | type = props.type[1]['type']['name'] 125 | if (type === 'grass') { 126 | bgcolor = 'linear-gradient(145deg, #98FF87 30%, ' + bgcolor + ' 70%)' 127 | typeShort = 'GRS/' + typeShort 128 | } else if (type === 'fire') { 129 | bgcolor = 'linear-gradient(145deg, #FDA777 30%, ' + bgcolor + ' 70%)' 130 | typeShort = 'FIR/' + typeShort 131 | } else if (type === 'water') { 132 | bgcolor = 'linear-gradient(145deg, #9DEDFF 30%, ' + bgcolor + ' 70%)' 133 | typeShort = 'WTR/' + typeShort 134 | } else if (type === 'normal') { 135 | bgcolor = 'linear-gradient(145deg, #D3C969 30%, ' + bgcolor + ' 70%)' 136 | typeShort = 'NRM/' + typeShort 137 | } else if (type === 'ice') { 138 | bgcolor = 'linear-gradient(145deg, #B9F6F6 30%, ' + bgcolor + ' 70%)' 139 | typeShort = 'ICE/' + typeShort 140 | } else if (type === 'bug') { 141 | bgcolor = 'linear-gradient(145deg, #CADC33 30%, ' + bgcolor + ' 70%)' 142 | typeShort = 'BUG/' + typeShort 143 | } else if (type === 'fighting') { 144 | bgcolor = 'linear-gradient(145deg, #EA5850 30%, ' + bgcolor + ' 70%)' 145 | typeShort = 'FGT/' + typeShort 146 | } else if (type === 'flying') { 147 | bgcolor = 'linear-gradient(145deg, #CBBEF1 30%, ' + bgcolor + ' 70%)' 148 | typeShort = 'FLY/' + typeShort 149 | } else if (type === 'poison') { 150 | bgcolor = 'linear-gradient(145deg, #DD78DD 30%, ' + bgcolor + ' 70%)' 151 | typeShort = 'PSN/' + typeShort 152 | } else if (type === 'ground') { 153 | bgcolor = 'linear-gradient(145deg, #EFD58B 30%, ' + bgcolor + ' 70%)' 154 | typeShort = 'GRD/' + typeShort 155 | } else if (type === 'psychic') { 156 | bgcolor = 'linear-gradient(145deg, #FFA3BE 30%, ' + bgcolor + ' 70%)' 157 | typeShort = 'PSY/' + typeShort 158 | } else if (type === 'rock') { 159 | bgcolor = 'linear-gradient(145deg, #DDB400 30%, ' + bgcolor + ' 70%)' 160 | typeShort = 'RCK/' + typeShort 161 | } else if (type === 'ghost') { 162 | bgcolor = 'linear-gradient(145deg, #9473CA 30%, ' + bgcolor + ' 70%)' 163 | typeShort = 'GHT/' + typeShort 164 | } else if (type === 'dragon') { 165 | bgcolor = 'linear-gradient(145deg, #7038F8 30%, ' + bgcolor + ' 70%)' 166 | typeShort = 'DRG/' + typeShort 167 | } else if (type === 'dark') { 168 | bgcolor = 'linear-gradient(145deg, #8F8F8F 30%, ' + bgcolor + ' 70%)' 169 | typeShort = 'DRK/' + typeShort 170 | } else if (type === 'steel') { 171 | bgcolor = 'linear-gradient(145deg, #B8B8D0 30%, ' + bgcolor + ' 70%)' 172 | typeShort = 'STL/' + typeShort 173 | } else if (type === 'steel') { 174 | bgcolor = 'linear-gradient(145deg, #FF9EF5 30%, ' + bgcolor + ' 70%)' 175 | typeShort = 'FRY/' + typeShort 176 | } else if (type === 'electric') { 177 | bgcolor = 'linear-gradient(145deg, #FCFF76 30%, ' + bgcolor + ' 70%)' 178 | typeShort = 'ELC/' + typeShort 179 | } 180 | } 181 | 182 | return 183 | props.onClick(props.id)}> 184 |
185 | {name} 186 |
187 | 188 |
189 |

{idstring}

190 |

{typeShort}

191 |
192 |

{name}

193 |
194 |
195 |
196 | } 197 | 198 | export default PokemonCard -------------------------------------------------------------------------------- /src/Sansation_Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aargyle/React-Pokedex/8e5267cd4369f2aaf6a77ea84b309c3a01414307/src/Sansation_Regular.woff -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' } 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready.then(registration => { 134 | registration.unregister(); 135 | }); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | --------------------------------------------------------------------------------