├── .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 | You need to enable JavaScript to run this app.
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
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 |
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 |
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 |
--------------------------------------------------------------------------------