├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── pokemon │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ ├── 9.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.jpg │ ├── 19.jpg │ ├── 20.jpg │ ├── 21.jpg │ ├── 22.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── 25.jpg │ ├── 26.jpg │ ├── 27.jpg │ ├── 28.jpg │ ├── 30.jpg │ ├── 31.jpg │ ├── 33.jpg │ ├── 34.jpg │ ├── 35.jpg │ ├── 36.jpg │ ├── 37.jpg │ ├── 38.jpg │ ├── 39.jpg │ ├── 40.jpg │ ├── 41.jpg │ ├── 42.jpg │ ├── 43.jpg │ ├── 44.jpg │ ├── 45.jpg │ ├── 29.jpg │ ├── 32.jpg │ ├── 10.json │ ├── 11.json │ ├── 19.json │ ├── 20.json │ ├── 23.json │ ├── 24.json │ ├── 29.json │ ├── 30.json │ ├── 32.json │ ├── 33.json │ ├── 35.json │ ├── 36.json │ ├── 37.json │ ├── 4.json │ ├── 5.json │ ├── 7.json │ ├── 8.json │ ├── 9.json │ ├── 25.json │ ├── 26.json │ ├── 27.json │ ├── 28.json │ ├── 38.json │ ├── 13.json │ ├── 14.json │ ├── 2.json │ ├── 44.json │ ├── 1.json │ ├── 12.json │ ├── 15.json │ ├── 16.json │ ├── 17.json │ ├── 18.json │ ├── 21.json │ ├── 22.json │ ├── 3.json │ ├── 31.json │ ├── 34.json │ ├── 41.json │ ├── 42.json │ ├── 43.json │ ├── 45.json │ ├── 6.json │ ├── 39.json │ └── 40.json ├── pages │ ├── 4.json │ ├── 2.json │ ├── 1.json │ ├── 0.json │ └── 3.json ├── manifest.json └── index.html ├── src ├── setupTests.js ├── App.test.js ├── index.css ├── reportWebVitals.js ├── App.css ├── pokemonViewer.json ├── index.js ├── Components.jsx ├── App.js ├── usePokemon.js ├── logo.svg └── pokemonViewerMachine.js ├── .gitignore ├── package.json └── README.md /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/pokemon/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/1.jpg -------------------------------------------------------------------------------- /public/pokemon/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/2.jpg -------------------------------------------------------------------------------- /public/pokemon/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/3.jpg -------------------------------------------------------------------------------- /public/pokemon/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/4.jpg -------------------------------------------------------------------------------- /public/pokemon/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/5.jpg -------------------------------------------------------------------------------- /public/pokemon/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/6.jpg -------------------------------------------------------------------------------- /public/pokemon/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/7.jpg -------------------------------------------------------------------------------- /public/pokemon/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/8.jpg -------------------------------------------------------------------------------- /public/pokemon/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/9.jpg -------------------------------------------------------------------------------- /public/pokemon/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/10.jpg -------------------------------------------------------------------------------- /public/pokemon/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/11.jpg -------------------------------------------------------------------------------- /public/pokemon/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/12.jpg -------------------------------------------------------------------------------- /public/pokemon/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/13.jpg -------------------------------------------------------------------------------- /public/pokemon/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/14.jpg -------------------------------------------------------------------------------- /public/pokemon/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/15.jpg -------------------------------------------------------------------------------- /public/pokemon/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/16.jpg -------------------------------------------------------------------------------- /public/pokemon/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/17.jpg -------------------------------------------------------------------------------- /public/pokemon/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/18.jpg -------------------------------------------------------------------------------- /public/pokemon/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/19.jpg -------------------------------------------------------------------------------- /public/pokemon/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/20.jpg -------------------------------------------------------------------------------- /public/pokemon/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/21.jpg -------------------------------------------------------------------------------- /public/pokemon/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/22.jpg -------------------------------------------------------------------------------- /public/pokemon/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/23.jpg -------------------------------------------------------------------------------- /public/pokemon/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/24.jpg -------------------------------------------------------------------------------- /public/pokemon/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/25.jpg -------------------------------------------------------------------------------- /public/pokemon/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/26.jpg -------------------------------------------------------------------------------- /public/pokemon/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/27.jpg -------------------------------------------------------------------------------- /public/pokemon/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/28.jpg -------------------------------------------------------------------------------- /public/pokemon/30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/30.jpg -------------------------------------------------------------------------------- /public/pokemon/31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/31.jpg -------------------------------------------------------------------------------- /public/pokemon/33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/33.jpg -------------------------------------------------------------------------------- /public/pokemon/34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/34.jpg -------------------------------------------------------------------------------- /public/pokemon/35.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/35.jpg -------------------------------------------------------------------------------- /public/pokemon/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/36.jpg -------------------------------------------------------------------------------- /public/pokemon/37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/37.jpg -------------------------------------------------------------------------------- /public/pokemon/38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/38.jpg -------------------------------------------------------------------------------- /public/pokemon/39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/39.jpg -------------------------------------------------------------------------------- /public/pokemon/40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/40.jpg -------------------------------------------------------------------------------- /public/pokemon/41.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/41.jpg -------------------------------------------------------------------------------- /public/pokemon/42.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/42.jpg -------------------------------------------------------------------------------- /public/pokemon/43.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/43.jpg -------------------------------------------------------------------------------- /public/pokemon/44.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/44.jpg -------------------------------------------------------------------------------- /public/pokemon/45.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/xstate-pokemon-viewer/HEAD/public/pokemon/45.jpg -------------------------------------------------------------------------------- /public/pokemon/29.jpg: -------------------------------------------------------------------------------- 1 | 2 | 404 Not Found 3 | 4 |

404 Not Found

5 |
nginx/1.14.0 (Ubuntu)
6 | 7 | 8 | -------------------------------------------------------------------------------- /public/pokemon/32.jpg: -------------------------------------------------------------------------------- 1 | 2 | 404 Not Found 3 | 4 |

404 Not Found

5 |
nginx/1.14.0 (Ubuntu)
6 | 7 | 8 | -------------------------------------------------------------------------------- /public/pokemon/10.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 10, 3 | "name": "Caterpie", 4 | "type": [ 5 | "Bug" 6 | ], 7 | "hp": 45, 8 | "attack": 30, 9 | "defense": 35, 10 | "special_attack": 20, 11 | "special_defense": 20, 12 | "speed": 45 13 | } -------------------------------------------------------------------------------- /public/pokemon/11.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 11, 3 | "name": "Metapod", 4 | "type": [ 5 | "Bug" 6 | ], 7 | "hp": 50, 8 | "attack": 20, 9 | "defense": 55, 10 | "special_attack": 25, 11 | "special_defense": 25, 12 | "speed": 30 13 | } -------------------------------------------------------------------------------- /public/pokemon/19.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 19, 3 | "name": "Rattata", 4 | "type": [ 5 | "Normal" 6 | ], 7 | "hp": 30, 8 | "attack": 56, 9 | "defense": 35, 10 | "special_attack": 25, 11 | "special_defense": 35, 12 | "speed": 72 13 | } -------------------------------------------------------------------------------- /public/pokemon/20.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 20, 3 | "name": "Raticate", 4 | "type": [ 5 | "Normal" 6 | ], 7 | "hp": 55, 8 | "attack": 81, 9 | "defense": 60, 10 | "special_attack": 50, 11 | "special_defense": 70, 12 | "speed": 97 13 | } -------------------------------------------------------------------------------- /public/pokemon/23.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 23, 3 | "name": "Ekans", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 35, 8 | "attack": 60, 9 | "defense": 44, 10 | "special_attack": 40, 11 | "special_defense": 54, 12 | "speed": 55 13 | } -------------------------------------------------------------------------------- /public/pokemon/24.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 24, 3 | "name": "Arbok", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 60, 8 | "attack": 95, 9 | "defense": 69, 10 | "special_attack": 65, 11 | "special_defense": 79, 12 | "speed": 80 13 | } -------------------------------------------------------------------------------- /public/pokemon/29.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 29, 3 | "name": "Nidoran♀", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 55, 8 | "attack": 47, 9 | "defense": 52, 10 | "special_attack": 40, 11 | "special_defense": 40, 12 | "speed": 41 13 | } -------------------------------------------------------------------------------- /public/pokemon/30.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 30, 3 | "name": "Nidorina", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 70, 8 | "attack": 62, 9 | "defense": 67, 10 | "special_attack": 55, 11 | "special_defense": 55, 12 | "speed": 56 13 | } -------------------------------------------------------------------------------- /public/pokemon/32.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 32, 3 | "name": "Nidoran♂", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 46, 8 | "attack": 57, 9 | "defense": 40, 10 | "special_attack": 40, 11 | "special_defense": 40, 12 | "speed": 50 13 | } -------------------------------------------------------------------------------- /public/pokemon/33.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 33, 3 | "name": "Nidorino", 4 | "type": [ 5 | "Poison" 6 | ], 7 | "hp": 61, 8 | "attack": 72, 9 | "defense": 57, 10 | "special_attack": 55, 11 | "special_defense": 55, 12 | "speed": 65 13 | } -------------------------------------------------------------------------------- /public/pokemon/35.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 35, 3 | "name": "Clefairy", 4 | "type": [ 5 | "Fairy" 6 | ], 7 | "hp": 70, 8 | "attack": 45, 9 | "defense": 48, 10 | "special_attack": 60, 11 | "special_defense": 65, 12 | "speed": 35 13 | } -------------------------------------------------------------------------------- /public/pokemon/36.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 36, 3 | "name": "Clefable", 4 | "type": [ 5 | "Fairy" 6 | ], 7 | "hp": 95, 8 | "attack": 70, 9 | "defense": 73, 10 | "special_attack": 95, 11 | "special_defense": 90, 12 | "speed": 60 13 | } -------------------------------------------------------------------------------- /public/pokemon/37.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 37, 3 | "name": "Vulpix", 4 | "type": [ 5 | "Fire" 6 | ], 7 | "hp": 38, 8 | "attack": 41, 9 | "defense": 40, 10 | "special_attack": 50, 11 | "special_defense": 65, 12 | "speed": 65 13 | } -------------------------------------------------------------------------------- /public/pokemon/4.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 4, 3 | "name": "Charmander", 4 | "type": [ 5 | "Fire" 6 | ], 7 | "hp": 39, 8 | "attack": 52, 9 | "defense": 43, 10 | "special_attack": 60, 11 | "special_defense": 50, 12 | "speed": 65 13 | } -------------------------------------------------------------------------------- /public/pokemon/5.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 5, 3 | "name": "Charmeleon", 4 | "type": [ 5 | "Fire" 6 | ], 7 | "hp": 58, 8 | "attack": 64, 9 | "defense": 58, 10 | "special_attack": 80, 11 | "special_defense": 65, 12 | "speed": 80 13 | } -------------------------------------------------------------------------------- /public/pokemon/7.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 7, 3 | "name": "Squirtle", 4 | "type": [ 5 | "Water" 6 | ], 7 | "hp": 44, 8 | "attack": 48, 9 | "defense": 65, 10 | "special_attack": 50, 11 | "special_defense": 64, 12 | "speed": 43 13 | } -------------------------------------------------------------------------------- /public/pokemon/8.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 8, 3 | "name": "Wartortle", 4 | "type": [ 5 | "Water" 6 | ], 7 | "hp": 59, 8 | "attack": 63, 9 | "defense": 80, 10 | "special_attack": 65, 11 | "special_defense": 80, 12 | "speed": 58 13 | } -------------------------------------------------------------------------------- /public/pokemon/9.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 9, 3 | "name": "Blastoise", 4 | "type": [ 5 | "Water" 6 | ], 7 | "hp": 79, 8 | "attack": 83, 9 | "defense": 100, 10 | "special_attack": 85, 11 | "special_defense": 105, 12 | "speed": 78 13 | } -------------------------------------------------------------------------------- /public/pokemon/25.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 25, 3 | "name": "Pikachu", 4 | "type": [ 5 | "Electric" 6 | ], 7 | "hp": 35, 8 | "attack": 55, 9 | "defense": 40, 10 | "special_attack": 50, 11 | "special_defense": 50, 12 | "speed": 90 13 | } -------------------------------------------------------------------------------- /public/pokemon/26.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 26, 3 | "name": "Raichu", 4 | "type": [ 5 | "Electric" 6 | ], 7 | "hp": 60, 8 | "attack": 90, 9 | "defense": 55, 10 | "special_attack": 90, 11 | "special_defense": 80, 12 | "speed": 110 13 | } -------------------------------------------------------------------------------- /public/pokemon/27.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 27, 3 | "name": "Sandshrew", 4 | "type": [ 5 | "Ground" 6 | ], 7 | "hp": 50, 8 | "attack": 75, 9 | "defense": 85, 10 | "special_attack": 20, 11 | "special_defense": 30, 12 | "speed": 40 13 | } -------------------------------------------------------------------------------- /public/pokemon/28.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 28, 3 | "name": "Sandslash", 4 | "type": [ 5 | "Ground" 6 | ], 7 | "hp": 75, 8 | "attack": 100, 9 | "defense": 110, 10 | "special_attack": 45, 11 | "special_defense": 55, 12 | "speed": 65 13 | } -------------------------------------------------------------------------------- /public/pokemon/38.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 38, 3 | "name": "Ninetales", 4 | "type": [ 5 | "Fire" 6 | ], 7 | "hp": 73, 8 | "attack": 76, 9 | "defense": 75, 10 | "special_attack": 81, 11 | "special_defense": 100, 12 | "speed": 100 13 | } -------------------------------------------------------------------------------- /public/pokemon/13.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 13, 3 | "name": "Weedle", 4 | "type": [ 5 | "Bug", 6 | "Poison" 7 | ], 8 | "hp": 40, 9 | "attack": 35, 10 | "defense": 30, 11 | "special_attack": 20, 12 | "special_defense": 20, 13 | "speed": 50 14 | } -------------------------------------------------------------------------------- /public/pokemon/14.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 14, 3 | "name": "Kakuna", 4 | "type": [ 5 | "Bug", 6 | "Poison" 7 | ], 8 | "hp": 45, 9 | "attack": 25, 10 | "defense": 50, 11 | "special_attack": 25, 12 | "special_defense": 25, 13 | "speed": 35 14 | } -------------------------------------------------------------------------------- /public/pokemon/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 2, 3 | "name": "Ivysaur", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 60, 9 | "attack": 62, 10 | "defense": 63, 11 | "special_attack": 80, 12 | "special_defense": 80, 13 | "speed": 60 14 | } -------------------------------------------------------------------------------- /public/pokemon/44.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 44, 3 | "name": "Gloom", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 60, 9 | "attack": 65, 10 | "defense": 70, 11 | "special_attack": 85, 12 | "special_defense": 75, 13 | "speed": 40 14 | } -------------------------------------------------------------------------------- /public/pokemon/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "name": "Bulbasaur", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 45, 9 | "attack": 49, 10 | "defense": 49, 11 | "special_attack": 65, 12 | "special_defense": 65, 13 | "speed": 45 14 | } -------------------------------------------------------------------------------- /public/pokemon/12.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 12, 3 | "name": "Butterfree", 4 | "type": [ 5 | "Bug", 6 | "Flying" 7 | ], 8 | "hp": 60, 9 | "attack": 45, 10 | "defense": 50, 11 | "special_attack": 90, 12 | "special_defense": 80, 13 | "speed": 70 14 | } -------------------------------------------------------------------------------- /public/pokemon/15.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 15, 3 | "name": "Beedrill", 4 | "type": [ 5 | "Bug", 6 | "Poison" 7 | ], 8 | "hp": 65, 9 | "attack": 90, 10 | "defense": 40, 11 | "special_attack": 45, 12 | "special_defense": 80, 13 | "speed": 75 14 | } -------------------------------------------------------------------------------- /public/pokemon/16.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 16, 3 | "name": "Pidgey", 4 | "type": [ 5 | "Normal", 6 | "Flying" 7 | ], 8 | "hp": 40, 9 | "attack": 45, 10 | "defense": 40, 11 | "special_attack": 35, 12 | "special_defense": 35, 13 | "speed": 56 14 | } -------------------------------------------------------------------------------- /public/pokemon/17.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 17, 3 | "name": "Pidgeotto", 4 | "type": [ 5 | "Normal", 6 | "Flying" 7 | ], 8 | "hp": 63, 9 | "attack": 60, 10 | "defense": 55, 11 | "special_attack": 50, 12 | "special_defense": 50, 13 | "speed": 71 14 | } -------------------------------------------------------------------------------- /public/pokemon/18.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 18, 3 | "name": "Pidgeot", 4 | "type": [ 5 | "Normal", 6 | "Flying" 7 | ], 8 | "hp": 83, 9 | "attack": 80, 10 | "defense": 75, 11 | "special_attack": 70, 12 | "special_defense": 70, 13 | "speed": 101 14 | } -------------------------------------------------------------------------------- /public/pokemon/21.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 21, 3 | "name": "Spearow", 4 | "type": [ 5 | "Normal", 6 | "Flying" 7 | ], 8 | "hp": 40, 9 | "attack": 60, 10 | "defense": 30, 11 | "special_attack": 31, 12 | "special_defense": 31, 13 | "speed": 70 14 | } -------------------------------------------------------------------------------- /public/pokemon/22.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 22, 3 | "name": "Fearow", 4 | "type": [ 5 | "Normal", 6 | "Flying" 7 | ], 8 | "hp": 65, 9 | "attack": 90, 10 | "defense": 65, 11 | "special_attack": 61, 12 | "special_defense": 61, 13 | "speed": 100 14 | } -------------------------------------------------------------------------------- /public/pokemon/3.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 3, 3 | "name": "Venusaur", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 80, 9 | "attack": 82, 10 | "defense": 83, 11 | "special_attack": 100, 12 | "special_defense": 100, 13 | "speed": 80 14 | } -------------------------------------------------------------------------------- /public/pokemon/31.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 31, 3 | "name": "Nidoqueen", 4 | "type": [ 5 | "Poison", 6 | "Ground" 7 | ], 8 | "hp": 90, 9 | "attack": 92, 10 | "defense": 87, 11 | "special_attack": 75, 12 | "special_defense": 85, 13 | "speed": 76 14 | } -------------------------------------------------------------------------------- /public/pokemon/34.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 34, 3 | "name": "Nidoking", 4 | "type": [ 5 | "Poison", 6 | "Ground" 7 | ], 8 | "hp": 81, 9 | "attack": 102, 10 | "defense": 77, 11 | "special_attack": 85, 12 | "special_defense": 75, 13 | "speed": 85 14 | } -------------------------------------------------------------------------------- /public/pokemon/41.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 41, 3 | "name": "Zubat", 4 | "type": [ 5 | "Poison", 6 | "Flying" 7 | ], 8 | "hp": 40, 9 | "attack": 45, 10 | "defense": 35, 11 | "special_attack": 30, 12 | "special_defense": 40, 13 | "speed": 55 14 | } -------------------------------------------------------------------------------- /public/pokemon/42.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 42, 3 | "name": "Golbat", 4 | "type": [ 5 | "Poison", 6 | "Flying" 7 | ], 8 | "hp": 75, 9 | "attack": 80, 10 | "defense": 70, 11 | "special_attack": 65, 12 | "special_defense": 75, 13 | "speed": 90 14 | } -------------------------------------------------------------------------------- /public/pokemon/43.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 43, 3 | "name": "Oddish", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 45, 9 | "attack": 50, 10 | "defense": 55, 11 | "special_attack": 75, 12 | "special_defense": 65, 13 | "speed": 30 14 | } -------------------------------------------------------------------------------- /public/pokemon/45.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 45, 3 | "name": "Vileplume", 4 | "type": [ 5 | "Grass", 6 | "Poison" 7 | ], 8 | "hp": 75, 9 | "attack": 80, 10 | "defense": 85, 11 | "special_attack": 110, 12 | "special_defense": 90, 13 | "speed": 50 14 | } -------------------------------------------------------------------------------- /public/pokemon/6.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 6, 3 | "name": "Charizard", 4 | "type": [ 5 | "Fire", 6 | "Flying" 7 | ], 8 | "hp": 78, 9 | "attack": 84, 10 | "defense": 78, 11 | "special_attack": 109, 12 | "special_defense": 85, 13 | "speed": 100 14 | } -------------------------------------------------------------------------------- /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'; 6 | -------------------------------------------------------------------------------- /public/pokemon/39.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 39, 3 | "name": "Jigglypuff", 4 | "type": [ 5 | "Normal", 6 | "Fairy" 7 | ], 8 | "hp": 115, 9 | "attack": 45, 10 | "defense": 20, 11 | "special_attack": 45, 12 | "special_defense": 25, 13 | "speed": 20 14 | } -------------------------------------------------------------------------------- /public/pokemon/40.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 40, 3 | "name": "Wigglytuff", 4 | "type": [ 5 | "Normal", 6 | "Fairy" 7 | ], 8 | "hp": 140, 9 | "attack": 70, 10 | "defense": 45, 11 | "special_attack": 85, 12 | "special_defense": 50, 13 | "speed": 45 14 | } -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /public/pages/4.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageCount": 5, 3 | "list": [ 4 | { 5 | "id": 41, 6 | "name": "Zubat" 7 | }, 8 | { 9 | "id": 42, 10 | "name": "Golbat" 11 | }, 12 | { 13 | "id": 43, 14 | "name": "Oddish" 15 | }, 16 | { 17 | "id": 44, 18 | "name": "Gloom" 19 | }, 20 | { 21 | "id": 45, 22 | "name": "Vileplume" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /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/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .app { 2 | margin-top: 2rem; 3 | } 4 | .container { 5 | max-width: 960px; 6 | margin: 0 auto; 7 | display: grid; 8 | grid-template-columns: 1fr 2fr 1fr; 9 | gap: 1rem; 10 | } 11 | 12 | .parameter { 13 | font-weight: bolder; 14 | } 15 | 16 | .value-grid { 17 | display: grid; 18 | grid-template-columns: 1fr 1fr; 19 | column-gap: 1rem; 20 | } 21 | 22 | .pokemon-image { 23 | max-height: 300px; 24 | } 25 | 26 | .pages { 27 | margin-top: 1rem; 28 | } -------------------------------------------------------------------------------- /src/pokemonViewer.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "PokemonViewer", 3 | "initial": "getPokemonList", 4 | "states": { 5 | "getPokemonList": { 6 | "invoke": { 7 | "src": "fetchCurrentPage", 8 | "onDone": [ 9 | { 10 | "actions": "savePokemonList", 11 | "target": "showPokemonList" 12 | } 13 | ], 14 | "onError": [ 15 | { 16 | "target": "showError" 17 | } 18 | ] 19 | } 20 | }, 21 | "showPokemonList": {}, 22 | "showError": {} 23 | } 24 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /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/pages/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageCount": 5, 3 | "list": [ 4 | { 5 | "id": 21, 6 | "name": "Spearow" 7 | }, 8 | { 9 | "id": 22, 10 | "name": "Fearow" 11 | }, 12 | { 13 | "id": 23, 14 | "name": "Ekans" 15 | }, 16 | { 17 | "id": 24, 18 | "name": "Arbok" 19 | }, 20 | { 21 | "id": 25, 22 | "name": "Pikachu" 23 | }, 24 | { 25 | "id": 26, 26 | "name": "Raichu" 27 | }, 28 | { 29 | "id": 27, 30 | "name": "Sandshrew" 31 | }, 32 | { 33 | "id": 28, 34 | "name": "Sandslash" 35 | }, 36 | { 37 | "id": 29, 38 | "name": "Nidoran♀" 39 | }, 40 | { 41 | "id": 30, 42 | "name": "Nidorina" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /public/pages/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageCount": 5, 3 | "list": [ 4 | { 5 | "id": 11, 6 | "name": "Metapod" 7 | }, 8 | { 9 | "id": 12, 10 | "name": "Butterfree" 11 | }, 12 | { 13 | "id": 13, 14 | "name": "Weedle" 15 | }, 16 | { 17 | "id": 14, 18 | "name": "Kakuna" 19 | }, 20 | { 21 | "id": 15, 22 | "name": "Beedrill" 23 | }, 24 | { 25 | "id": 16, 26 | "name": "Pidgey" 27 | }, 28 | { 29 | "id": 17, 30 | "name": "Pidgeotto" 31 | }, 32 | { 33 | "id": 18, 34 | "name": "Pidgeot" 35 | }, 36 | { 37 | "id": 19, 38 | "name": "Rattata" 39 | }, 40 | { 41 | "id": 20, 42 | "name": "Raticate" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /public/pages/0.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageCount": 5, 3 | "list": [ 4 | { 5 | "id": 1, 6 | "name": "Bulbasaur" 7 | }, 8 | { 9 | "id": 2, 10 | "name": "Ivysaur" 11 | }, 12 | { 13 | "id": 3, 14 | "name": "Venusaur" 15 | }, 16 | { 17 | "id": 4, 18 | "name": "Charmander" 19 | }, 20 | { 21 | "id": 5, 22 | "name": "Charmeleon" 23 | }, 24 | { 25 | "id": 6, 26 | "name": "Charizard" 27 | }, 28 | { 29 | "id": 7, 30 | "name": "Squirtle" 31 | }, 32 | { 33 | "id": 8, 34 | "name": "Wartortle" 35 | }, 36 | { 37 | "id": 9, 38 | "name": "Blastoise" 39 | }, 40 | { 41 | "id": 10, 42 | "name": "Caterpie" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /public/pages/3.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageCount": 5, 3 | "list": [ 4 | { 5 | "id": 31, 6 | "name": "Nidoqueen" 7 | }, 8 | { 9 | "id": 32, 10 | "name": "Nidoran♂" 11 | }, 12 | { 13 | "id": 33, 14 | "name": "Nidorino" 15 | }, 16 | { 17 | "id": 34, 18 | "name": "Nidoking" 19 | }, 20 | { 21 | "id": 35, 22 | "name": "Clefairy" 23 | }, 24 | { 25 | "id": 36, 26 | "name": "Clefable" 27 | }, 28 | { 29 | "id": 37, 30 | "name": "Vulpix" 31 | }, 32 | { 33 | "id": 38, 34 | "name": "Ninetales" 35 | }, 36 | { 37 | "id": 39, 38 | "name": "Jigglypuff" 39 | }, 40 | { 41 | "id": 40, 42 | "name": "Wigglytuff" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pokemon-viewer", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.14.1", 7 | "@testing-library/react": "^13.0.0", 8 | "@testing-library/user-event": "^13.2.1", 9 | "@xstate/react": "^3.0.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-scripts": "5.0.1", 13 | "web-vitals": "^2.1.0", 14 | "xstate": "^4.31.0" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 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 | } 41 | -------------------------------------------------------------------------------- /src/Components.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const PokemonList = ({ pokemonList, onClick }) => 4 | (pokemonList ?? []).map((p) => ( 5 |
6 | { 9 | evt.preventDefault(); 10 | onClick(p.id); 11 | }} 12 | > 13 | {p.name} 14 | 15 |
16 | )); 17 | 18 | export const Pages = ({ pageCount, onClick }) => ( 19 |
20 | Page:{" "} 21 | {new Array(pageCount ?? 0).fill(0).map((_, i) => ( 22 | 23 | {i > 0 && " "} 24 | { 27 | evt.preventDefault(); 28 | onClick(i); 29 | }} 30 | > 31 | {i + 1} 32 | 33 | 34 | ))} 35 |
36 | ); 37 | 38 | export const Pokemon = ({ pokemon }) => 39 | pokemon && ( 40 |
41 | {Object.entries(pokemon).map(([key, value]) => ( 42 | 43 |
{key}
44 |
{Array.isArray(value) ? value.join(", ") : value}
45 |
46 | ))} 47 |
48 | ); 49 | 50 | export const PokemonImage = ({ pokemon }) => 51 | pokemon && ( 52 | {pokemon.name} 57 | ); 58 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useMachine } from "@xstate/react"; 3 | 4 | import { PokemonImage, Pokemon, PokemonList, Pages } from "./Components"; 5 | import pokemonViewerMachine from "./pokemonViewerMachine"; 6 | 7 | import "./App.css"; 8 | 9 | function App() { 10 | const [ 11 | { 12 | value, 13 | context: { pageCount, pokemonList, selectedPokemon }, 14 | }, 15 | send, 16 | ] = useMachine(pokemonViewerMachine); 17 | const error = value === "showError"; 18 | const setCurrentPage = () => {}; 19 | 20 | return ( 21 |
22 | {error &&
We encountered an error. Please try again later.
} 23 | {!error && ( 24 |
25 |
26 | { 29 | send({ 30 | type: "SET_SELECTED_POKEMON_ID", 31 | id, 32 | }); 33 | }} 34 | /> 35 | 38 | send({ 39 | type: "SET_CURRENT_PAGE", 40 | page, 41 | }) 42 | } 43 | /> 44 |
45 |
46 | 47 |
48 |
49 | 50 |
51 |
52 | )} 53 |
54 | ); 55 | } 56 | 57 | export default App; 58 | -------------------------------------------------------------------------------- /src/usePokemon.js: -------------------------------------------------------------------------------- 1 | import { useReducer, useEffect, useCallback } from "react"; 2 | 3 | export const usePokemon = () => { 4 | const [state, dispatch] = useReducer( 5 | (originalState, stateUpdate) => ({ 6 | ...originalState, 7 | ...stateUpdate, 8 | }), 9 | { 10 | error: null, 11 | currentPage: 0, 12 | pageCount: 0, 13 | pokemonList: [], 14 | selectedPokemon: null, 15 | selectedPokemonID: null, 16 | } 17 | ); 18 | 19 | useEffect(() => { 20 | dispatch({ selectedPokemon: null }); 21 | fetch(`/pages/${state.currentPage}.json`) 22 | .then((res) => res.json()) 23 | .then(({ pageCount, list }) => { 24 | dispatch({ pageCount, pokemonList: list }); 25 | }) 26 | .catch(() => dispatch({ error: true })); 27 | }, [state.currentPage]); 28 | 29 | useEffect(() => { 30 | dispatch({ selectedPokemon: null }); 31 | if (state.selectedPokemonID) { 32 | fetch(`/pokemon/${state.selectedPokemonID}.json`) 33 | .then((res) => res.json()) 34 | .then((selectedPokemon) => dispatch({ selectedPokemon })) 35 | .catch(() => dispatch({ error: true })); 36 | } 37 | }, [state.selectedPokemonID]); 38 | 39 | const setCurrentPage = useCallback( 40 | (currentPage) => dispatch({ currentPage }), 41 | [] 42 | ); 43 | const setSelectedPokemonID = useCallback( 44 | (selectedPokemonID) => dispatch({ selectedPokemonID }), 45 | [] 46 | ); 47 | 48 | return { 49 | error: state.error, 50 | pageCount: state.pageCount, 51 | setCurrentPage, 52 | pokemonList: state.pokemonList, 53 | setSelectedPokemonID, 54 | selectedPokemon: state.selectedPokemon, 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | 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. 37 | 38 | 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. 39 | 40 | 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. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /src/pokemonViewerMachine.js: -------------------------------------------------------------------------------- 1 | import { createMachine } from "xstate"; 2 | 3 | export default /** @xstate-layout N4IgpgJg5mDOIC5QAUD2BrMBbVA7AagJZgDuYATgHQwAuamOuAMobDQMQR5iWG4BuGHvWx4ipCtTB0hjFmwR9BAYwCGNQngDaABgC6iUAAdUsQhryGQAD0QBaACwBmJ5QAcLnQFY3DgEwAjE4OAGwA7AA0IACe9gFhrn5+TgCcLiFJGX4ODgC+uVEijOJkVLRFePIcFOSoVEYANuoAZnVYlBUExKVSMgyVrDSKAqhqFri6BkggJmbjVrYIdiEpOpSpYQ5eIRkhDmEpUbFLwZQpDm5eAaF+KclOHvmFsmLdkrAAFqgknVXsAMoAUQAKgB9IFMQEAYWBgIAIqDkAB5ADSgIAskiAHKggCScKss3MmlwCzibjc6z8lwC2x0bj8VwyR3spwOOzCYRCHgS2SeIE6JUk5ReuE43F4I0wHVFQrK0k6wxU6hJk0JpmJlmmi2urh5-h0YQCjJSXicLIQYS8lDCSQCAR0hr8CR0yX5gre8r6ojFNTqlEaLTaMv6XQkXsVSlGKu0+nVcxJZKWOQclC8yQCKwpOhS8QCFtNlEC-jcOhCwW2jJC7tlnson2+nQBIPBgMhMPhiNRGOxeIJ0yJ821cTZKTcKW56YOhq2FoCKRSaZ013TqVz+z5BQFtfDzbBUIAqgAlI+ArFg5AAQQA4oD45rScOluFU5nTeWnA67uaYvZnYuwldFw-BzICQi8fIt1wVAIDgKwPXDXpfkGe8h1ARY7CNAJKH2TNth2DwaQtOwAkuG1nXiDxDXApwa1DOV6y+H5RSqVDEyfRxbkoHRP3LecrVNc4HGIhxsK2bIkjuLxnFpFI6J9BiGxIQFyFqcg2K1dD7BWVMnHAhwyy2Wl4hCC0rncZc3BCe1OSNUs3Hk4o6xFUMNMfLSlmuAC9h4tIPCcHx0wtcsi1Iy4rXZYJHQgrcEJ6JTOjcpN4j8birJSW1SOdHIvAtQJUouDKnCNHivEdJw-Ec15wySjiEmtXDwJ2bkHiuYi9NTFYKvnVZpLcIJINyIA */ 4 | createMachine( 5 | { 6 | on: { 7 | SET_CURRENT_PAGE: { 8 | actions: "saveCurrentPage", 9 | target: ".getPokemonList", 10 | }, 11 | }, 12 | id: "PokemonViewer", 13 | initial: "getPokemonList", 14 | states: { 15 | getPokemonList: { 16 | invoke: { 17 | src: "fetchCurrentPage", 18 | onDone: [ 19 | { 20 | actions: "savePokemonList", 21 | target: "showPokemonList", 22 | }, 23 | ], 24 | onError: [ 25 | { 26 | target: "showError", 27 | }, 28 | ], 29 | }, 30 | }, 31 | showPokemonList: { 32 | on: { 33 | SET_SELECTED_POKEMON_ID: { 34 | actions: "saveSelectedPokemonID", 35 | target: "getPokemon", 36 | }, 37 | }, 38 | }, 39 | showError: {}, 40 | getPokemon: { 41 | invoke: { 42 | src: "getSelectedPokemon", 43 | onDone: [ 44 | { 45 | actions: "savePokemon", 46 | target: "showPokemon", 47 | }, 48 | ], 49 | onError: [ 50 | { 51 | target: "showError", 52 | }, 53 | ], 54 | }, 55 | }, 56 | showPokemon: { 57 | on: { 58 | SET_SELECTED_POKEMON_ID: { 59 | actions: "saveSelectedPokemonID", 60 | target: "getPokemon", 61 | }, 62 | }, 63 | }, 64 | }, 65 | }, 66 | { 67 | context: { 68 | pageCount: 0, 69 | pokemonList: [], 70 | currentPage: 0, 71 | selectedPokemonID: null, 72 | selectedPokemon: null, 73 | }, 74 | actions: { 75 | saveCurrentPage: (context, event) => { 76 | context.currentPage = event.page; 77 | context.selectedPokemon = null; 78 | context.selectedPokemonID = null; 79 | }, 80 | savePokemon: (context, event) => { 81 | context.selectedPokemon = event.data; 82 | }, 83 | saveSelectedPokemonID: (context, event) => { 84 | context.selectedPokemonID = event.id; 85 | }, 86 | savePokemonList: (context, event) => { 87 | context.pokemonList = event.data.list; 88 | context.pageCount = event.data.pageCount; 89 | }, 90 | }, 91 | services: { 92 | getSelectedPokemon: (context) => 93 | fetch(`/pokemon/${context.selectedPokemonID}.json`).then((res) => 94 | res.json() 95 | ), 96 | fetchCurrentPage: (context) => 97 | fetch(`/pages/${context.currentPage ?? 0}.json`).then((res) => 98 | res.json() 99 | ), 100 | }, 101 | } 102 | ); 103 | --------------------------------------------------------------------------------